@linkurious/ogma-annotations 2.1.2 → 2.1.4

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,1913 +1,285 @@
1
- import { BBox } from 'geojson';
2
- import { default as default_2 } from 'eventemitter3';
3
- import { Feature } from 'geojson';
4
- import { FeatureCollection } from 'geojson';
5
- import { Geometry } from 'geojson';
6
- import { GeometryObject } from 'geojson';
7
- import { LineString } 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
- import { Position } from 'geojson';
14
- import { Size } from '@linkurious/ogma';
15
-
16
- /**
17
- * Adjusts the brightness of a color (hex or rgba) based on its perceived luminance.
18
- * For bright colors, the adjustment is applied as darkening; for dark colors, as lightening.
19
- *
20
- * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
21
- * @param amount - Adjustment factor between -1 and 1:
22
- * - Positive values (0 to 1): lighten dark colors, darken bright colors
23
- * - Negative values (-1 to 0): darken dark colors, lighten bright colors
24
- * - 0: no change
25
- * - Example: 0.2 applies a 20% adjustment, -0.1 applies a -10% adjustment
26
- * @returns Adjusted color in rgba format
27
- */
28
- export declare function adjustColorBrightness(color: Color, amount: number): RgbaColor;
29
-
30
- /** Union type of all Annotation features */
31
- export declare type Annotation = Arrow | Box | Text_2 | Comment_2 | Polygon;
32
-
33
- /** Collection of Annotations, GeoJSON FeatureCollection */
34
- export declare interface AnnotationCollection extends FeatureCollection {
35
- features: Annotation[];
36
- }
37
-
38
- /**
39
- * Base interface for all annotation features.
40
- * @template G - Geometry type
41
- * @template P - Properties type
42
- */
43
- export declare interface AnnotationFeature<G extends GeometryObject = GeometryObject, P = AnnotationProps> extends Feature<G, P> {
44
- /** Unique identifier for the annotation */
45
- id: Id;
46
- }
47
-
48
- /** Function type to get an Annotation by its id */
49
- export declare type AnnotationGetter = (id: Id) => Annotation | undefined;
50
-
51
- export declare type AnnotationOptions = {
52
- handleSize: number;
53
- placeholder?: string;
54
- };
55
-
56
- /**
57
- * Base properties for all annotations.
58
- */
59
- export declare interface AnnotationProps {
60
- /** Type of annotation */
61
- type: AnnotationType;
62
- /** Optional style configuration */
63
- style?: unknown;
64
- }
65
-
66
- /** Types of annotations supported */
67
- export declare type AnnotationType = "arrow" | "text" | "box" | "comment" | "polygon";
68
-
69
- /**
70
- * Arrow annotation feature. Represents a directed line between two points,
71
- * can connect a textbox to a shape.
72
- */
73
- export declare interface Arrow extends AnnotationFeature<LineString, ArrowProperties> {
74
- }
75
-
76
- export declare interface ArrowProperties extends AnnotationProps {
77
- type: "arrow";
78
- style?: ArrowStyles;
79
- link?: Partial<Record<Side, ExportedLink>>;
80
- }
81
-
82
- /**
83
- * Styles specific to arrow annotations.
84
- */
85
- export declare interface ArrowStyles extends StrokeOptions {
86
- /** Tail extremity style */
87
- tail?: Extremity;
88
- /** Head extremity style */
89
- head?: Extremity;
90
- }
91
-
92
- /**
93
- * Safely cast a string to a Color type with runtime validation
94
- * @throws {Error} if the color format is invalid
95
- */
96
- export declare function asColor(color: string): Color;
97
-
98
- /**
99
- * Safely cast a string to a HexColor type with runtime validation
100
- * @throws {Error} if the color format is invalid
101
- */
102
- export declare function asHexColor(color: string): HexColor;
103
-
104
- /**
105
- * Safely cast a string to an RgbaColor type with runtime validation
106
- * @throws {Error} if the color format is invalid
107
- */
108
- export declare function asRgbaColor(color: string): RgbaColor;
109
-
110
- /**
111
- * Safely cast a string to an RgbColor type with runtime validation
112
- * @throws {Error} if the color format is invalid
113
- */
114
- export declare function asRgbColor(color: string): RgbColor;
115
-
116
- /**
117
- * Bounding box object, with the following properties:
118
- * - [0]: min x
119
- * - [1]: min y
120
- * - [2]: max x
121
- * - [3]: max y
122
- */
123
- export declare type Bounds = [number, number, number, number];
124
-
125
- /**
126
- * Box annotation feature
127
- */
128
- export declare interface Box extends AnnotationFeature<Point_2, BoxProperties> {
129
- }
130
-
131
- /**
132
- * Arrow snapped to a rectangular annotation (text, box, comment).
133
- * nx/ny are center-relative fractions multiplied by width/height:
134
- * left-center = { nx: -0.5, ny: 0 }
135
- * right-center = { nx: 0.5, ny: 0 }
136
- * center = { nx: 0, ny: 0 }
137
- */
138
- export declare type BoxMagnet = {
139
- type: "box";
140
- nx: number;
141
- ny: number;
142
- };
143
-
144
- /** Properties specific to box annotations. */
145
- export declare interface BoxProperties extends AnnotationProps {
146
- type: "box";
147
- /** Width of the box */
148
- width: number;
149
- /** Height of the box */
150
- height: number;
151
- /** Style options for the box */
152
- style?: BoxStyle;
153
- }
154
-
155
- /** Styles specific to box annotations. */
156
- export declare interface BoxStyle extends StrokeOptions {
157
- /** background color: empty for transparent #f00, yellow...*/
158
- background?: Color;
159
- /** padding around the box */
160
- padding?: number;
161
- /** border radius */
162
- borderRadius?: number;
163
- /** if true, the box scales with zoom. Default is true */
164
- scaled?: boolean;
165
- /** box shadow in CSS format, e.g. "0px 4px 6px rgba(0, 0, 0, 0.1)" */
166
- boxShadow?: string;
167
- }
168
-
169
- /**
170
- * Brighten a color for highlight purposes.
171
- * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
172
- * @returns
173
- */
174
- export declare const brighten: (color: Color) => RgbaColor;
175
-
176
- /**
177
- * Move `el` to the end of `root`'s children. SVG paint order is DOM order,
178
- * so this is how a shape gets raised to the top of its group. Safe to call
179
- * every render even when `el` is already last - `appendChild` on an
180
- * existing child just re-positions it, it doesn't clone or re-trigger
181
- * insertion.
182
- */
183
- export declare function bringToTop(root: Element, el: Element): void;
184
-
185
- /**
186
- * Calculate optimal zoom threshold for auto-collapse based on comment dimensions
187
- *
188
- * The threshold is computed so that the comment collapses when its screen-space
189
- * size would be smaller than a minimum readable size.
190
- *
191
- * @param comment - Comment annotation
192
- * @param minReadableWidth - Minimum readable width in pixels (default: 80)
193
- * @returns Zoom threshold below which comment should collapse
194
- *
195
- * @example
196
- * // A 200px wide comment with minReadable=80 will collapse at zoom < 0.4
197
- * // because 200 * 0.4 = 80
198
- */
199
- export declare function calculateCommentZoomThreshold(comment: Comment_2, minReadableWidth?: number): number;
200
-
201
- /**
202
- * Check if arrow endpoint can be detached from its target
203
- *
204
- * Always returns true since arrow endpoints can be freely retargeted,
205
- * even for comment arrows. The comment is typically on the start side.
206
- *
207
- * @param _arrow - The arrow feature (unused, kept for API consistency)
208
- * @returns Always true - arrow ends can be detached
209
- *
210
- * @example
211
- * ```typescript
212
- * if (canDetachArrowEnd(arrow)) {
213
- * // Allow user to drag arrow end point
214
- * }
215
- * ```
216
- */
217
- export declare function canDetachArrowEnd(_arrow: Arrow): boolean;
218
-
219
- /**
220
- * Check if arrow start point can be detached from its source
221
- *
222
- * Returns false for arrows originating FROM comments, since comment arrows
223
- * must always remain attached to the comment on their start side.
224
- *
225
- * @param arrow - The arrow feature
226
- * @returns True if arrow start can be detached
227
- *
228
- * @example
229
- * ```typescript
230
- * if (canDetachArrowStart(arrow)) {
231
- * // Allow user to drag arrow start point
232
- * } else {
233
- * // Keep arrow start locked to comment
234
- * }
235
- * ```
236
- */
237
- export declare function canDetachArrowStart(arrow: Arrow): boolean;
238
-
239
- /** Event related to a single annotation feature */
240
- export declare interface ClickEvent {
241
- /** Annotation ID involved in the event */
242
- id?: Id;
243
- /** Mouse position in pixel coordinates */
244
- position: {
245
- x: number;
246
- y: number;
247
- };
248
- }
249
-
250
- export declare type ClientMouseEvent = {
251
- clientX: number;
252
- clientY: number;
253
- };
254
-
255
- export declare function clientToContainerPosition(evt: ClientMouseEvent, container?: HTMLElement | null): {
256
- x: number;
257
- y: number;
258
- };
259
-
260
- /**
261
- * Any valid color format
262
- */
263
- export declare type Color = HexColor | RgbColor | RgbaColor | "transparent" | "none" | string;
264
-
265
- export declare function colorToRgba(color: Color, alpha: number): RgbaColor;
266
-
267
- /**
268
- * Comment annotation type
269
- * Geometry: Point (center position of comment box/icon)
270
- *
271
- * Note: Arrows are stored separately in Arrow features.
272
- * Arrows reference comments via their link.start or link.end properties.
273
- */
274
- declare interface Comment_2 extends AnnotationFeature<Point_2, CommentProps> {
275
- }
276
- export { Comment_2 as Comment }
277
-
278
- export declare const COMMENT_MODE_COLLAPSED = "collapsed";
279
-
280
- export declare const COMMENT_MODE_EXPANDED = "expanded";
281
-
282
- /**
283
- * Properties for Comment annotations
284
- *
285
- * Comments are specialized annotations that:
286
- * - Always maintain fixed screen-space size
287
- * - Always have at least one arrow pointing TO them
288
- * - Can be collapsed (icon) or expanded (text box)
289
- * - Support multiple arrows pointing to them
290
- */
291
- export declare interface CommentProps extends AnnotationProps {
292
- type: "comment";
293
- /** Text content (similar to text annotation) */
294
- content: string;
295
- /** Display mode: collapsed (icon) or expanded (text box) */
296
- mode: typeof COMMENT_MODE_COLLAPSED | typeof COMMENT_MODE_EXPANDED;
297
- /** Width in expanded mode (pixels) */
298
- width: number;
299
- /** Height (auto-grows with content, pixels) */
300
- height: number;
301
- /** Optional metadata */
302
- author?: string;
303
- timestamp?: Date;
304
- /** Styling */
305
- style?: CommentStyle;
306
- }
307
-
308
- /**
309
- * Style configuration for Comment annotations
310
- */
311
- export declare interface CommentStyle extends TextStyle {
312
- /** Background color for collapsed icon (default: "#FFD700") */
313
- iconColor?: Color;
314
- /** Icon to display when collapsed (default: "💬") */
315
- iconSymbol?: string;
316
- /** Border color for collapsed icon */
317
- iconBorderColor?: Color;
318
- /** Border width for collapsed icon */
319
- iconBorderWidth?: number;
320
- /** Minimum height (default: 60px) */
321
- minHeight?: number;
322
- /** Maximum height before scrolling (default: 480px, undefined = no limit) */
323
- maxHeight?: number;
324
- /** Size when collapsed (default: 32px) */
325
- iconSize?: number;
326
- /** Zoom threshold below which comment auto-collapses (default: 0.5) */
327
- collapseZoomThreshold?: number;
328
- /** Show "send" button in edit mode (default: true) */
329
- showSendButton?: boolean;
330
- /** Auto-grow height with content (default: true) */
331
- autoGrow?: boolean;
332
- /** Show drop shadow on comment box (default: true) */
333
- shadow?: boolean;
334
- /** Expand to full width when selected (default: false) */
335
- expandOnSelect?: boolean;
336
- /**
337
- * Connector-line behavior when the attachment point moves (default: "rigid").
338
- * - "rigid": the comment translates by the same offset as the moved
339
- * attachment point — the arrow keeps its length/angle, whole callout moves.
340
- * - "elastic": the comment stays put; the arrow re-anchors to the nearest
341
- * point on the comment box, so the line can stretch/rotate.
342
- */
343
- connectorMode?: "rigid" | "elastic";
344
- }
345
-
346
- /**
347
- * Main controller class for managing annotations.
348
- * It manages rendering and editing of annotations.
349
- */
350
- export declare class Control extends default_2<FeatureEvents> {
351
- private ogma;
352
- private store;
353
- private renderers;
354
- private interactions;
355
- private editor;
356
- private links;
357
- private index;
358
- private drawing;
359
- private snapping;
360
- private selectionManager;
361
- private historyManager;
362
- private updateManager;
363
- private commentManager;
364
- constructor(ogma: Ogma, options?: Partial<ControllerOptions>);
365
- private initializeRenderers;
366
- private setupEvents;
367
- private onRotate;
368
- private onZoom;
369
- private onLayout;
370
- /**
371
- * Set the options for the controller
372
- * @param options new Options
373
- * @returns the updated options
374
- */
375
- setOptions(options?: Partial<ControllerOptions>): {
376
- showSendButton: boolean;
377
- showEditButton: boolean;
378
- sendButtonIcon: string;
379
- editButtonIcon: string;
380
- minArrowHeight: number;
381
- maxArrowHeight: number;
382
- detectMargin: number;
383
- magnetRadius: number;
384
- magnetHandleRadius: number;
385
- textPlaceholder: string;
386
- };
387
- /**
388
- * Add an annotation to the controller
389
- * @param annotation The annotation to add
390
- */
391
- add(annotation: Annotation | AnnotationCollection): this;
392
- /**
393
- * Remove an annotation or an array of annotations from the controller
394
- * @param annotation The annotation(s) to remove
395
- */
396
- remove(annotation: Annotation | AnnotationCollection): this;
397
- /**
398
- * Undo the last change
399
- * @returns true if undo was successful, false if no changes to undo
400
- */
401
- undo(): boolean;
402
- /**
403
- * Redo the last undone change
404
- * @returns true if redo was successful, false if no changes to redo
405
- */
406
- redo(): boolean;
407
- /**
408
- * Check if there are changes to undo
409
- * @returns true if undo is possible
410
- */
411
- canUndo(): boolean;
412
- /**
413
- * Check if there are changes to redo
414
- * @returns true if redo is possible
415
- */
416
- canRedo(): boolean;
417
- /**
418
- * Clear the undo/redo history
419
- */
420
- clearHistory(): void;
421
- /**
422
- * Get all annotations in the controller
423
- * @returns A FeatureCollection containing all annotations
424
- */
425
- getAnnotations(): AnnotationCollection;
426
- /**
427
- * Select one or more annotations by id
428
- * @param annotations The id(s) of the annotation(s) to select
429
- * @returns this for chaining
430
- */
431
- select(annotations: Id | Id[]): this;
432
- /**
433
- * Unselect one or more annotations, or all if no ids provided
434
- * @param annotations The id(s) of the annotation(s) to unselect, or undefined to unselect all
435
- * @returns this for chaining
436
- */
437
- unselect(annotations?: Id | Id[]): this;
438
- /**
439
- * Cancel the current drawing operation
440
- * @returns this for chaining
441
- */
442
- cancelDrawing(): this;
443
- /**
444
- * Enable arrow drawing mode - the recommended way to add arrows.
445
- *
446
- * Call this method when the user clicks an "Add Arrow" button. The control will:
447
- * 1. Wait for the next mousedown event
448
- * 2. Create an arrow at that position with the specified style
449
- * 3. Start the interactive drawing process
450
- * 4. Clean up automatically when done
451
- *
452
- * **This is the recommended API for 99% of use cases.** Only use `startArrow()`
453
- * if you need to implement custom mouse handling or positioning logic.
454
- *
455
- * @example
456
- * ```ts
457
- * addArrowButton.addEventListener('click', () => {
458
- * control.enableArrowDrawing({ strokeColor: '#3A03CF', strokeWidth: 2 });
459
- * });
460
- * ```
461
- *
462
- * @param style Arrow style options
463
- * @returns this for chaining
464
- * @see startArrow for low-level programmatic control
465
- */
466
- enableArrowDrawing(style?: Partial<Arrow["properties"]["style"]>): this;
467
- /**
468
- * Enable text drawing mode - the recommended way to add text annotations.
469
- *
470
- * Call this method when the user clicks an "Add Text" button. The control will:
471
- * 1. Wait for the next mousedown event
472
- * 2. Create a text box at that position with the specified style
473
- * 3. Start the interactive drawing/editing process
474
- * 4. Clean up automatically when done
475
- *
476
- * **This is the recommended API for 99% of use cases.** Only use `startText()`
477
- * if you need to implement custom mouse handling or positioning logic.
478
- *
479
- * @example
480
- * ```ts
481
- * addTextButton.addEventListener('click', () => {
482
- * control.enableTextDrawing({ color: '#3A03CF', fontSize: 24 });
483
- * });
484
- * ```
485
- *
486
- * @param style Text style options
487
- * @returns this for chaining
488
- * @see startText for low-level programmatic control
489
- */
490
- enableTextDrawing(style?: Partial<Text_2["properties"]["style"]>): this;
491
- /**
492
- * Enable box drawing mode - the recommended way to add boxes.
493
- *
494
- * Call this method when the user clicks an "Add Box" button. The control will:
495
- * 1. Wait for the next mousedown event
496
- * 2. Create a box at that position with the specified style
497
- * 3. Start the interactive drawing process (drag to size)
498
- * 4. Clean up automatically when done
499
- *
500
- * **This is the recommended API for 99% of use cases.** Only use `startBox()`
501
- * if you need to implement custom mouse handling or positioning logic.
502
- *
503
- * @example
504
- * ```ts
505
- * addBoxButton.addEventListener('click', () => {
506
- * control.enableBoxDrawing({ background: '#EDE6FF', borderRadius: 8 });
507
- * });
508
- * ```
509
- *
510
- * @param style Box style options
511
- * @returns this for chaining
512
- * @see startBox for low-level programmatic control
513
- */
514
- enableBoxDrawing(style?: Partial<Box["properties"]["style"]>): this;
515
- /**
516
- * Enable polygon drawing mode - the recommended way to add polygons.
517
- *
518
- * Call this method when the user clicks an "Add Polygon" button. The control will:
519
- * 1. Wait for the next mousedown event
520
- * 2. Create a polygon starting at that position with the specified style
521
- * 3. Start the interactive drawing process (click points to draw shape)
522
- * 4. Clean up automatically when done
523
- *
524
- * **This is the recommended API for 99% of use cases.** Only use `startPolygon()`
525
- * if you need to implement custom mouse handling or positioning logic.
526
- *
527
- * @example
528
- * ```ts
529
- * addPolygonButton.addEventListener('click', () => {
530
- * control.enablePolygonDrawing({ strokeColor: '#3A03CF', background: 'rgba(58, 3, 207, 0.15)' });
531
- * });
532
- * ```
533
- *
534
- * @param style Polygon style options
535
- * @returns this for chaining
536
- * @see startPolygon for low-level programmatic control
537
- */
538
- enablePolygonDrawing(style?: Partial<Polygon["properties"]["style"]>): this;
539
- /**
540
- * Enable comment drawing mode - the recommended way to add comments.
541
- *
542
- * Call this method when the user clicks an "Add Comment" button. The control will:
543
- * 1. Wait for the next mousedown event
544
- * 2. Create a comment with an arrow pointing to that position
545
- * 3. Smart positioning: automatically finds the best placement for the comment box
546
- * 4. Start the interactive editing process
547
- * 5. Clean up automatically when done
548
- *
549
- * **This is the recommended API for 99% of use cases.** Only use `startComment()`
550
- * if you need to implement custom mouse handling or positioning logic.
551
- *
552
- * @example
553
- * ```ts
554
- * addCommentButton.addEventListener('click', () => {
555
- * control.enableCommentDrawing({
556
- * commentStyle: { color: '#3A03CF', background: '#EDE6FF' },
557
- * arrowStyle: { strokeColor: '#3A03CF', head: 'halo-dot' }
558
- * });
559
- * });
560
- * ```
561
- *
562
- * @param options Drawing options including offsets and styles
563
- * @param options.offsetX Manual X offset for comment placement (overrides smart positioning)
564
- * @param options.offsetY Manual Y offset for comment placement (overrides smart positioning)
565
- * @param options.commentStyle Style options for the comment box
566
- * @param options.arrowStyle Style options for the arrow
567
- * @returns this for chaining
568
- * @see startComment for low-level programmatic control
569
- */
570
- enableCommentDrawing(options?: {
571
- offsetX?: number;
572
- offsetY?: number;
573
- commentStyle?: Partial<CommentProps>;
574
- arrowStyle?: Partial<ArrowProperties>;
575
- }): this;
576
- /**
577
- * Enable sticky note drawing mode - drops a plain, resizable text box
578
- * (empty content, "Quick note…" ghost placeholder, no connector arrow)
579
- * like a Miro sticky note, unlike `enableCommentDrawing`. It's a regular
580
- * `text` annotation, so it's placed the same interactive way as
581
- * `enableBoxDrawing`/`enableTextDrawing`: click for a default-size square,
582
- * or drag to size it - either way it keeps the usual corner/edge drag
583
- * handles to resize it afterward.
584
- *
585
- * Call this method when the user clicks an "Add sticky note" button. The
586
- * control will:
587
- * 1. Wait for the next mousedown event
588
- * 2. Create the note at that position and start the interactive
589
- * corner-drag, already selected
590
- * 3. On release: a plain click (no drag) gets a default square size, a
591
- * drag gets sized to match instead - either way it drops straight
592
- * into editing (the placeholder is just ghost text, so typing
593
- * immediately replaces it)
594
- * 4. Clean up automatically when done
595
- *
596
- * @example
597
- * ```ts
598
- * addStickyNoteButton.addEventListener('click', () => {
599
- * control.enableStickyNoteDrawing({ background: '#FFEB99' });
600
- * });
601
- * ```
602
- *
603
- * @param style Sticky note style options (merged over the sticky note defaults)
604
- * @returns this for chaining
605
- * @see startStickyNote for low-level programmatic control
606
- */
607
- enableStickyNoteDrawing(style?: Partial<Text_2["properties"]["style"]>): this;
608
- /**
609
- * Enable erase mode: every click on an annotation deletes it immediately.
610
- * Stays armed across multiple clicks until `disableEraseMode()` is called,
611
- * or another drawing tool is enabled / `cancelDrawing()` is called.
612
- *
613
- * @returns this for chaining
614
- * @see disableEraseMode to turn erase mode off
615
- */
616
- enableEraseMode(): this;
617
- /** Turn erase mode off. No-op if it isn't active. */
618
- disableEraseMode(): this;
619
- /** Whether erase mode is currently active. */
620
- isEraseModeActive(): boolean;
621
- /**
622
- * Place a pre-created annotation by moving it with the cursor.
623
- * The annotation follows the mouse until the user clicks to place it.
624
- * Press Escape to cancel.
625
- *
626
- * @param annotation The text or box annotation to place
627
- * @returns this for chaining
628
- */
629
- enablePlacement(annotation: Text_2 | Box): this;
630
- /**
631
- * **Advanced API:** Programmatically start drawing a comment at specific coordinates.
632
- *
633
- * This is a low-level method that gives you full control over the drawing process.
634
- * You must handle mouse events and create the comment object yourself.
635
- *
636
- * **For most use cases, use `enableCommentDrawing()` instead** - it handles all
637
- * mouse events and annotation creation automatically.
638
- *
639
- * Use this method only when you need:
640
- * - Custom mouse event handling (e.g., custom cursors, right-click menus)
641
- * - Programmatic placement without user interaction
642
- * - Integration with custom UI frameworks
643
- *
644
- * @example
645
- * ```ts
646
- * // Custom cursor example
647
- * ogma.setOptions({ cursor: { default: 'crosshair' } });
648
- * ogma.events.once('mousedown', (evt) => {
649
- * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
650
- * const comment = createComment(x, y, 'My comment', { color: '#3A03CF' });
651
- * control.startComment(x, y, comment);
652
- * });
653
- * ```
654
- *
655
- * @param x X coordinate to start drawing
656
- * @param y Y coordinate to start drawing
657
- * @param comment The comment annotation to add
658
- * @param options Drawing options including offsets and styles
659
- * @returns this for chaining
660
- * @see enableCommentDrawing for the recommended high-level API
661
- */
662
- startComment(x: number, y: number, comment: Comment_2, options?: {
663
- offsetX?: number;
664
- offsetY?: number;
665
- commentStyle?: Partial<CommentProps>;
666
- arrowStyle?: Partial<ArrowProperties>;
667
- }): this;
668
- /**
669
- * **Advanced API:** Programmatically start drawing a sticky note at
670
- * specific coordinates - same interactive corner-drag as `startBox`.
671
- * You must handle mouse events yourself (or immediately release/complete
672
- * it via the same events `enableStickyNoteDrawing` would).
673
- *
674
- * **For most use cases, use `enableStickyNoteDrawing()` instead.**
675
- *
676
- * @param x X coordinate for the note's top-left corner
677
- * @param y Y coordinate for the note's top-left corner
678
- * @param style Sticky note style options
679
- * @returns this for chaining
680
- * @see enableStickyNoteDrawing for the recommended high-level API
681
- */
682
- startStickyNote(x: number, y: number, style?: Partial<Text_2["properties"]["style"]>): this;
683
- /**
684
- * **Advanced API:** Programmatically start drawing a box at specific coordinates.
685
- *
686
- * This is a low-level method that gives you full control over the drawing process.
687
- * You must handle mouse events and optionally create the box object yourself.
688
- *
689
- * **For most use cases, use `enableBoxDrawing()` instead** - it handles all
690
- * mouse events and annotation creation automatically.
691
- *
692
- * Use this method only when you need:
693
- * - Custom mouse event handling (e.g., custom cursors, right-click menus)
694
- * - Programmatic placement without user interaction
695
- * - Integration with custom UI frameworks
696
- *
697
- * @example
698
- * ```ts
699
- * // Custom cursor example
700
- * ogma.setOptions({ cursor: { default: 'crosshair' } });
701
- * ogma.events.once('mousedown', (evt) => {
702
- * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
703
- * const box = createBox(x, y, 100, 50, { background: '#EDE6FF' });
704
- * control.startBox(x, y, box);
705
- * });
706
- * ```
707
- *
708
- * @param x X coordinate for the box origin
709
- * @param y Y coordinate for the box origin
710
- * @param box The box annotation to add (optional, will be created if not provided)
711
- * @returns this for chaining
712
- * @see enableBoxDrawing for the recommended high-level API
713
- */
714
- startBox(x: number, y: number, box?: Box): this;
715
- /**
716
- * **Advanced API:** Programmatically start drawing an arrow at specific coordinates.
717
- *
718
- * This is a low-level method that gives you full control over the drawing process.
719
- * You must handle mouse events and optionally create the arrow object yourself.
720
- *
721
- * **For most use cases, use `enableArrowDrawing()` instead** - it handles all
722
- * mouse events and annotation creation automatically.
723
- *
724
- * Use this method only when you need:
725
- * - Custom mouse event handling (e.g., custom cursors, right-click menus)
726
- * - Programmatic placement without user interaction
727
- * - Integration with custom UI frameworks
728
- *
729
- * @example
730
- * ```ts
731
- * // Custom cursor example
732
- * ogma.setOptions({ cursor: { default: 'crosshair' } });
733
- * ogma.events.once('mousedown', (evt) => {
734
- * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
735
- * const arrow = createArrow(x, y, x, y, { strokeColor: '#3A03CF' });
736
- * control.startArrow(x, y, arrow);
737
- * });
738
- * ```
739
- *
740
- * @param x X coordinate for the arrow start
741
- * @param y Y coordinate for the arrow start
742
- * @param arrow The arrow annotation to add (optional, will be created if not provided)
743
- * @returns this for chaining
744
- * @see enableArrowDrawing for the recommended high-level API
745
- */
746
- startArrow(x: number, y: number, arrow?: Arrow): this;
747
- /**
748
- * **Advanced API:** Programmatically start drawing a text annotation at specific coordinates.
749
- *
750
- * This is a low-level method that gives you full control over the drawing process.
751
- * You must handle mouse events and optionally create the text object yourself.
752
- *
753
- * **For most use cases, use `enableTextDrawing()` instead** - it handles all
754
- * mouse events and annotation creation automatically.
755
- *
756
- * Use this method only when you need:
757
- * - Custom mouse event handling (e.g., custom cursors, right-click menus)
758
- * - Programmatic placement without user interaction
759
- * - Integration with custom UI frameworks
760
- *
761
- * @example
762
- * ```ts
763
- * // Custom cursor example
764
- * ogma.setOptions({ cursor: { default: 'crosshair' } });
765
- * ogma.events.once('mousedown', (evt) => {
766
- * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
767
- * const text = createText(x, y, 0, 0, 'Hello', { color: '#3A03CF' });
768
- * control.startText(x, y, text);
769
- * });
770
- * ```
771
- *
772
- * @param x X coordinate for the text
773
- * @param y Y coordinate for the text
774
- * @param text The text annotation to add (optional, will be created if not provided)
775
- * @returns this for chaining
776
- * @see enableTextDrawing for the recommended high-level API
777
- */
778
- startText(x: number, y: number, text?: Text_2): this;
779
- /**
780
- * **Advanced API:** Programmatically start drawing a polygon at specific coordinates.
781
- *
782
- * This is a low-level method that gives you full control over the drawing process.
783
- * You must handle mouse events and create the polygon object yourself.
784
- *
785
- * **For most use cases, use `enablePolygonDrawing()` instead** - it handles all
786
- * mouse events and annotation creation automatically.
787
- *
788
- * Use this method only when you need:
789
- * - Custom mouse event handling (e.g., custom cursors, right-click menus)
790
- * - Programmatic placement without user interaction
791
- * - Integration with custom UI frameworks
792
- *
793
- * @example
794
- * ```ts
795
- * // Custom cursor example
796
- * ogma.setOptions({ cursor: { default: 'crosshair' } });
797
- * ogma.events.once('mousedown', (evt) => {
798
- * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
799
- * const polygon = createPolygon([[[x, y]]], { strokeColor: '#3A03CF' });
800
- * control.startPolygon(x, y, polygon);
801
- * });
802
- * ```
803
- *
804
- * @param x X coordinate to start drawing
805
- * @param y Y coordinate to start drawing
806
- * @param polygon The polygon annotation to add
807
- * @returns this for chaining
808
- * @see enablePolygonDrawing for the recommended high-level API
809
- */
810
- startPolygon(x: number, y: number, polygon: Polygon): this;
811
- /**
812
- * Get the currently selected annotations as a collection
813
- * @returns A FeatureCollection of selected annotations
814
- */
815
- getSelectedAnnotations(): AnnotationCollection;
816
- /**
817
- * Get the first selected annotation (for backwards compatibility)
818
- * @returns The currently selected annotation, or null if none selected
819
- */
820
- getSelected(): Annotation | null;
821
- /**
822
- * Get a specific annotation by id
823
- * @param id The id of the annotation to retrieve
824
- * @returns The annotation with the given id, or undefined if not found
825
- */
826
- getAnnotation<T = Annotation>(id: Id): T | undefined;
827
- /**
828
- * Scale an annotation by a given factor around an origin point
829
- * @param id The id of the annotation to scale
830
- * @param scale The scale factor
831
- * @param ox Origin x coordinate
832
- * @param oy Origin y coordinate
833
- * @returns this for chaining
834
- */
835
- setScale(id: Id, scale: number, ox: number, oy: number): this;
836
- /**
837
- * Toggle a comment between collapsed and expanded mode
838
- * @param id The id of the comment to toggle
839
- * @returns this for chaining
840
- */
841
- toggleComment(id: Id): this;
842
- /**
843
- * Destroy the controller and its elements
844
- */
845
- destroy(): void;
846
- /**
847
- * Update the style of the annotation with the given id
848
- * @param id The id of the annotation to update
849
- * @param style The new style
850
- */
851
- updateStyle<A extends Annotation>(id: Id, style: A["properties"]["style"]): this;
852
- /**
853
- * Update an annotation with partial updates
854
- *
855
- * This method allows you to update any properties of an annotation, including
856
- * geometry, properties, and style. Updates are merged with existing data.
857
- *
858
- * @param annotation Partial annotation object with id and properties to update
859
- * @returns this for chaining
860
- *
861
- * @example
862
- * ```ts
863
- * // Update arrow geometry
864
- * controller.update({
865
- * id: arrowId,
866
- * geometry: {
867
- * type: 'LineString',
868
- * coordinates: [[0, 0], [200, 200]]
869
- * }
870
- * });
871
- *
872
- * // Update text content and position
873
- * controller.update({
874
- * id: textId,
875
- * geometry: {
876
- * type: 'Point',
877
- * coordinates: [100, 100]
878
- * },
879
- * properties: {
880
- * content: 'Updated text'
881
- * }
882
- * });
883
- *
884
- * // Update style only (prefer updateStyle for style-only updates)
885
- * controller.update({
886
- * id: boxId,
887
- * properties: {
888
- * style: {
889
- * background: '#ff0000'
890
- * }
891
- * }
892
- * });
893
- * ```
894
- */
895
- update<A extends Annotation>(annotation: DeepPartial<A> & {
896
- id: Id;
897
- }): this;
898
- /**
899
- * Attach an arrow to a node at the specified side
900
- * @param arrowId
901
- * @param targetNode
902
- * @param side
903
- */
904
- link(arrowId: Id, targetNode: Node_2, side: Side): this;
905
- /**
906
- * Attach an arrow to an annotation at the specified side
907
- * @param arrowId
908
- * @param target
909
- * @param side
910
- */
911
- link(arrowId: Id, target: Id, side: Side): this;
912
- isDrawing(): boolean;
913
- }
914
-
915
- /**
916
- * Options for the annotations control
917
- */
918
- export declare type ControllerOptions = {
919
- /**
920
- * The radius in which arrows are attracted
921
- */
922
- magnetRadius: number;
923
- /**
924
- * The margin in which the Texts are detected when looking for magnet points
925
- */
926
- detectMargin: number;
927
- /**
928
- * Display size of the magnet point
929
- */
930
- magnetHandleRadius: number;
931
- /**
932
- * Placeholder for the text input
933
- */
934
- textPlaceholder: string;
935
- /**
936
- * Show send button in text editor
937
- */
938
- showSendButton: boolean;
939
- /**
940
- * Show edit button in text editor
941
- */
942
- showEditButton: boolean;
943
- /**
944
- * SVG icon for the send button in text editor
945
- * Should be a complete SVG string (e.g., '<svg>...</svg>')
946
- */
947
- sendButtonIcon: string;
948
- /**
949
- * SVG icon for the edit button in text editor
950
- * Should be a complete SVG string (e.g., '<svg>...</svg>')
951
- */
952
- editButtonIcon: string;
953
- /**
954
- * Minimum height of the arrow in units
955
- */
956
- minArrowHeight: number;
957
- /**
958
- * Maximum height of the arrow in units
959
- */
960
- maxArrowHeight: number;
961
- };
962
-
963
- export declare const createArrow: (x0?: number, y0?: number, x1?: number, y1?: number, styles?: {
964
- /** Tail extremity style */
965
- tail?: Extremity | undefined;
966
- /** Head extremity style */
967
- head?: Extremity | undefined;
968
- strokeType?: StrokeType | undefined;
969
- strokeColor?: string | undefined;
970
- strokeWidth?: number | undefined;
971
- }) => Arrow;
972
-
973
- export declare const createBox: (x?: number, y?: number, width?: number, height?: number, styles?: Partial<BoxStyle>) => Box;
974
-
975
- /**
976
- * Create a new Comment annotation
977
- *
978
- * @param x - X coordinate of the comment box/icon center
979
- * @param y - Y coordinate of the comment box/icon center
980
- * @param content - Text content
981
- * @param options - Optional configuration
982
- * @returns New Comment feature
983
- *
984
- * @important This creates ONLY the comment box without an arrow. Since comments
985
- * require at least one arrow, you should use {@link createCommentWithArrow}
986
- * instead for programmatic creation. This function is primarily used internally
987
- * by the interactive drawing handlers.
988
- *
989
- * @see createCommentWithArrow for creating comments programmatically
990
- */
991
- export declare function createComment(x: number, y: number, content: string, options?: Partial<CommentProps>): Comment_2;
992
-
993
- /**
994
- * Create a comment with an arrow pointing to a target location
995
- *
996
- * This is the recommended way to create comments programmatically, as it ensures
997
- * that the comment always has at least one arrow (which is required).
998
- *
999
- * @param targetX - X coordinate where the arrow points to
1000
- * @param targetY - Y coordinate where the arrow points to
1001
- * @param commentX - X coordinate of the comment box center
1002
- * @param commentY - Y coordinate of the comment box center
1003
- * @param content - Text content of the comment
1004
- * @param options - Optional configuration
1005
- * @param options.commentStyle - Style options for the comment
1006
- * @param options.arrowStyle - Style options for the arrow
1007
- * @returns Object containing the comment and arrow features
1008
- *
1009
- * @example
1010
- * ```typescript
1011
- * import { createCommentWithArrow } from '@linkurious/ogma-annotations';
1012
- *
1013
- * // Create a comment pointing to a node at (100, 100)
1014
- * const { comment, arrow } = createCommentWithArrow(
1015
- * 100, 100, // Target position (where arrow points)
1016
- * 300, 50, // Comment position
1017
- * "Important node!", // Comment text
1018
- * {
1019
- * commentStyle: {
1020
- * style: {
1021
- * background: "#FFFACD",
1022
- * color: "#333"
1023
- * }
1024
- * },
1025
- * arrowStyle: {
1026
- * strokeColor: "#3498db",
1027
- * strokeWidth: 2,
1028
- * head: "arrow"
1029
- * }
1030
- * }
1031
- * );
1032
- *
1033
- * // Add both to the controller
1034
- * controller.add(comment);
1035
- * controller.add(arrow);
1036
- *
1037
- * // The arrow is automatically linked to the comment
1038
- * ```
1039
- */
1040
- export declare function createCommentWithArrow(targetX: number, targetY: number, commentX: number, commentY: number, content?: string, options?: {
1041
- commentStyle?: Partial<CommentProps>;
1042
- arrowStyle?: Partial<ArrowStyles>;
1043
- }): {
1044
- comment: Comment_2;
1045
- arrow: Arrow;
1046
- };
1047
-
1048
- /**
1049
- * Create a polygon annotation
1050
- */
1051
- export declare function createPolygon(coordinates: [number, number][][], properties?: Partial<Omit<PolygonProperties, "type">> & {
1052
- id?: Id;
1053
- }): Polygon;
1054
-
1055
- /** @private */
1056
- export declare function createSVGElement<T extends SVGElement>(tag: string): T;
1057
-
1058
- export declare const createText: (x?: number, y?: number, width?: number, height?: number, content?: string, styles?: Partial<TextStyle>) => Text_2;
1059
-
1060
- /** @private */
1061
- 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";
1062
-
1063
- /** @private */
1064
- export declare const cursors: Record<string, Cursor>;
1065
-
1066
- /**
1067
- * Darken a color for highlight purposes.
1068
- * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
1069
- * @returns
1070
- */
1071
- export declare const darken: (color: Color) => RgbaColor;
1072
-
1073
- export declare const DATA_ATTR = "data-annotation";
1074
-
1075
- /** @private */
1076
- export declare const debounce: <F extends (...args: Parameters<F>) => ReturnType<F>>(func: F, waitFor: number) => (...args: Parameters<F>) => void;
1077
-
1078
- /** @private */
1079
- export declare function debounceTail<T, A extends unknown[]>(fn: (this: T, ...args: A) => void, delay: number): (this: T, ...args: A) => void;
1080
-
1081
- export declare type DeepPartial<T> = {
1082
- [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
1083
- };
1084
-
1085
- 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";
1086
-
1087
- /** Default send button icon (paper plane) */
1088
- 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>";
1089
-
1090
- /**
1091
- * Default options for creating new Arrow annotations.
1092
- * Contains the default arrow structure with {@link defaultArrowStyle}.
1093
- */
1094
- export declare const defaultArrowOptions: Arrow;
1095
-
1096
- /**
1097
- * Default style configuration for arrow annotations.
1098
- *
1099
- * @example
1100
- * ```typescript
1101
- * {
1102
- * strokeType: "plain",
1103
- * strokeColor: "#202020",
1104
- * strokeWidth: 1,
1105
- * head: "none",
1106
- * tail: "none"
1107
- * }
1108
- * ```
1109
- */
1110
- export declare const defaultArrowStyle: ArrowStyles;
1111
-
1112
- /**
1113
- * Default options for creating new Box annotations.
1114
- * Contains the default box structure with {@link defaultBoxStyle}.
1115
- */
1116
- export declare const defaultBoxOptions: Box;
1117
-
1118
- /**
1119
- * Default style configuration for box annotations.
1120
- *
1121
- * @example
1122
- * ```typescript
1123
- * {
1124
- * background: "#f5f5f5",
1125
- * strokeWidth: 0,
1126
- * borderRadius: 8,
1127
- * padding: 16,
1128
- * strokeType: "plain"
1129
- * }
1130
- * ```
1131
- */
1132
- export declare const defaultBoxStyle: BoxStyle;
1133
-
1134
- /**
1135
- * Default options for creating new Comments.
1136
- * Contains the default comment configuration with {@link defaultCommentStyle}.
1137
- *
1138
- * @example
1139
- * ```typescript
1140
- * {
1141
- * mode: "expanded",
1142
- * width: 200,
1143
- * height: 120,
1144
- * content: "",
1145
- * style: defaultCommentStyle
1146
- * }
1147
- * ```
1148
- */
1149
- export declare const defaultCommentOptions: Partial<CommentProps>;
1150
-
1151
- /**
1152
- * Default style for Comment annotations
1153
- *
1154
- * @example
1155
- * ```typescript
1156
- * {
1157
- * // Box styling
1158
- * background: "#FFFACD", // Light yellow (sticky note color)
1159
- * padding: 8,
1160
- * borderRadius: 4,
1161
- * strokeColor: "#DDD",
1162
- * strokeWidth: 1,
1163
- * strokeType: "plain",
1164
- *
1165
- * // Icon styling (collapsed mode)
1166
- * iconColor: "#FFCB2F", // Gold
1167
- * iconSymbol: "💬",
1168
- * iconBorderColor: "#aaa",
1169
- * iconBorderWidth: 2,
1170
- *
1171
- * // Size properties
1172
- * minHeight: 60,
1173
- * iconSize: 32,
1174
- *
1175
- * // Text styling
1176
- * color: "#333",
1177
- * font: "Arial, sans-serif",
1178
- * fontSize: 12,
1179
- *
1180
- * // Editing UI
1181
- * showSendButton: true,
1182
- * autoGrow: true,
1183
- *
1184
- * // Visual effects
1185
- * shadow: true,
1186
- * expandOnSelect: false,
1187
- *
1188
- * // Fixed size (always screen-aligned)
1189
- * fixedSize: true
1190
- * }
1191
- * ```
1192
- */
1193
- export declare const defaultCommentStyle: CommentStyle;
1194
-
1195
- /**
1196
- * Default polygon properties for creating new Polygon annotations.
1197
- * Contains the default polygon configuration with {@link defaultPolygonStyle}.
1198
- */
1199
- export declare const defaultPolygonProperties: PolygonProperties;
1200
-
1201
- /**
1202
- * Default style configuration for polygon annotations.
1203
- *
1204
- * @example
1205
- * ```typescript
1206
- * {
1207
- * background: "transparent",
1208
- * strokeWidth: 2,
1209
- * borderRadius: 8,
1210
- * padding: 16,
1211
- * strokeType: "plain",
1212
- * strokeColor: "#000000"
1213
- * }
1214
- * ```
1215
- */
1216
- export declare const defaultPolygonStyle: PolygonStyle;
1217
-
1218
- /**
1219
- * Default options for creating new Text annotations.
1220
- * Contains the default text structure with {@link defaultTextStyle}.
1221
- */
1222
- export declare const defaultTextOptions: Text_2;
1223
-
1224
- /**
1225
- * Default style configuration for text annotations.
1226
- *
1227
- * @example
1228
- * ```typescript
1229
- * {
1230
- * font: "sans-serif",
1231
- * fontSize: 18,
1232
- * color: "#505050",
1233
- * background: "#f5f5f5",
1234
- * strokeWidth: 0,
1235
- * borderRadius: 8,
1236
- * padding: 16,
1237
- * strokeType: "plain",
1238
- * fixedSize: false
1239
- * }
1240
- * ```
1241
- */
1242
- export declare const defaultTextStyle: TextStyle;
1243
-
1244
- /**
1245
- * @private
1246
- * @param a Arrow annotation
1247
- * @param point Point to test
1248
- * @param threshold Detection threshold
1249
- * @returns True if the point is on the arrow line within the given threshold
1250
- */
1251
- export declare function detectArrow(a: Arrow, point: Point_3, threshold: number): boolean;
1252
-
1253
- /** @private */
1254
- export declare function detectBox(a: Box, p: Point, sin?: number, cos?: number, threshold?: number): boolean;
1255
-
1256
- /**
1257
- * Detect if a point is within a comment's bounds
1258
- * @private
1259
- * @param comment - Comment to test
1260
- * @param point - Point to test
1261
- * @param threshold - Detection threshold in pixels
1262
- * @param zoom - Current zoom level
1263
- * @returns True if point is within comment bounds
1264
- */
1265
- export declare function detectComment(comment: Comment_2, point: Point, threshold: number | undefined, sin: number, cos: number, zoom?: number): boolean;
1266
-
1267
- /**
1268
- * Point-in-polygon detection using ray casting algorithm
1269
- * @private
1270
- * @param polygon The polygon annotation
1271
- * @param point The point to test
1272
- * @param threshold Detection threshold in pixels
1273
- * @return True if the point is inside the polygon or within the threshold distance from its edges
1274
- */
1275
- export declare function detectPolygon(polygon: Polygon, point: Point, threshold?: number): boolean;
1276
-
1277
- /**
1278
- * Detects whether a point is within a text annotation's bounds.
1279
- * @private
1280
- * @param a Text annotation
1281
- * @param p Point to test
1282
- * @param threshold Detection threshold
1283
- * @param sin Rotation sine
1284
- * @param cos Rotation cosine
1285
- * @param zoom Current zoom level
1286
- * @returns True if the point is within the text bounds, false otherwise
1287
- */
1288
- export declare function detectText(a: Text_2, p: Point, threshold?: number, sin?: number, cos?: number, zoom?: number): boolean;
1289
-
1290
- /** Event related to a single annotation feature */
1291
- declare interface DragEvent_2 {
1292
- /** Annotation ID involved in the event */
1293
- id: Id;
1294
- /** Current mouse position in pixel coordinates during the drag */
1295
- position: {
1296
- x: number;
1297
- y: number;
1298
- };
1299
- }
1300
- export { DragEvent_2 as DragEvent }
1301
-
1302
- /** Arrow snapped at parametric position t (0–1) along an edge path. */
1303
- export declare type EdgeMagnet = {
1304
- type: "edge";
1305
- t: number;
1306
- };
1307
-
1308
- export declare const EVT_ADD = "add";
1309
-
1310
- export declare const EVT_CANCEL_DRAWING = "cancelDrawing";
1311
-
1312
- export declare const EVT_CLICK = "click";
1313
-
1314
- export declare const EVT_COMPLETE_DRAWING = "completeDrawing";
1315
-
1316
- export declare const EVT_DRAG = "dragging";
1317
-
1318
- export declare const EVT_DRAG_END = "dragend";
1319
-
1320
- export declare const EVT_DRAG_START = "dragstart";
1321
-
1322
- export declare const EVT_HISTORY = "history";
1323
-
1324
- export declare const EVT_HOVER = "hover";
1325
-
1326
- export declare const EVT_LINK = "link";
1327
-
1328
- export declare const EVT_REMOVE = "remove";
1329
-
1330
- export declare const EVT_SELECT = "select";
1331
-
1332
- export declare const EVT_UNHOVER = "unhover";
1333
-
1334
- export declare const EVT_UNSELECT = "unselect";
1335
-
1336
- export declare const EVT_UPDATE = "update";
1337
-
1338
- /**
1339
- * Serialized link stored inside arrow.properties.link.
1340
- * Uses plain { x, y } for backward compatibility with saved annotations.
1341
- * Converted to the internal Magnet type by Links.add().
1342
- */
1343
- export declare type ExportedLink = {
1344
- id: Id;
1345
- side: Side;
1346
- type: TargetType;
1347
- magnet?: Point;
1348
- };
1349
-
1350
- /** Extremity types for arrow annotations. */
1351
- export declare type Extremity = "none" | "arrow" | "arrow-plain" | "dot" | "halo-dot";
1352
-
1353
- /** Event related to a single annotation feature */
1354
- export declare interface FeatureEvent {
1355
- /** Annotation ID involved in the event */
1356
- id: Id;
1357
- }
1358
-
1359
- export declare type FeatureEvents = {
1360
- /**
1361
- * Event trigerred when selecting an annotation
1362
- * @param evt The annotation selected
1363
- */
1364
- [EVT_SELECT]: (evt: FeaturesEvent) => void;
1365
- /**
1366
- * Event trigerred when unselecting an annotation
1367
- * @param evt The annotation unselected
1368
- */
1369
- [EVT_UNSELECT]: (evt: FeaturesEvent) => void;
1370
- /**
1371
- * Event trigerred when removing an annotation
1372
- * @param evt The annotation removed
1373
- */
1374
- [EVT_REMOVE]: (evt: FeatureEvent) => void;
1375
- /**
1376
- * Event trigerred when adding an annotation
1377
- * @param evt The annotation added
1378
- */
1379
- [EVT_ADD]: (evt: FeatureEvent) => void;
1380
- /**
1381
- * Event trigerred when canceling drawing mode
1382
- */
1383
- [EVT_CANCEL_DRAWING]: () => void;
1384
- /**
1385
- * Event trigerred when completing a drawing operation
1386
- * @param evt Contains the ID of the completed annotation
1387
- */
1388
- [EVT_COMPLETE_DRAWING]: (evt: FeatureEvent) => void;
1389
- /**
1390
- * Event trigerred when updating an annotation.
1391
- * This fires after any modification including drag operations, style changes, scaling, etc.
1392
- * @param evt The updated annotation with all changes applied
1393
- */
1394
- [EVT_UPDATE]: (evt: Annotation) => void;
1395
- /**
1396
- * Event trigerred when linking an arrow to a node or annotation
1397
- * @param evt Contains the arrow and link details
1398
- */
1399
- [EVT_LINK]: (evt: {
1400
- arrow: Arrow;
1401
- link: Link;
1402
- }) => void;
1403
- /**
1404
- * Event trigerred when history state changes (after undo/redo operations)
1405
- * @param evt Contains boolean flags for undo/redo availability
1406
- */
1407
- [EVT_HISTORY]: (evt: HistoryEvent) => void;
1408
- /**
1409
- * Event triggered when a drag operation starts on an annotation
1410
- */
1411
- [EVT_DRAG_START]: (evt: DragEvent_2) => void;
1412
- /**
1413
- * Event triggered when a drag operation ends on an annotation
1414
- */
1415
- [EVT_DRAG_END]: (evt: DragEvent_2) => void;
1416
- /**
1417
- * Event triggered when a click completes on an annotation (mouseup without drag)
1418
- */
1419
- [EVT_CLICK]: (evt: ClickEvent) => void;
1420
- };
1421
-
1422
- /** Event related to multiple annotation features */
1423
- export declare interface FeaturesEvent {
1424
- /** Annotation IDs involved in the event */
1425
- ids: Id[];
1426
- }
1427
-
1428
- /**
1429
- * Calculate the bounds of a collection of annotations
1430
- * @param annotations
1431
- * @returns Bounds [minX, minY, maxX, maxY]
1432
- */
1433
- export declare function getAnnotationsBounds(annotations: AnnotationCollection): Bounds;
1434
-
1435
- export declare function getArrowEnd(a: Arrow): {
1436
- x: number;
1437
- y: number;
1438
- };
1439
-
1440
- export declare function getArrowEndPoints(a: Arrow): {
1441
- start: {
1442
- x: number;
1443
- y: number;
1444
- };
1445
- end: {
1446
- x: number;
1447
- y: number;
1448
- };
1449
- };
1450
-
1451
- export declare function getArrowSide(a: Arrow, side: Side): {
1452
- x: number;
1453
- y: number;
1454
- };
1455
-
1456
- export declare function getArrowStart(a: Arrow): {
1457
- x: number;
1458
- y: number;
1459
- };
1460
-
1461
- export declare function getAttachmentPointOnNode(start: Point_3, nodeCenter: Point_3, nodeRadius: number): {
1462
- x: number;
1463
- y: number;
1464
- };
1465
-
1466
- declare function getBbox<T extends Annotation>(b: T): BBox;
1467
- export { getBbox }
1468
- export { getBbox as getTextBbox }
1469
-
1470
- export declare function getBoxCenter<T extends Annotation>(t: T): {
1471
- x: number;
1472
- y: number;
1473
- };
1474
-
1475
- declare function getBoxPosition<T extends Annotation>(t: T, fixedSize?: boolean, zoom?: number): {
1476
- x: number;
1477
- y: number;
1478
- };
1479
- export { getBoxPosition }
1480
- export { getBoxPosition as getTextPosition }
1481
-
1482
- declare function getBoxSize<T extends Annotation>(t: T): {
1483
- width: number;
1484
- height: number;
1485
- };
1486
- export { getBoxSize }
1487
- export { getBoxSize as getTextSize }
1488
-
1489
- /** @private */
1490
- export declare function getBrowserWindow(): HTMLElement | undefined;
1491
-
1492
- /**
1493
- * Ids that removing `id` should take with it: `id` itself, plus every arrow
1494
- * attached to it when it's a comment or text annotation - deleting the
1495
- * anchor takes its connectors along, since a detached comment-arrow has
1496
- * nothing to point at.
1497
- *
1498
- * @param features - The full feature map (pre-deletion)
1499
- * @param id - The id being removed
1500
- * @returns The complete set of ids to delete
1501
- */
1502
- export declare function getCascadeDeleteIds(features: Record<Id, Annotation>, id: Id): Set<Id>;
1503
-
1504
- /**
1505
- * Comments must always keep at least one arrow. Returns the comment's id
1506
- * when deleting `arrowId` would leave it with none, so the caller can block
1507
- * the deletion instead - or `null` when it's safe to proceed.
1508
- *
1509
- * @param features - The full feature map (pre-deletion)
1510
- * @param arrowId - The arrow being removed
1511
- */
1512
- export declare function getCommentLeftOrphanedBy(features: Record<Id, Annotation>, arrowId: Id): Id | null;
1513
-
1514
- /**
1515
- * Get the id of the comment an arrow is connected to, if any.
1516
- *
1517
- * A comment is one visual annotation together with the arrow that connects
1518
- * it - callers that raise a comment's z-order (e.g. bringing a newly
1519
- * created/selected comment to the front) should raise this arrow along with
1520
- * it, not just the comment bubble.
1521
- *
1522
- * @param arrow - The arrow feature to check
1523
- * @returns The linked comment's id, or undefined if the arrow isn't attached
1524
- * to a comment
1525
- */
1526
- export declare function getCommentLinkId(arrow: Arrow): Id | undefined;
1527
-
1528
- /**
1529
- * Get the position (center) of a comment
1530
- *
1531
- * @param comment - Comment annotation
1532
- * @returns Center position
1533
- */
1534
- export declare function getCommentPosition(comment: Comment_2): Point;
1535
-
1536
- /**
1537
- * Get the dimensions of a comment based on its mode
1538
- *
1539
- * @param comment - Comment annotation
1540
- * @returns Width and height
1541
- */
1542
- export declare function getCommentSize(comment: Comment_2): Size;
1543
-
1544
- /**
1545
- * Get the effective zoom threshold for a comment
1546
- * Uses explicit threshold if set, otherwise calculates from dimensions
1547
- *
1548
- * @param comment - Comment annotation
1549
- * @returns Effective zoom threshold
1550
- */
1551
- export declare function getCommentZoomThreshold(comment: Comment_2): number;
1552
-
1553
- export declare function getCoordinates(geojson: Feature | FeatureCollection | Geometry): Position[];
1554
-
1555
- export declare const getHandleId: (handle: HTMLDivElement) => number;
1556
-
1557
- /**
1558
- * Get bounding box of a polygon
1559
- */
1560
- export declare function getPolygonBounds(polygon: Polygon): Bounds;
1561
-
1562
- /**
1563
- * Get centroid (geometric center) of a polygon
1564
- */
1565
- export declare function getPolygonCenter(polygon: Polygon): Point;
1566
-
1567
- export declare const handleDetectionThreshold = 5;
1568
-
1569
- export declare const handleRadius = 3;
1570
-
1571
- /**
1572
- * Hex color string in format #RGB or #RRGGBB
1573
- * @example "#fff" | "#ffffff" | "#F0A" | "#FF00AA"
1574
- */
1575
- export declare type HexColor = `#${string}`;
1576
-
1577
- export declare function hexShortToLong(color: HexColor): HexColor;
1578
-
1579
- /**
1580
- * Adds alpha channel to a hex color
1581
- * @param color
1582
- * @param alpha
1583
- * @returns rgba color string
1584
- */
1585
- export declare function hexToRgba(color: HexColor, alpha: number): RgbaColor;
1586
-
1587
- /** History stack change event */
1588
- export declare interface HistoryEvent {
1589
- /** Indicates if undo operation is available */
1590
- canUndo: boolean;
1591
- /** Indicates if redo operation is available */
1592
- canRedo: boolean;
1593
- }
1594
-
1595
- export declare const HL_BRIGHTEN = 0.2;
1596
-
1597
- /** Unique identifier type for annotations */
1598
- export declare type Id = string | number;
1599
-
1600
- /** Helper to check if a feature collection is an annotation collection */
1601
- export declare const isAnnotationCollection: (a: AnnotationFeature<Geometry, AnnotationProps> | FeatureCollection) => a is AnnotationCollection;
1602
-
1603
- export declare const isArrow: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Arrow;
1604
-
1605
- export declare const isBox: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Box;
1606
-
1607
- /**
1608
- * Type guard to check if a string is a valid color
1609
- */
1610
- export declare function isColor(color: string): color is Color;
1611
-
1612
- /**
1613
- * Type guard to check if an annotation is a Comment
1614
- */
1615
- export declare const isComment: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Comment_2;
1616
-
1617
- /**
1618
- * Helper functions for managing comment-arrow relationships
1619
- *
1620
- * These functions provide utilities for:
1621
- * - Checking if an arrow is connected to a comment
1622
- * - Determining if arrow endpoints can be detached from comments
1623
- * - Cascading a comment's delete to its arrows, and blocking deletion of a
1624
- * comment's last remaining arrow (store/index.ts:removeFeature uses both)
1625
- */
1626
- /**
1627
- * Check if an arrow is connected to a comment
1628
- *
1629
- * @param arrow - The arrow feature to check
1630
- * @returns True if the arrow has a comment on either end
1631
- *
1632
- * @example
1633
- * ```typescript
1634
- * if (isCommentArrow(arrow)) {
1635
- * // Handle comment arrow specially
1636
- * }
1637
- * ```
1638
- */
1639
- export declare function isCommentArrow(arrow: Arrow): boolean;
1640
-
1641
- /**
1642
- * Type guard to check if a string is a valid hex color
1643
- */
1644
- export declare function isHexColor(color: string): color is HexColor;
1645
-
1646
- export declare const isPolygon: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Polygon;
1647
-
1648
- /**
1649
- * Type guard to check if a string is a valid RGBA color
1650
- */
1651
- export declare function isRgbaColor(color: string): color is RgbaColor;
1652
-
1653
- /**
1654
- * Type guard to check if a string is a valid RGB color
1655
- */
1656
- export declare function isRgbColor(color: string): color is RgbColor;
1657
-
1658
- /**
1659
- * Whether a comment's connector line should rigidly follow its attachment
1660
- * point (translate the comment by the same offset) rather than elastically
1661
- * re-anchoring to the nearest point on the comment box.
1662
- *
1663
- * @param comment - Comment annotation
1664
- * @returns True unless the comment's style explicitly sets `connectorMode: "elastic"`
1665
- */
1666
- export declare function isRigidConnector(comment: Comment_2): boolean;
1667
-
1668
- export declare const isText: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Text_2;
1669
-
1670
- /** @private */
1671
- export declare const LAYERS: {
1672
- SHAPES: number;
1673
- EDITOR: number;
1674
- HANDLES: number;
1675
- };
1676
-
1677
- /** Link between an arrow and a text or node */
1678
- export declare interface Link {
1679
- /** arrow attached to the text or node */
1680
- arrow: Id;
1681
- /** id of the text the arrow is attached to */
1682
- id: Id;
1683
- /** On which end the arrow is tighten to the text */
1684
- side: Side;
1685
- /** id of the text or node the arrow is attached to */
1686
- target: Id;
1687
- /** Text or node */
1688
- targetType: TargetType;
1689
- /** Typed snap point — semantics depend on targetType, see Magnet union. */
1690
- magnet: Magnet;
1691
- }
1692
-
1693
- export declare type Magnet = NodeMagnet | EdgeMagnet | BoxMagnet | PolygonMagnet;
1694
-
1695
- /**
1696
- * Migrates old Polygon-based Box/Text to new Point-based format
1697
- * Called only when annotations are added/loaded
1698
- * @private
1699
- */
1700
- export declare function migrateBoxOrTextIfNeeded<T extends Annotation>(annotation: T): T;
1701
-
1702
- /** Arrow snapped to the center or perimeter of a node. */
1703
- export declare type NodeMagnet = {
1704
- type: "node";
1705
- center: boolean;
1706
- };
1707
-
1708
- export declare const NONE = -1;
1709
-
1710
- export declare function parseColor(color: Color): {
1711
- r: number;
1712
- g: number;
1713
- b: number;
1714
- a: number;
1715
- };
1716
-
1717
- /** 2D coordinate */
1718
- export declare type Point = {
1719
- x: number;
1720
- y: number;
1721
- };
1722
-
1723
- /**
1724
- * Polygon placed on the graph, use it to highlight areas
1725
- */
1726
- export declare interface Polygon extends AnnotationFeature<Polygon_2, PolygonProperties> {
1727
- }
1728
-
1729
- /**
1730
- * Arrow snapped to a polygon annotation.
1731
- * rx/ry are 0–1 fractions of the polygon's bounding box from its top-left corner.
1732
- */
1733
- export declare type PolygonMagnet = {
1734
- type: "polygon";
1735
- rx: number;
1736
- ry: number;
1737
- };
1738
-
1739
- export declare interface PolygonProperties extends AnnotationProps {
1740
- type: "polygon";
1741
- style?: PolygonStyle;
1742
- }
1743
-
1744
- export declare interface PolygonStyle extends BoxStyle {
1745
- }
1746
-
1747
- /**
1748
- * RGBA color string in format rgba(r, g, b, a)
1749
- * @example "rgba(255, 0, 0, 1)" | "rgba(128, 128, 128, 0.5)"
1750
- */
1751
- export declare type RgbaColor = `rgba(${number}, ${number}, ${number}, ${number})` | `rgba(${number},${number},${number},${number})`;
1752
-
1753
- /**
1754
- * RGB color string in format rgb(r, g, b)
1755
- * @example "rgb(255, 0, 0)" | "rgb(128, 128, 128)"
1756
- */
1757
- export declare type RgbColor = `rgb(${number}, ${number}, ${number})` | `rgb(${number},${number},${number})`;
1758
-
1759
- /**
1760
- * Adds alpha channel to an rgb color
1761
- * @param color
1762
- * @param alpha
1763
- * @returns rgba color string
1764
- */
1765
- export declare function rgbToRgba(color: RgbColor, alpha: number): RgbaColor;
1766
-
1767
- export declare function scaleGeometry(geometry: LineString | Polygon_2, scale: number, ox: number, oy: number): LineString | Polygon_2;
1768
-
1769
- /**
1770
- * Scale polygon around an origin point
1771
- */
1772
- export declare function scalePolygon(polygon: Polygon, scale: number, originX: number, originY: number): Polygon;
1773
-
1774
- export declare function setArrowEnd(a: Arrow, x: number, y: number): void;
1775
-
1776
- export declare function setArrowEndPoint(a: Arrow, side: Side, x: number, y: number): void;
1777
-
1778
- export declare function setArrowStart(a: Arrow, x: number, y: number): void;
1779
-
1780
- declare function setBbox(t: Box | Text_2, x: number, y: number, width: number, height: number): void;
1781
- export { setBbox }
1782
- export { setBbox as setTextBbox }
1783
-
1784
- export declare type Side = typeof SIDE_START | typeof SIDE_END;
1785
-
1786
- export declare const SIDE_END: "end";
1787
-
1788
- export declare const SIDE_START: "start";
1789
-
1790
- /**
1791
- * Polyline simplification using a combination of
1792
- * the Radial Distance and
1793
- * the Douglas-Peucker algorithms
1794
- * See https://github.com/mourner/simplify-js for more details
1795
- *
1796
- * @param points Points to simplify
1797
- * @param tolerance Tolerance in pixels
1798
- * @param highestQuality Whether to skip radial distance simplification
1799
- * @returns Simplified points
1800
- */
1801
- export declare function simplifyPolygon(points: Position[], tolerance: number, highestQuality: boolean): Position[];
1802
-
1803
- /** Stroke style for arrow annotations */
1804
- export declare type Stroke = {
1805
- /** Stroke type */
1806
- type: StrokeType;
1807
- /** Stroke color */
1808
- color: Color;
1809
- /** Stroke width */
1810
- width: number;
1811
- };
1812
-
1813
- /** Stroke style options for annotations */
1814
- export declare type StrokeOptions = {
1815
- /** Type of stroke: plain, dashed, or none */
1816
- strokeType?: StrokeType;
1817
- /** Stroke color: #f00, yellow... */
1818
- strokeColor?: Color;
1819
- /** Stroke width */
1820
- strokeWidth?: number;
1821
- };
1822
-
1823
- export declare type StrokeStyle = Stroke;
1824
-
1825
- /** Stroke types available for annotations */
1826
- export declare type StrokeType = "plain" | "dashed" | "none";
1827
-
1828
- /** @private */
1829
- export declare const TARGET_TYPES: {
1830
- TEXT: "text";
1831
- NODE: "node";
1832
- BOX: "box";
1833
- COMMENT: "comment";
1834
- POLYGON: "polygon";
1835
- ANNOTATION: "annotation";
1836
- EDGE: "edge";
1837
- };
1838
-
1839
- export declare type TargetType = (typeof TARGET_TYPES)[keyof typeof TARGET_TYPES];
1840
-
1841
- /**
1842
- * Text annotation feature, represents a text box at a specific position
1843
- */
1844
- declare interface Text_2 extends AnnotationFeature<Point_2, TextProperties> {
1845
- }
1846
- export { Text_2 as Text }
1847
-
1848
- export declare const TEXT_LINE_HEIGHT = 1.2;
1849
-
1850
- export declare interface TextProperties extends Omit<BoxProperties, "type"> {
1851
- type: "text";
1852
- /**text to display*/
1853
- content: string;
1854
- /** Width of the text box */
1855
- width: number;
1856
- /** Height of the text box */
1857
- height: number;
1858
- style?: TextStyle;
1859
- }
1860
-
1861
- export declare interface TextStyle extends BoxStyle {
1862
- /** Helvetica, sans-serif... */
1863
- font?: string;
1864
- /** Font size, in pixels */
1865
- fontSize?: number | string;
1866
- /** text color: #f00, yellow...*/
1867
- color?: Color;
1868
- /** background color: empty for transparent #f00, yellow...*/
1869
- background?: Color;
1870
- /** padding around the text */
1871
- padding?: number;
1872
- /** Text box border radius */
1873
- borderRadius?: number;
1874
- /** When true, text maintains constant size regardless of zoom level */
1875
- fixedSize?: boolean;
1876
- /**
1877
- * Ghost text shown (via the textarea's native `placeholder` attribute)
1878
- * while `content` is empty - disappears the instant the user types, no
1879
- * selection/focus tricks needed. Overrides the global
1880
- * `ControllerOptions.textPlaceholder` for this annotation.
1881
- */
1882
- placeholder?: string;
1883
- }
1884
-
1885
- /** @private */
1886
- export declare const throttle: <T extends unknown[]>(callback: (...args: T) => void, delay?: number, callIfWaiting?: boolean) => (...args: T) => void;
1887
-
1888
- /**
1889
- * Toggle comment mode between collapsed and expanded
1890
- *
1891
- * @param comment - Comment to toggle
1892
- * @returns Updated comment with toggled mode
1893
- */
1894
- export declare function toggleCommentMode(comment: Comment_2): Comment_2;
1895
-
1896
- /**
1897
- * Translate (move) a polygon by dx, dy
1898
- */
1899
- export declare function translatePolygon(polygon: Polygon, dx: number, dy: number): Polygon;
1900
-
1901
- declare function updateBbox<T extends Annotation>(t: T): void;
1902
- export { updateBbox }
1903
- export { updateBbox as updateTextBbox }
1904
-
1905
- /**
1906
- * Update bbox for a polygon
1907
- */
1908
- export declare function updatePolygonBbox(polygon: Polygon): void;
1909
-
1910
- /** @private */
1911
- export declare type Vector = Point;
1912
-
1913
- export { }
1
+ import { P as Polygon, B as Bounds, a as Point, C as Color, R as RgbaColor, b as ClientMouseEvent, A as AnnotationCollection, c as Arrow, S as Side, d as Annotation, H as HexColor, e as RgbColor, f as Box, T as Text, I as Id } from './Control-Cv1I3e3C.js';
2
+ export { g as AnnotationFeature, h as AnnotationGetter, i as AnnotationOptions, j as AnnotationProps, k as AnnotationType, l as ArrowProperties, m as ArrowStyles, n as AuthorLineStyle, o as BoxMagnet, p as BoxProperties, q as BoxStyle, r as COMMENT_MODE_COLLAPSED, s as COMMENT_MODE_EXPANDED, t as ClickEvent, u as Comment, v as CommentProps, w as CommentStyle, x as Control, y as ControllerOptions, z as Cursor, D as DATA_ATTR, E as DEFAULT_EDIT_ICON, F as DEFAULT_SEND_ICON, G as DeepPartial, J as DragEvent, K as EVT_ADD, L as EVT_CANCEL_DRAWING, M as EVT_CLICK, N as EVT_COMPLETE_DRAWING, O as EVT_DRAG, Q as EVT_DRAG_END, U as EVT_DRAG_START, V as EVT_HISTORY, W as EVT_HOVER, X as EVT_LINK, Y as EVT_REMOVE, Z as EVT_SELECT, _ as EVT_UNHOVER, $ as EVT_UNSELECT, a0 as EVT_UPDATE, a1 as EdgeMagnet, a2 as ExportedLink, a3 as Extremity, a4 as FeatureEvent, a5 as FeatureEvents, a6 as FeaturesEvent, a7 as HL_BRIGHTEN, a8 as HistoryEvent, a9 as LAYERS, aa as Link, ab as Magnet, ac as NONE, ad as NodeMagnet, ae as PolygonMagnet, af as PolygonProperties, ag as PolygonStyle, ah as SIDE_END, ai as SIDE_START, aj as Stroke, ak as StrokeOptions, al as StrokeStyle, am as StrokeType, an as TARGET_TYPES, ao as TEXT_LINE_HEIGHT, ap as TargetType, aq as TextProperties, ar as TextStyle, as as Vector, at as asColor, au as asHexColor, av as asRgbColor, aw as asRgbaColor, ax as calculateCommentZoomThreshold, ay as createArrow, az as createBox, aA as createComment, aB as createCommentWithArrow, aC as createPolygon, aD as createText, aE as cursors, aF as defaultArrowOptions, aG as defaultArrowStyle, aH as defaultBoxOptions, aI as defaultBoxStyle, aJ as defaultCommentOptions, aK as defaultCommentStyle, aL as defaultPolygonProperties, aM as defaultPolygonStyle, aN as defaultTextOptions, aO as defaultTextStyle, aP as detectArrow, aQ as detectBox, aR as detectComment, aS as detectPolygon, aT as detectText, aU as getCommentPosition, aV as getCommentSize, aW as getCommentZoomThreshold, aX as handleDetectionThreshold, aY as handleRadius, aZ as isAnnotationCollection, a_ as isArrow, a$ as isBox, b0 as isColor, b1 as isComment, b2 as isHexColor, b3 as isPolygon, b4 as isRgbColor, b5 as isRgbaColor, b6 as isRigidConnector, b7 as isStickyNote, b8 as isText, b9 as toggleCommentMode } from './Control-Cv1I3e3C.js';
3
+ import { Point as Point$1 } from '@linkurious/ogma';
4
+ import { Position, BBox, Feature, FeatureCollection, Geometry, LineString, Polygon as Polygon$1 } from 'geojson';
5
+ import 'eventemitter3';
6
+
7
+ /**
8
+ * Polyline simplification using a combination of
9
+ * the Radial Distance and
10
+ * the Douglas-Peucker algorithms
11
+ * See https://github.com/mourner/simplify-js for more details
12
+ *
13
+ * @param points Points to simplify
14
+ * @param tolerance Tolerance in pixels
15
+ * @param highestQuality Whether to skip radial distance simplification
16
+ * @returns Simplified points
17
+ */
18
+ declare function simplify(points: Position[], tolerance: number, highestQuality: boolean): Position[];
19
+
20
+ /**
21
+ * Get bounding box of a polygon
22
+ */
23
+ declare function getPolygonBounds(polygon: Polygon): Bounds;
24
+ /**
25
+ * Get centroid (geometric center) of a polygon
26
+ */
27
+ declare function getPolygonCenter(polygon: Polygon): Point;
28
+
29
+ /**
30
+ * Translate (move) a polygon by dx, dy
31
+ */
32
+ declare function translatePolygon(polygon: Polygon, dx: number, dy: number): Polygon;
33
+ /**
34
+ * Update bbox for a polygon
35
+ */
36
+ declare function updatePolygonBbox(polygon: Polygon): void;
37
+ /**
38
+ * Scale polygon around an origin point
39
+ */
40
+ declare function scalePolygon(polygon: Polygon, scale: number, originX: number, originY: number): Polygon;
41
+
42
+ /** @private */
43
+ declare function createSVGElement<T extends SVGElement>(tag: string): T;
44
+ /**
45
+ * Move `el` to the end of `root`'s children. SVG paint order is DOM order,
46
+ * so this is how a shape gets raised to the top of its group. Safe to call
47
+ * every render even when `el` is already last - `appendChild` on an
48
+ * existing child just re-positions it, it doesn't clone or re-trigger
49
+ * insertion.
50
+ */
51
+ declare function bringToTop(root: Element, el: Element): void;
52
+ declare function getBbox<T extends Annotation>(b: T): BBox;
53
+ declare function getBoxSize<T extends Annotation>(t: T): {
54
+ width: number;
55
+ height: number;
56
+ };
57
+ declare const MIN_FONT_SCALE = 0.4;
58
+ declare const MAX_FONT_SCALE = 4;
59
+ /** fontSize * fontScale, the number to actually render/edit at. Shared by
60
+ * the SVG renderer (text.ts) and the live-edit overlay (textArea.ts) so
61
+ * both stay in sync. fontScale absent/undefined is a no-op (×1). */
62
+ declare function getEffectiveFontSize(fontSize: number | string | undefined, fontScale: number | undefined): number;
63
+ declare function getBoxPosition<T extends Annotation>(t: T, fixedSize?: boolean, zoom?: number): {
64
+ x: number;
65
+ y: number;
66
+ };
67
+ declare function getBoxCenter<T extends Annotation>(t: T): {
68
+ x: number;
69
+ y: number;
70
+ };
71
+ declare function updateBbox<T extends Annotation>(t: T): void;
72
+ declare function setBbox(t: Box | Text, x: number, y: number, width: number, height: number): void;
73
+ declare function getArrowStart(a: Arrow): {
74
+ x: number;
75
+ y: number;
76
+ };
77
+ declare function getArrowSide(a: Arrow, side: Side): {
78
+ x: number;
79
+ y: number;
80
+ };
81
+ declare function getArrowEnd(a: Arrow): {
82
+ x: number;
83
+ y: number;
84
+ };
85
+ declare function setArrowStart(a: Arrow, x: number, y: number): void;
86
+ declare function setArrowEnd(a: Arrow, x: number, y: number): void;
87
+ declare function getArrowEndPoints(a: Arrow): {
88
+ start: {
89
+ x: number;
90
+ y: number;
91
+ };
92
+ end: {
93
+ x: number;
94
+ y: number;
95
+ };
96
+ };
97
+ declare function setArrowEndPoint(a: Arrow, side: Side, x: number, y: number): void;
98
+ declare const getHandleId: (handle: HTMLDivElement) => number;
99
+ /**
100
+ * Calculate the bounds of a collection of annotations
101
+ * @param annotations
102
+ * @returns Bounds [minX, minY, maxX, maxY]
103
+ */
104
+ declare function getAnnotationsBounds(annotations: AnnotationCollection): Bounds;
105
+ declare function scaleGeometry(geometry: LineString | Polygon$1, scale: number, ox: number, oy: number): LineString | Polygon$1;
106
+ declare function getCoordinates(geojson: Feature | FeatureCollection | Geometry): Position[];
107
+ declare function getAttachmentPointOnNode(start: Point$1, nodeCenter: Point$1, nodeRadius: number): {
108
+ x: number;
109
+ y: number;
110
+ };
111
+ declare function clientToContainerPosition(evt: ClientMouseEvent, container?: HTMLElement | null): {
112
+ x: number;
113
+ y: number;
114
+ };
115
+ /**
116
+ * Inverse of clientToContainerPosition: turns a point already relative to
117
+ * the container's top-left (e.g. from ogma.view.graphToScreenCoordinates)
118
+ * into viewport-relative clientX/clientY, for code paths that synthesize a
119
+ * MouseEvent-shaped object and hand it to something (like Handler.onDragStart)
120
+ * that normalizes via clientToContainerPosition itself.
121
+ */
122
+ declare function containerToClientPosition(point: {
123
+ x: number;
124
+ y: number;
125
+ }, container?: HTMLElement | null): {
126
+ x: number;
127
+ y: number;
128
+ };
129
+ declare function colorToRgba(color: Color, alpha: number): RgbaColor;
130
+ declare function parseColor(color: Color): {
131
+ r: number;
132
+ g: number;
133
+ b: number;
134
+ a: number;
135
+ };
136
+ declare function hexShortToLong(color: HexColor): HexColor;
137
+ /**
138
+ * Adds alpha channel to a hex color
139
+ * @param color
140
+ * @param alpha
141
+ * @returns rgba color string
142
+ */
143
+ declare function hexToRgba(color: HexColor, alpha: number): RgbaColor;
144
+ /**
145
+ * Adds alpha channel to an rgb color
146
+ * @param color
147
+ * @param alpha
148
+ * @returns rgba color string
149
+ */
150
+ declare function rgbToRgba(color: RgbColor, alpha: number): RgbaColor;
151
+ /** @private */
152
+ declare function getBrowserWindow(): HTMLElement | undefined;
153
+ /** @private */
154
+ declare const throttle: <T extends unknown[]>(callback: (...args: T) => void, delay?: number, callIfWaiting?: boolean) => (...args: T) => void;
155
+ /** @private */
156
+ declare const debounce: <F extends (...args: Parameters<F>) => ReturnType<F>>(func: F, waitFor: number) => (...args: Parameters<F>) => void;
157
+ /** @private */
158
+ declare function debounceTail<T, A extends unknown[]>(fn: (this: T, ...args: A) => void, delay: number): (this: T, ...args: A) => void;
159
+
160
+ /**
161
+ * Migrates old Polygon-based Box/Text to new Point-based format
162
+ * Called only when annotations are added/loaded
163
+ * @private
164
+ */
165
+ declare function migrateBoxOrTextIfNeeded<T extends Annotation>(annotation: T): T;
166
+ /**
167
+ * Adjusts the brightness of a color (hex or rgba) based on its perceived luminance.
168
+ * For bright colors, the adjustment is applied as darkening; for dark colors, as lightening.
169
+ *
170
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
171
+ * @param amount - Adjustment factor between -1 and 1:
172
+ * - Positive values (0 to 1): lighten dark colors, darken bright colors
173
+ * - Negative values (-1 to 0): darken dark colors, lighten bright colors
174
+ * - 0: no change
175
+ * - Example: 0.2 applies a 20% adjustment, -0.1 applies a -10% adjustment
176
+ * @returns Adjusted color in rgba format
177
+ */
178
+ declare function adjustColorBrightness(color: Color, amount: number): RgbaColor;
179
+ /**
180
+ * Brighten a color for highlight purposes.
181
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
182
+ * @returns
183
+ */
184
+ declare const brighten: (color: Color) => RgbaColor;
185
+ /**
186
+ * Darken a color for highlight purposes.
187
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
188
+ * @returns
189
+ */
190
+ declare const darken: (color: Color) => RgbaColor;
191
+
192
+ /**
193
+ * Helper functions for managing comment-arrow relationships
194
+ *
195
+ * These functions provide utilities for:
196
+ * - Checking if an arrow is connected to a comment
197
+ * - Determining if arrow endpoints can be detached from comments
198
+ * - Cascading a comment's delete to its arrows, and blocking deletion of a
199
+ * comment's last remaining arrow (store/index.ts:removeFeature uses both)
200
+ */
201
+ /**
202
+ * Check if an arrow is connected to a comment
203
+ *
204
+ * @param arrow - The arrow feature to check
205
+ * @returns True if the arrow has a comment on either end
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * if (isCommentArrow(arrow)) {
210
+ * // Handle comment arrow specially
211
+ * }
212
+ * ```
213
+ */
214
+ declare function isCommentArrow(arrow: Arrow): boolean;
215
+ /**
216
+ * Get the id of the comment an arrow is connected to, if any.
217
+ *
218
+ * A comment is one visual annotation together with the arrow that connects
219
+ * it - callers that raise a comment's z-order (e.g. bringing a newly
220
+ * created/selected comment to the front) should raise this arrow along with
221
+ * it, not just the comment bubble.
222
+ *
223
+ * @param arrow - The arrow feature to check
224
+ * @returns The linked comment's id, or undefined if the arrow isn't attached
225
+ * to a comment
226
+ */
227
+ declare function getCommentLinkId(arrow: Arrow): Id | undefined;
228
+ /**
229
+ * Check if arrow start point can be detached from its source
230
+ *
231
+ * Returns false for arrows originating FROM comments, since comment arrows
232
+ * must always remain attached to the comment on their start side.
233
+ *
234
+ * @param arrow - The arrow feature
235
+ * @returns True if arrow start can be detached
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * if (canDetachArrowStart(arrow)) {
240
+ * // Allow user to drag arrow start point
241
+ * } else {
242
+ * // Keep arrow start locked to comment
243
+ * }
244
+ * ```
245
+ */
246
+ declare function canDetachArrowStart(arrow: Arrow): boolean;
247
+ /**
248
+ * Check if arrow endpoint can be detached from its target
249
+ *
250
+ * Always returns true since arrow endpoints can be freely retargeted,
251
+ * even for comment arrows. The comment is typically on the start side.
252
+ *
253
+ * @param _arrow - The arrow feature (unused, kept for API consistency)
254
+ * @returns Always true - arrow ends can be detached
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * if (canDetachArrowEnd(arrow)) {
259
+ * // Allow user to drag arrow end point
260
+ * }
261
+ * ```
262
+ */
263
+ declare function canDetachArrowEnd(_arrow: Arrow): boolean;
264
+ /**
265
+ * Ids that removing `id` should take with it: `id` itself, plus every arrow
266
+ * attached to it when it's a comment or text annotation - deleting the
267
+ * anchor takes its connectors along, since a detached comment-arrow has
268
+ * nothing to point at.
269
+ *
270
+ * @param features - The full feature map (pre-deletion)
271
+ * @param id - The id being removed
272
+ * @returns The complete set of ids to delete
273
+ */
274
+ declare function getCascadeDeleteIds(features: Record<Id, Annotation>, id: Id): Set<Id>;
275
+ /**
276
+ * Comments must always keep at least one arrow. Returns the comment's id
277
+ * when deleting `arrowId` would leave it with none, so the caller can block
278
+ * the deletion instead - or `null` when it's safe to proceed.
279
+ *
280
+ * @param features - The full feature map (pre-deletion)
281
+ * @param arrowId - The arrow being removed
282
+ */
283
+ declare function getCommentLeftOrphanedBy(features: Record<Id, Annotation>, arrowId: Id): Id | null;
284
+
285
+ export { Annotation, AnnotationCollection, Arrow, Bounds, Box, ClientMouseEvent, Color, HexColor, Id, MAX_FONT_SCALE, MIN_FONT_SCALE, Point, Polygon, RgbColor, RgbaColor, Side, Text, adjustColorBrightness, brighten, bringToTop, canDetachArrowEnd, canDetachArrowStart, clientToContainerPosition, colorToRgba, containerToClientPosition, createSVGElement, darken, debounce, debounceTail, getAnnotationsBounds, getArrowEnd, getArrowEndPoints, getArrowSide, getArrowStart, getAttachmentPointOnNode, getBbox, getBoxCenter, getBoxPosition, getBoxSize, getBrowserWindow, getCascadeDeleteIds, getCommentLeftOrphanedBy, getCommentLinkId, getCoordinates, getEffectiveFontSize, getHandleId, getPolygonBounds, getPolygonCenter, getBbox as getTextBbox, getBoxPosition as getTextPosition, getBoxSize as getTextSize, hexShortToLong, hexToRgba, isCommentArrow, migrateBoxOrTextIfNeeded, parseColor, rgbToRgba, scaleGeometry, scalePolygon, setArrowEnd, setArrowEndPoint, setArrowStart, setBbox, setBbox as setTextBbox, simplify as simplifyPolygon, throttle, translatePolygon, updateBbox, updatePolygonBbox, updateBbox as updateTextBbox };