@linkurious/ogma-annotations 2.1.0 → 2.1.2

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.
@@ -0,0 +1,573 @@
1
+ /**
2
+ * Canonical stylesheet for the annotation style panel and toolbar UI.
3
+ * Shared by the vanilla (core) and React packages.
4
+ *
5
+ * Theming: override the `--oa-*` custom properties on `.annotation-panel`
6
+ * / `.annotation-toolbar` (or any ancestor) to restyle. Defaults preserve
7
+ * the original look. The accent color falls back to the legacy `--brand`
8
+ * variable if set.
9
+ *
10
+ * Layout: both roots carry `data-placement` (which screen edge/corner they
11
+ * dock to — `right` (default for the panel), `left`, `top`,
12
+ * `bottom` (default for the toolbar), `top-left`, `top-right`,
13
+ * `bottom-left`, `bottom-right`) and `data-orientation` (`vertical`
14
+ * (default for the panel) or `horizontal` (default for the toolbar)), set
15
+ * via the `placement`/`orientation` options (vanilla) or props (React).
16
+ * Position either relative to its container by giving that container
17
+ * `position: relative`.
18
+ */
19
+
20
+ .annotation-panel,
21
+ .annotation-toolbar {
22
+ /* Theme tokens */
23
+ --oa-accent: var(--brand, #3a03cf);
24
+ --oa-panel-bg: #ffffff;
25
+ --oa-panel-radius: 10px;
26
+ --oa-panel-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
27
+ --oa-control-bg: #eeeeee;
28
+ --oa-text-color: #333333;
29
+ --oa-muted-color: #666666;
30
+ --oa-panel-margin: 10px;
31
+
32
+ position: absolute;
33
+ background: var(--oa-panel-bg);
34
+ z-index: 100;
35
+ box-shadow: var(--oa-panel-shadow);
36
+ border-radius: var(--oa-panel-radius);
37
+ }
38
+
39
+ .annotation-panel {
40
+ width: 228px;
41
+ }
42
+
43
+ /* Placement: which screen edge/corner the root docks to. */
44
+ .annotation-panel:not([data-placement]),
45
+ .annotation-panel[data-placement="right"],
46
+ .annotation-toolbar[data-placement="right"] {
47
+ right: var(--oa-panel-margin);
48
+ top: 50%;
49
+ transform: translateY(-50%);
50
+ }
51
+
52
+ .annotation-panel[data-placement="left"],
53
+ .annotation-toolbar[data-placement="left"] {
54
+ left: var(--oa-panel-margin);
55
+ top: 50%;
56
+ transform: translateY(-50%);
57
+ }
58
+
59
+ .annotation-panel[data-placement="top"],
60
+ .annotation-toolbar[data-placement="top"] {
61
+ top: var(--oa-panel-margin);
62
+ left: 50%;
63
+ transform: translateX(-50%);
64
+ }
65
+
66
+ .annotation-toolbar:not([data-placement]),
67
+ .annotation-panel[data-placement="bottom"],
68
+ .annotation-toolbar[data-placement="bottom"] {
69
+ bottom: var(--oa-panel-margin);
70
+ left: 50%;
71
+ transform: translateX(-50%);
72
+ }
73
+
74
+ .annotation-panel[data-placement="top-left"],
75
+ .annotation-toolbar[data-placement="top-left"] {
76
+ left: var(--oa-panel-margin);
77
+ top: var(--oa-panel-margin);
78
+ }
79
+
80
+ .annotation-panel[data-placement="top-right"],
81
+ .annotation-toolbar[data-placement="top-right"] {
82
+ right: var(--oa-panel-margin);
83
+ top: var(--oa-panel-margin);
84
+ }
85
+
86
+ .annotation-panel[data-placement="bottom-left"],
87
+ .annotation-toolbar[data-placement="bottom-left"] {
88
+ left: var(--oa-panel-margin);
89
+ bottom: var(--oa-panel-margin);
90
+ }
91
+
92
+ .annotation-panel[data-placement="bottom-right"],
93
+ .annotation-toolbar[data-placement="bottom-right"] {
94
+ right: var(--oa-panel-margin);
95
+ bottom: var(--oa-panel-margin);
96
+ }
97
+
98
+ /* Orientation: lay sections out as a horizontal toolbar instead of a
99
+ vertically-stacked card. Every section is a `.section-header` + one
100
+ content sibling (`.color-selector`, `.slider-section`, ...); a 2-row
101
+ auto-flow grid regroups each consecutive pair into its own column
102
+ without any markup changes. */
103
+ .annotation-panel[data-orientation="horizontal"] {
104
+ width: auto;
105
+ max-width: min(90vw, 640px);
106
+ }
107
+
108
+ .annotation-panel[data-orientation="horizontal"] .panel-body {
109
+ display: grid;
110
+ grid-auto-flow: column;
111
+ grid-template-rows: auto auto;
112
+ align-items: start;
113
+ column-gap: 20px;
114
+ overflow-x: auto;
115
+ }
116
+
117
+ .annotation-panel[data-orientation="horizontal"] .section-header {
118
+ margin-top: 0;
119
+ }
120
+
121
+ .annotation-panel[data-orientation="horizontal"] .slider {
122
+ width: 120px;
123
+ }
124
+
125
+ .panel-header {
126
+ padding: 20px 20px 10px 20px;
127
+ }
128
+
129
+ .panel-header h3 {
130
+ margin: 0;
131
+ font-size: 12px;
132
+ font-weight: 400;
133
+ letter-spacing: 0.05em;
134
+ text-transform: uppercase;
135
+ }
136
+
137
+ .panel-body {
138
+ padding: 10px 20px 20px 20px;
139
+ }
140
+
141
+ /* Color Selector */
142
+ .color-selector {
143
+ display: flex;
144
+ gap: 12px;
145
+ }
146
+
147
+ .color-circle {
148
+ position: relative;
149
+ width: 40px;
150
+ height: 40px;
151
+ background: transparent;
152
+ border-radius: 4px;
153
+ border: none;
154
+ cursor: pointer;
155
+ padding: 0;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ transition: transform 0.2s;
160
+ }
161
+
162
+ .color-circle:hover {
163
+ transform: scale(1.05);
164
+ }
165
+
166
+ .color-circle .color-inner {
167
+ width: 30px;
168
+ height: 30px;
169
+ border-radius: 50%;
170
+ border: 1px solid #d4d4d8;
171
+ background: white;
172
+ position: relative;
173
+ }
174
+
175
+ .color-circle .color-inner::after {
176
+ content: "";
177
+ position: absolute;
178
+ top: 50%;
179
+ left: 50%;
180
+ transform: translate(-50%, -50%);
181
+ width: 18px;
182
+ height: 18px;
183
+ border-radius: 50%;
184
+ background: var(--circle-color);
185
+ }
186
+
187
+ .color-circle-primary .color-inner {
188
+ border: 3px solid var(--oa-accent);
189
+ }
190
+
191
+ /* Color Picker Container */
192
+ .color-picker-container {
193
+ margin-bottom: 20px;
194
+ padding: 10px;
195
+ background: #f9f9f9;
196
+ border-radius: 4px;
197
+ display: none !important;
198
+ }
199
+
200
+ /* Toggle Section */
201
+ .toggle-section {
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ gap: 12px;
206
+ padding: 12px 0;
207
+ margin-bottom: 10px;
208
+ }
209
+
210
+ .toggle-section svg {
211
+ color: var(--oa-text-color);
212
+ }
213
+
214
+ .toggle-label {
215
+ font-size: 14px;
216
+ color: var(--oa-text-color);
217
+ font-weight: 400;
218
+ }
219
+
220
+ .toggle-switch {
221
+ position: relative;
222
+ display: inline-block;
223
+ width: 31px;
224
+ height: 15px;
225
+ }
226
+
227
+ .toggle-switch input {
228
+ opacity: 0;
229
+ width: 0;
230
+ height: 0;
231
+ }
232
+
233
+ .toggle-slider {
234
+ position: absolute;
235
+ cursor: pointer;
236
+ top: 0;
237
+ left: 0;
238
+ right: 0;
239
+ bottom: 0;
240
+ background-color: #eeeeee;
241
+ transition: 0.3s;
242
+ border-radius: 7.5px;
243
+ border: 0.5px solid #b6c2e2;
244
+ }
245
+
246
+ .toggle-slider:before {
247
+ position: absolute;
248
+ content: "";
249
+ height: 12px;
250
+ width: 12px;
251
+ left: 2px;
252
+ bottom: 1.5px;
253
+ background-color: white;
254
+ transition: 0.3s;
255
+ border-radius: 50%;
256
+ }
257
+
258
+ input:checked + .toggle-slider {
259
+ background-color: var(--oa-accent);
260
+ }
261
+
262
+ input:checked + .toggle-slider:before {
263
+ transform: translateX(15px);
264
+ }
265
+
266
+ /* Section Headers */
267
+ .section-header {
268
+ margin-top: 10px;
269
+ }
270
+
271
+ .section-header h3 {
272
+ margin: 0;
273
+ font-size: 12px;
274
+ font-weight: 400;
275
+ letter-spacing: 0.05em;
276
+ text-transform: uppercase;
277
+ }
278
+
279
+ /* Slider Section */
280
+ .slider-section {
281
+ position: relative;
282
+ padding: 10px 0;
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 10px;
286
+ }
287
+
288
+ .slider {
289
+ width: 85%;
290
+ height: 4.8px;
291
+ border-radius: 2.4px;
292
+ background: #e4e4e7;
293
+ outline: none;
294
+ -webkit-appearance: none;
295
+ appearance: none;
296
+ }
297
+
298
+ .slider::-webkit-slider-thumb {
299
+ -webkit-appearance: none;
300
+ appearance: none;
301
+ width: 12px;
302
+ height: 12px;
303
+ border-radius: 50%;
304
+ background: white;
305
+ border: 3px solid var(--oa-accent);
306
+ cursor: pointer;
307
+ box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
308
+ }
309
+
310
+ .slider::-moz-range-thumb {
311
+ width: 12px;
312
+ height: 12px;
313
+ border-radius: 50%;
314
+ background: white;
315
+ border: 3px solid var(--oa-accent);
316
+ cursor: pointer;
317
+ box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
318
+ }
319
+
320
+ .slider-value {
321
+ width: 15%;
322
+ text-align: right;
323
+ flex-shrink: 0;
324
+ }
325
+
326
+ .slider-value span {
327
+ font-size: 14px;
328
+ font-weight: 500;
329
+ color: black;
330
+ }
331
+
332
+ /* Line Type Section */
333
+ .linetype-section {
334
+ display: flex;
335
+ gap: 8px;
336
+ justify-content: center;
337
+ padding: 10px 0;
338
+ }
339
+
340
+ .linetype-button {
341
+ flex: 1;
342
+ height: 36px;
343
+ background: var(--oa-control-bg);
344
+ border: none;
345
+ border-radius: 8px;
346
+ cursor: pointer;
347
+ display: flex;
348
+ align-items: center;
349
+ justify-content: center;
350
+ color: var(--oa-muted-color);
351
+ transition: all 0.2s;
352
+ font-size: 18px;
353
+ }
354
+
355
+ .linetype-button:hover {
356
+ background: #e0e0e0;
357
+ }
358
+
359
+ .linetype-button.active {
360
+ background: var(--oa-accent);
361
+ color: white;
362
+ }
363
+
364
+ /* Color Picker Overlay */
365
+ .color-picker-overlay {
366
+ position: fixed;
367
+ z-index: 10000;
368
+ background: white;
369
+ padding: 10px;
370
+ border-radius: 8px;
371
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
372
+ }
373
+
374
+ /* Custom Select Section */
375
+ .custom-select-section {
376
+ display: flex;
377
+ gap: 8px;
378
+ }
379
+
380
+ .extremity-wrapper {
381
+ flex: 1;
382
+ display: flex;
383
+ flex-direction: column;
384
+ gap: 6px;
385
+ }
386
+
387
+ .extremity-wrapper label {
388
+ font-size: 11px;
389
+ font-weight: 400;
390
+ color: var(--oa-muted-color);
391
+ text-transform: capitalize;
392
+ text-align: center;
393
+ }
394
+
395
+ .custom-select {
396
+ position: relative;
397
+ width: 100%;
398
+ }
399
+
400
+ .custom-select-trigger {
401
+ width: 100%;
402
+ height: 36px;
403
+ background: transparent;
404
+ border: none;
405
+ border-radius: 8px;
406
+ cursor: pointer;
407
+ padding: 0 8px;
408
+ font-size: 14px;
409
+ color: var(--oa-text-color);
410
+ display: flex;
411
+ align-items: center;
412
+ justify-content: center;
413
+ gap: 6px;
414
+ transition: all 0.2s;
415
+ user-select: none;
416
+ }
417
+
418
+ .custom-select-trigger svg:first-child {
419
+ flex-shrink: 0;
420
+ }
421
+
422
+ .custom-select-trigger span {
423
+ display: none;
424
+ }
425
+
426
+ .custom-select-arrow {
427
+ font-size: 12px;
428
+ transition: transform 0.2s;
429
+ flex-shrink: 0;
430
+ }
431
+
432
+ .custom-select.open .custom-select-arrow {
433
+ transform: rotate(180deg);
434
+ }
435
+
436
+ .custom-select-options {
437
+ position: absolute;
438
+ top: 100%;
439
+ right: 0;
440
+ background: white;
441
+ border-radius: 8px;
442
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
443
+ margin-top: 4px;
444
+ margin-right: 24px;
445
+ overflow: hidden;
446
+ z-index: 1000;
447
+ display: none;
448
+ }
449
+
450
+ .custom-select.open .custom-select-options {
451
+ display: block;
452
+ width: 36px;
453
+ }
454
+
455
+ .custom-select-option {
456
+ padding: 10px 12px;
457
+ cursor: pointer;
458
+ display: flex;
459
+ align-items: center;
460
+ justify-content: center;
461
+ gap: 8px;
462
+ transition: background 0.15s;
463
+ font-size: 14px;
464
+ color: var(--oa-text-color);
465
+ }
466
+
467
+ .custom-select-option:hover {
468
+ background: #f5f5f5;
469
+ }
470
+
471
+ .custom-select-option.selected {
472
+ background: #e8f4ff;
473
+ color: var(--oa-accent);
474
+ }
475
+
476
+ .custom-select-option svg {
477
+ flex-shrink: 0;
478
+ }
479
+
480
+ .custom-select-option span {
481
+ display: none;
482
+ }
483
+
484
+ /* --- Annotation Toolbar (AnnotationToolbar) ---
485
+ Drawing/undo-redo toolbar. Shares the placement rules above with
486
+ `.annotation-panel`; only its own button/orientation styling lives here. */
487
+ .annotation-toolbar {
488
+ display: flex;
489
+ align-items: center;
490
+ gap: 4px;
491
+ padding: 5px;
492
+ }
493
+
494
+ .annotation-toolbar[data-orientation="vertical"] {
495
+ flex-direction: column;
496
+ }
497
+
498
+ .annotation-toolbar:not([data-orientation]),
499
+ .annotation-toolbar[data-orientation="horizontal"] {
500
+ flex-direction: row;
501
+ }
502
+
503
+ .annotation-toolbar button {
504
+ margin: 2px;
505
+ padding: 5px;
506
+ border: 1px solid transparent;
507
+ cursor: pointer;
508
+ border-radius: 5px;
509
+ background: transparent;
510
+ color: var(--oa-muted-color);
511
+ display: inline-flex;
512
+ align-items: center;
513
+ justify-content: center;
514
+ }
515
+
516
+ .annotation-toolbar button:hover {
517
+ background: var(--oa-control-bg);
518
+ color: var(--oa-text-color);
519
+ }
520
+
521
+ .annotation-toolbar button.active {
522
+ background: var(--oa-accent);
523
+ color: #fff;
524
+ }
525
+
526
+ .annotation-toolbar button:disabled {
527
+ color: #aaa;
528
+ cursor: not-allowed;
529
+ }
530
+
531
+ .annotation-toolbar .separator {
532
+ border-left: 1px solid #ccc;
533
+ margin: 0 4px;
534
+ height: 20px;
535
+ display: inline-block;
536
+ vertical-align: middle;
537
+ }
538
+
539
+ .annotation-toolbar[data-orientation="vertical"] .separator {
540
+ border-left: none;
541
+ border-top: 1px solid #ccc;
542
+ width: 20px;
543
+ height: 0;
544
+ margin: 4px 0;
545
+ }
546
+
547
+ /* Tooltips, shown on hover via the `data-tooltip` attribute. */
548
+ .annotation-toolbar [data-tooltip] {
549
+ position: relative;
550
+ }
551
+
552
+ .annotation-toolbar [data-tooltip]::after {
553
+ content: attr(data-tooltip);
554
+ position: absolute;
555
+ left: 50%;
556
+ bottom: 100%;
557
+ transform: translateX(-50%) translateY(-6px);
558
+ background: rgba(0, 0, 0, 0.75);
559
+ color: #fff;
560
+ text-align: center;
561
+ white-space: nowrap;
562
+ font-size: 12px;
563
+ padding: 4px 6px;
564
+ border-radius: 5px;
565
+ pointer-events: none;
566
+ z-index: 99;
567
+ opacity: 0;
568
+ transition: opacity 0.15s;
569
+ }
570
+
571
+ .annotation-toolbar [data-tooltip]:hover::after {
572
+ opacity: 1;
573
+ }
package/dist/ui.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";var B=Object.defineProperty;var N=(r,t,e)=>t in r?B(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var a=(r,t,e)=>N(r,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("vanilla-colorful/lib/entrypoints/rgba"),l=require("./Polygon-D4SNG2xn.cjs"),m="rgba-color-picker";class F extends D.RgbaBase{}function E(){return customElements.get(m)||customElements.define(m,F),document.createElement(m)}const C=[{value:"#f5f5f5",style:"--circle-color: #f5f5f5;"},{value:"#EDE6FF",style:"--circle-color: #EDE6FF;"},{value:"transparent",style:"--circle-color: white; border: 2px dashed #ccc;"}],y=[{value:"sans-serif",label:"Sans Serif",icon:"type"},{value:"serif",label:"Serif",icon:"italic"},{value:"monospace",label:"Monospace",icon:"code"}],b=[{value:"none",label:"None",icon:"x"},{value:"arrow",label:"Open Arrow",icon:"arrow-left"},{value:"arrow-plain",label:"Filled Arrow",icon:"play"},{value:"halo-dot",label:"Halo Dot",icon:"circle-dot"},{value:"dot",label:"Dot",icon:"dot"}],k=[{value:"plain",icon:"circle"},{value:"dashed",icon:"circle-dashed"}],A=["#0099FF","#FF7523","#44AA99"];function S(r){return`rgba(${r.r}, ${r.g}, ${r.b}, ${r.a})`}const w=3;function x(){return{colors:[...A],activeIndex:0}}function T(r,t){const e=r.colors.indexOf(t);return e===-1?{colors:[t,...r.colors].slice(0,w),activeIndex:0}:{colors:r.colors,activeIndex:e}}const M={"chevron-down":'<path d="m6 9 6 6 6-6"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',"arrow-left":'<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>',"arrow-right":'<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',play:'<polygon points="6 3 20 12 6 21 6 3"/>',"circle-dot":'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="1"/>',dot:'<circle cx="12.1" cy="12.1" r="1"/>',circle:'<circle cx="12" cy="12" r="10"/>',"circle-dashed":'<path d="M10.1 2.182a10 10 0 0 1 3.8 0"/><path d="M13.9 21.818a10 10 0 0 1-3.8 0"/><path d="M17.609 3.721a10 10 0 0 1 2.69 2.7"/><path d="M2.182 13.9a10 10 0 0 1 0-3.8"/><path d="M20.279 17.609a10 10 0 0 1-2.7 2.69"/><path d="M21.818 10.1a10 10 0 0 1 0 3.8"/><path d="M3.721 6.391a10 10 0 0 1 2.7-2.69"/><path d="M6.391 20.279a10 10 0 0 1-2.69-2.7"/>',type:'<path d="M4 7V4h16v3"/><path d="M9 20h6"/><path d="M12 4v16"/>',italic:'<line x1="19" x2="10" y1="4" y2="4"/><line x1="14" x2="5" y1="20" y2="20"/><line x1="15" x2="9" y1="4" y2="20"/>',code:'<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>',trash:'<path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>',undo:'<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>',redo:'<path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"/>',pentagon:'<path d="M10.83 2.38a2 2 0 0 1 2.34 0l8 5.74a2 2 0 0 1 .73 2.25l-3.04 9.26a2 2 0 0 1-1.9 1.37H7.04a2 2 0 0 1-1.9-1.37L2.1 10.37a2 2 0 0 1 .73-2.25z"/>',"rectangle-horizontal":'<rect width="20" height="12" x="2" y="6" rx="2"/>',"message-square":'<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>',"sticky-note":'<path d="M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z"/><path d="M15 3v5a1 1 0 0 0 1 1h5"/>',eraser:'<path d="M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21"/><path d="m5.082 11.09 8.828 8.828"/>',download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',camera:'<path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/>',"rotate-cw":'<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/>',"rotate-ccw":'<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>',minimize:'<path d="M8 3v3a2 2 0 0 1-2 2H3"/><path d="M21 8h-3a2 2 0 0 1-2-2V3"/><path d="M3 16h3a2 2 0 0 1 2 2v3"/><path d="M16 21v-3a2 2 0 0 1 2-2h3"/>'};function v(r,t=18){return`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${M[r]}</svg>`}const _=150;function $(r,{onShow:t,onHide:e}){let o=null,i=null;const n=()=>{i!==null&&(clearTimeout(i),i=null)},s=()=>{n(),o&&(t(o),o=null)},c=h=>{if(n(),h.ids.length===1){const p=r.getAnnotation(h.ids[0]);if(!p)return;if(o=p,r.isDrawing()){r.once("cancelDrawing",s),r.once("completeDrawing",s);return}i=setTimeout(s,_)}else o=null,e()},d=()=>{n(),o=null,e()},u=()=>{n(),o=null,e()};return r.on("select",c),r.on("click",s),r.on("dragend",s),r.on("dragstart",d),r.on("unselect",u),()=>{n(),r.off("select",c),r.off("click",s),r.off("dragend",s),r.off("dragstart",d),r.off("unselect",u),r.off("cancelDrawing",s),r.off("completeDrawing",s)}}const P="right",L="vertical";class R{constructor(t){a(this,"control");a(this,"panel");a(this,"panelBody");a(this,"mode",null);a(this,"currentAnnotation",null);a(this,"currentColor","#0099FF");a(this,"recent",x());a(this,"colorCircles",[]);a(this,"colorPickerOverlay",null);a(this,"colorPicker",null);a(this,"detachVisibility");a(this,"documentClickHandler");a(this,"hide",()=>{this.panel.style.display="none",this.closeColorPicker(),this.currentAnnotation=null,this.mode=null});this.control=t.control;const e=t.container??document.body;this.panel=document.createElement("div"),this.panel.className="annotation-panel",this.panel.style.display="none",this.panel.dataset.placement=t.placement??P,this.panel.dataset.orientation=t.orientation??L,this.panelBody=document.createElement("div"),this.panelBody.className="panel-body",this.panel.appendChild(this.panelBody),e.appendChild(this.panel),this.detachVisibility=$(this.control,{onShow:o=>{this.setAnnotation(o),this.show()},onHide:this.hide}),["click","mousedown","mousemove"].forEach(o=>this.panel.addEventListener(o,i=>i.stopPropagation())),this.documentClickHandler=o=>{this.colorPickerOverlay&&!this.colorPickerOverlay.contains(o.target)&&!this.colorCircles.some(i=>i.contains(o.target))&&this.closeColorPicker(),this.panelBody.querySelectorAll(".custom-select").forEach(i=>i.classList.remove("open"))},document.addEventListener("click",this.documentClickHandler)}setAnnotation(t){this.currentAnnotation=t,l.isArrow(t)?(this.mode="arrow",this.renderArrow(t)):l.isText(t)||l.isBox(t)||l.isComment(t)?(this.mode="text",this.renderText(t)):l.isPolygon(t)&&(this.mode="polygon",this.renderPolygon(t))}renderArrow(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.strokeColor||l.defaultArrowStyle.strokeColor),this.panelBody.innerHTML=`
2
+ ${this.section("Color",this.colorSelector())}
3
+ ${this.section("Extremities",`<div class="custom-select-section">
4
+ ${this.extremitySelector("head",t)}
5
+ ${this.extremitySelector("tail",t)}
6
+ </div>`)}
7
+ ${this.slider("Stroke width","line-width",e.strokeWidth||l.defaultArrowStyle.strokeWidth,1,20)}
8
+ ${this.lineTypeButtons(e.strokeType||"plain")}
9
+ `,this.bind()}renderText(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.color||l.defaultTextStyle.color);const o=typeof e.fontSize=="number"?e.fontSize:typeof l.defaultTextStyle.fontSize=="number"?l.defaultTextStyle.fontSize:18;this.panelBody.innerHTML=`
10
+ ${this.section("Color",this.colorSelector())}
11
+ ${this.section("Background",this.backgroundSelector(e.background||l.defaultTextStyle.background))}
12
+ ${this.section("Font",`<div class="custom-select-section">${this.fontSelector(e.font||l.defaultTextStyle.font)}</div>`)}
13
+ ${this.slider("Font size","font-size",o,8,72)}
14
+ ${this.slider("Stroke width","line-width",e.strokeWidth||l.defaultTextStyle.strokeWidth,1,20)}
15
+ ${this.lineTypeButtons(e.strokeType||"plain")}
16
+ `,this.bind()}renderPolygon(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.strokeColor||"#000000"),this.panelBody.innerHTML=`
17
+ ${this.section("Color",this.colorSelector())}
18
+ ${this.section("Fill",this.backgroundSelector(e.background||"transparent"))}
19
+ ${this.slider("Stroke width","line-width",e.strokeWidth||2,1,20)}
20
+ ${this.lineTypeButtons(e.strokeType||"plain")}
21
+ `,this.bind()}section(t,e){return`<div class="section-header"><h3>${t}</h3></div>${e}`}icon(t,e=!1){return e?`<span style="display:inline-flex;transform:rotate(180deg)">${v(t)}</span>`:v(t)}colorSelector(){return`<div class="color-selector">${this.recent.colors.map((t,e)=>`
22
+ <button class="color-circle ${e===0?"color-circle-primary":""}" data-index="${e}" data-color="${t}">
23
+ <div class="color-inner"></div>
24
+ </button>
25
+ `).join("")}</div>`}backgroundSelector(t){return`<div class="color-selector">${C.map(({value:e,style:o})=>`
26
+ <button class="color-circle ${e===t?"color-circle-primary":""}" data-background-color="${e}">
27
+ <div class="color-inner" style="${o}"></div>
28
+ </button>
29
+ `).join("")}</div>`}fontSelector(t){const e=y.find(o=>o.value===t)||y[0];return this.dropdown("font",e,y.map(o=>({...o,selected:o.value===t})))}extremitySelector(t,e){var s;const o=((s=e.properties.style)==null?void 0:s[t])||"none",i=b.map(c=>({...c,icon:c.value==="arrow"&&t==="tail"?"arrow-left":c.value==="arrow"?"arrow-right":c.icon,selected:c.value===o,rotate:c.value==="arrow-plain"&&t==="tail"})),n=i.find(c=>c.selected)||i[0];return`<div class="extremity-wrapper"><label>${t}</label>${this.dropdown(t,n,i,`data-end="${t}"`)}</div>`}dropdown(t,e,o,i=""){return`<div class="custom-select" data-type="${t}" ${i}>
30
+ <div class="custom-select-trigger">
31
+ ${this.icon(e.icon,e.rotate)}
32
+ <span>${e.label}</span>
33
+ ${this.icon("chevron-down")}
34
+ </div>
35
+ <div class="custom-select-options">${o.map(n=>`
36
+ <div class="custom-select-option ${n.selected?"selected":""}" data-value="${n.value}" data-icon="${n.icon}" data-rotate="${n.rotate?"1":""}" title="${n.label}">
37
+ ${this.icon(n.icon,n.rotate)}
38
+ <span>${n.label}</span>
39
+ </div>
40
+ `).join("")}</div>
41
+ </div>`}slider(t,e,o,i,n){return`${this.section(t,`<div class="slider-section">
42
+ <input type="range" id="${e}-slider" class="slider" min="${i}" max="${n}" value="${o}">
43
+ <div class="slider-value"><span id="${e}-value">${o}</span></div>
44
+ </div>`)}`}lineTypeButtons(t){return`${this.section("Line type",`<div class="linetype-section">${k.map(({value:e,icon:o})=>`
45
+ <button class="linetype-button ${t===e?"active":""}" data-linetype="${e}" title="${e}">
46
+ ${this.icon(o)}
47
+ </button>
48
+ `).join("")}</div>`)}`}bind(){this.colorCircles=Array.from(this.panelBody.querySelectorAll("[data-index]")),this.colorCircles.forEach((t,e)=>{t.addEventListener("click",o=>{o.stopPropagation();const i=this.recent.activeIndex===e&&t.classList.contains("color-circle-primary");this.recent={...this.recent,activeIndex:e},this.currentColor=this.recent.colors[e],this.updateColorCircles(),i?this.toggleColorPicker(t):this.mode==="arrow"?this.updateStyle({strokeColor:this.currentColor}):this.mode==="text"&&this.updateStyle({strokeColor:this.currentColor})})}),this.updateColorCircles(),this.panelBody.querySelectorAll("[data-background-color]").forEach(t=>{t.addEventListener("click",()=>this.updateStyle({background:t.dataset.backgroundColor}))}),this.panelBody.querySelectorAll(".custom-select").forEach(t=>{const e=t.querySelector(".custom-select-trigger"),o=t.querySelectorAll(".custom-select-option");e.addEventListener("click",i=>{i.stopPropagation(),this.panelBody.querySelectorAll(".custom-select").forEach(n=>{n!==t&&n.classList.remove("open")}),t.classList.toggle("open")}),o.forEach(i=>{i.addEventListener("click",n=>{n.stopPropagation();const s=i.dataset.value;o.forEach(O=>O.classList.remove("selected")),i.classList.add("selected");const c=i.dataset.icon,d=i.dataset.rotate==="1",u=i.querySelector("span").textContent||"",h=e.querySelector("svg, span[style]");h&&(h.outerHTML=this.icon(c,d)),e.querySelector("span").textContent=u,t.classList.remove("open");const p=t.dataset.type,f=t.dataset.end;p==="font"?this.updateStyle({font:s}):f==="head"?this.updateStyle({head:s}):f==="tail"&&this.updateStyle({tail:s})})})}),["line-width","font-size"].forEach(t=>{const e=this.panelBody.querySelector(`#${t}-slider`),o=this.panelBody.querySelector(`#${t}-value`);e&&o&&e.addEventListener("input",()=>{const i=parseInt(e.value,10);o.textContent=i.toString(),t==="line-width"?this.updateStyle(this.mode==="text"?{strokeWidth:i,strokeColor:this.currentColor}:{strokeWidth:i}):t==="font-size"&&this.updateStyle({fontSize:i})})}),this.panelBody.querySelectorAll(".linetype-button").forEach(t=>{t.addEventListener("click",()=>{const e=t.dataset.linetype;this.panelBody.querySelectorAll(".linetype-button").forEach(o=>o.classList.remove("active")),t.classList.add("active"),this.updateStyle({strokeType:e})})})}updateColorFromAnnotation(t){this.recent=T(this.recent,t),this.currentColor=t}updateColorCircles(){this.colorCircles.forEach((t,e)=>{t.setAttribute("data-color",this.recent.colors[e]),t.style.setProperty("--circle-color",this.recent.colors[e]),t.classList.toggle("color-circle-primary",e===this.recent.activeIndex)})}toggleColorPicker(t){if(this.colorPickerOverlay){this.closeColorPicker();return}this.colorPickerOverlay=document.createElement("div"),this.colorPickerOverlay.className="color-picker-overlay",document.body.appendChild(this.colorPickerOverlay),this.colorPicker=E(),this.colorPicker.color=l.parseColor(this.currentColor),this.colorPickerOverlay.appendChild(this.colorPicker);const e=t.getBoundingClientRect();this.colorPickerOverlay.style.right=`${window.innerWidth-e.right}px`,this.colorPickerOverlay.style.top=`${e.bottom+10}px`,this.colorPicker.addEventListener("color-changed",o=>{this.currentColor=S(o.detail.value),this.recent.colors[this.recent.activeIndex]=this.currentColor,this.updateColorCircles(),this.mode==="arrow"?this.updateStyle({strokeColor:this.currentColor}):this.mode==="text"?this.updateStyle({color:this.currentColor}):this.mode==="polygon"&&this.updateStyle({strokeColor:this.currentColor})})}closeColorPicker(){this.colorPickerOverlay&&(this.colorPickerOverlay.remove(),this.colorPickerOverlay=null,this.colorPicker=null)}updateStyle(t){this.currentAnnotation&&(l.isArrow(this.currentAnnotation)?this.control.updateStyle(this.currentAnnotation.id,t):l.isPolygon(this.currentAnnotation)?this.control.updateStyle(this.currentAnnotation.id,t):this.control.updateStyle(this.currentAnnotation.id,t))}setPlacement(t){this.panel.dataset.placement=t}setOrientation(t){this.panel.dataset.orientation=t}show(){this.panel.style.display="block"}destroy(){this.closeColorPicker(),this.detachVisibility(),document.removeEventListener("click",this.documentClickHandler),this.panel.remove()}}const I="bottom",H="horizontal",g=["arrow","comment","sticky-note","box","text","polygon"];class q{constructor(t){a(this,"control");a(this,"root");a(this,"activeButton",null);a(this,"undoButton");a(this,"redoButton");a(this,"handleDrawingEnd",()=>this.setActiveMode(null));a(this,"handleHistory",()=>this.updateUndoRedo());this.control=t.control;const e=t.container??document.body;this.root=document.createElement("div"),this.root.className="annotation-toolbar",this.root.dataset.placement=t.placement??I,this.root.dataset.orientation=t.orientation??H,e.appendChild(this.root),["click","mousedown","mousemove"].forEach(s=>this.root.addEventListener(s,c=>c.stopPropagation()));const o=t.enabledTypes??g,i=t.styles??{};g.filter(s=>o.includes(s)).forEach(s=>this.root.appendChild(this.drawingButton(s,i))),o.length>0&&this.root.appendChild(this.separator()),this.undoButton=this.button(null,"undo","Undo",()=>this.control.undo()),this.redoButton=this.button(null,"redo","Redo",()=>this.control.redo()),this.root.appendChild(this.undoButton),this.root.appendChild(this.redoButton);const n=t.deleteMode??"erase";(n==="erase"||n==="both")&&(this.root.appendChild(this.separator()),this.root.appendChild(this.button("erase","eraser","Erase (click annotations to delete them)",()=>{this.control.isEraseModeActive()?(this.control.disableEraseMode(),this.setActiveMode(null)):(this.control.enableEraseMode(),this.setActiveMode("erase"))}))),(n==="select"||n==="both")&&(n==="select"&&this.root.appendChild(this.separator()),this.root.appendChild(this.button(null,"trash","Delete selected",()=>{const s=this.control.getSelectedAnnotations();s.features.length>0&&this.control.remove(s)}))),(t.onJsonExport||t.onSvgExport)&&(this.root.appendChild(this.separator()),t.onJsonExport&&this.root.appendChild(this.button(null,"download","Export annotations",t.onJsonExport)),t.onSvgExport&&this.root.appendChild(this.button(null,"camera","Export SVG",t.onSvgExport))),this.control.on(l.EVT_COMPLETE_DRAWING,this.handleDrawingEnd),this.control.on(l.EVT_CANCEL_DRAWING,this.handleDrawingEnd),this.control.on(l.EVT_HISTORY,this.handleHistory),this.updateUndoRedo()}drawingButton(t,e){switch(t){case"arrow":return this.button("arrow","arrow-right","Add arrow",()=>{this.control.enableArrowDrawing({strokeType:"plain",strokeColor:"#3A03CF",strokeWidth:2,head:"arrow",...e.arrow}),this.setActiveMode("arrow")});case"comment":return this.button("comment","message-square","Add comment",()=>{var n,s,c,d;const o=(n=e.comment)==null?void 0:n.commentStyle,i=(s=e.comment)==null?void 0:s.arrowStyle;this.control.enableCommentDrawing({offsetX:((c=e.comment)==null?void 0:c.offsetX)??200,offsetY:((d=e.comment)==null?void 0:d.offsetY)??-150,commentStyle:{content:"",...o,style:{color:"#3A03CF",background:"#EDE6FF",fontSize:16,font:"IBM Plex Sans",...o==null?void 0:o.style}},arrowStyle:{...i,style:{strokeType:"plain",strokeColor:"#3A03CF",strokeWidth:2,head:"halo-dot",...i==null?void 0:i.style}}}),this.setActiveMode("comment")});case"sticky-note":return this.button("sticky-note","sticky-note","Add sticky note",()=>{this.control.enableStickyNoteDrawing({...e.stickyNote}),this.setActiveMode("sticky-note")});case"box":return this.button("box","rectangle-horizontal","Add box",()=>{this.control.enableBoxDrawing({background:"#EDE6FF",borderRadius:8,padding:12,...e.box}),this.setActiveMode("box")});case"text":return this.button("text","type","Add text",()=>{this.control.enableTextDrawing({font:"IBM Plex Sans",fontSize:24,color:"#3A03CF",background:"#EDE6FF",borderRadius:8,padding:12,...e.text}),this.setActiveMode("text")});case"polygon":return this.button("polygon","pentagon","Add polygon (click points, Esc to finish)",()=>{this.control.enablePolygonDrawing({strokeColor:"#3A03CF",strokeWidth:2,background:"rgba(58, 3, 207, 0.15)",...e.polygon}),this.setActiveMode("polygon")})}}button(t,e,o,i){const n=document.createElement("button");return n.dataset.tooltip=o,n.innerHTML=v(e,16),n.addEventListener("click",i),t&&(n.dataset.mode=t),n}separator(){const t=document.createElement("span");return t.className="separator",t}setActiveMode(t){this.activeButton&&this.activeButton.classList.remove("active"),this.activeButton=t?this.root.querySelector(`[data-mode="${t}"]`):null,this.activeButton&&this.activeButton.classList.add("active")}updateUndoRedo(){this.undoButton.disabled=!this.control.canUndo(),this.redoButton.disabled=!this.control.canRedo()}setPlacement(t){this.root.dataset.placement=t}setOrientation(t){this.root.dataset.orientation=t}destroy(){this.control.off(l.EVT_COMPLETE_DRAWING,this.handleDrawingEnd),this.control.off(l.EVT_CANCEL_DRAWING,this.handleDrawingEnd),this.control.off(l.EVT_HISTORY,this.handleHistory),this.root.remove()}}exports.AnnotationPanel=R;exports.AnnotationToolbar=q;exports.BACKGROUNDS=C;exports.DEFAULT_PANEL_ORIENTATION=L;exports.DEFAULT_PANEL_PLACEMENT=P;exports.DEFAULT_RECENT_COLORS=A;exports.EXTREMITY_OPTIONS=b;exports.FONTS=y;exports.ICON_PATHS=M;exports.LINE_TYPES=k;exports.MAX_RECENT_COLORS=w;exports.attachPanelVisibility=$;exports.createRgbaColorPicker=E;exports.initialRecentColors=x;exports.rgbaToString=S;exports.svgIcon=v;exports.withColorFromAnnotation=T;