@linkurious/ogma-annotations 2.1.1 → 2.1.3
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.
- package/dist/{Polygon-DVFVmDbR.js → Polygon-C9ZkyU-t.js} +330 -306
- package/dist/index.js +9 -9
- package/dist/index.mjs +5033 -4431
- package/dist/types/Control-BiYdzv0K.d.ts +1609 -0
- package/dist/types/index.d.ts +271 -1851
- package/dist/types/ui.d.ts +742 -1415
- package/dist/ui-styles.css +308 -46
- package/dist/ui.js +17 -17
- package/dist/ui.mjs +572 -166
- package/package.json +10 -7
package/dist/ui-styles.css
CHANGED
|
@@ -481,93 +481,355 @@ input:checked + .toggle-slider:before {
|
|
|
481
481
|
display: none;
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
-
/* ---
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
484
|
+
/* --- Shared horizontal-toolbar system ---
|
|
485
|
+
`.oa-toolbar` is a bare marker class every toolbar bar in both packages
|
|
486
|
+
carries alongside its own root class (`.annotation-toolbar`,
|
|
487
|
+
`.annotation-style-toolbar`, React's `.add-menu`/`.view-controls`) -
|
|
488
|
+
it sets no properties of its own, it just wires up the shared tooltip
|
|
489
|
+
system below with a single selector instead of a 4-way list. `AddMenu`/
|
|
490
|
+
`ViewControls` keep their own bar layout and button visuals entirely
|
|
491
|
+
(`packages/react/src/ui/toolbar.css`) - only the marker is shared with
|
|
492
|
+
them. `.oa-toolbar-bar` is the actual shared bar layout, a *second*
|
|
493
|
+
class added only where core's own two toolbars want to look/behave
|
|
494
|
+
alike (row of small inset buttons) - kept separate from the marker so
|
|
495
|
+
applying it can't leak into `AddMenu`/`ViewControls`'s different design. */
|
|
496
|
+
.oa-toolbar-bar {
|
|
488
497
|
display: flex;
|
|
489
498
|
align-items: center;
|
|
490
|
-
|
|
491
|
-
|
|
499
|
+
flex-direction: row;
|
|
500
|
+
gap: 3px;
|
|
501
|
+
padding: 0 4px;
|
|
502
|
+
min-height: 40px;
|
|
492
503
|
}
|
|
493
504
|
|
|
494
505
|
.annotation-toolbar[data-orientation="vertical"] {
|
|
495
506
|
flex-direction: column;
|
|
496
507
|
}
|
|
497
508
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
margin:
|
|
505
|
-
padding:
|
|
509
|
+
/* Small inset button - used for every plain toolbar action/toggle
|
|
510
|
+
(AnnotationToolbar's drawing/undo/redo/erase/delete buttons,
|
|
511
|
+
TextAnnotationToolbar's Bold/Delete/author-toggle cells, a dropdown's
|
|
512
|
+
trigger). `position: relative` doubles as the tooltip's anchor. */
|
|
513
|
+
.oa-toolbar-button {
|
|
514
|
+
position: relative;
|
|
515
|
+
margin: 1px;
|
|
516
|
+
padding: 4px;
|
|
506
517
|
border: 1px solid transparent;
|
|
507
518
|
cursor: pointer;
|
|
508
519
|
border-radius: 5px;
|
|
509
520
|
background: transparent;
|
|
510
|
-
color: var(--oa-muted-color);
|
|
521
|
+
color: var(--oa-muted-color, #666);
|
|
511
522
|
display: inline-flex;
|
|
512
523
|
align-items: center;
|
|
513
524
|
justify-content: center;
|
|
525
|
+
gap: 4px;
|
|
514
526
|
}
|
|
515
527
|
|
|
516
|
-
.
|
|
517
|
-
background: var(--oa-control-bg);
|
|
518
|
-
color: var(--oa-text-color);
|
|
528
|
+
.oa-toolbar-button:hover {
|
|
529
|
+
background: var(--oa-control-bg, #eee);
|
|
530
|
+
color: var(--oa-text-color, #333);
|
|
519
531
|
}
|
|
520
532
|
|
|
521
|
-
.
|
|
522
|
-
background: var(--oa-accent);
|
|
533
|
+
.oa-toolbar-button.active {
|
|
534
|
+
background: var(--oa-accent, #3a03cf);
|
|
523
535
|
color: #fff;
|
|
524
536
|
}
|
|
525
537
|
|
|
526
|
-
.
|
|
538
|
+
.oa-toolbar-button:disabled {
|
|
527
539
|
color: #aaa;
|
|
528
540
|
cursor: not-allowed;
|
|
529
541
|
}
|
|
530
542
|
|
|
531
|
-
.
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
543
|
+
.oa-toolbar-button-danger:hover {
|
|
544
|
+
color: #d92d20;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/* `align-self: stretch` (not a hardcoded height) so the divider always
|
|
548
|
+
matches the bar's actual height - driven by `.oa-toolbar-bar`'s
|
|
549
|
+
`min-height: 40px` today, but this way it can't fall out of sync if that
|
|
550
|
+
number ever changes. */
|
|
551
|
+
.oa-toolbar-separator {
|
|
552
|
+
border-left: 1px solid var(--oa-toolbar-divider, #ccc);
|
|
553
|
+
margin: 0 3px;
|
|
554
|
+
align-self: stretch;
|
|
537
555
|
}
|
|
538
556
|
|
|
539
|
-
.annotation-toolbar[data-orientation="vertical"] .separator {
|
|
557
|
+
.annotation-toolbar[data-orientation="vertical"] .oa-toolbar-separator {
|
|
540
558
|
border-left: none;
|
|
541
|
-
border-top: 1px solid #ccc;
|
|
559
|
+
border-top: 1px solid var(--oa-toolbar-divider, #ccc);
|
|
560
|
+
align-self: auto;
|
|
542
561
|
width: 20px;
|
|
543
562
|
height: 0;
|
|
544
|
-
margin:
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
/* Tooltips, shown on hover via the `data-tooltip` attribute
|
|
548
|
-
|
|
563
|
+
margin: 3px 0;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* Tooltips, shown on hover via the `data-tooltip` attribute - one
|
|
567
|
+
definition shared by every toolbar in both packages (anything carrying
|
|
568
|
+
`.oa-toolbar`; React's `AddMenu`/`ViewControls` import this stylesheet
|
|
569
|
+
wholesale, see `packages/react/src/ui/styles.css`, and add no tooltip CSS
|
|
570
|
+
of their own). Previously each toolbar had its own near-duplicate block
|
|
571
|
+
(slightly different colors/radius/offsets, addressed by an earlier
|
|
572
|
+
4-selector-list version of this comment); worth keeping as one rule set
|
|
573
|
+
so they can't drift out of sync, or - as happened once - collide when a
|
|
574
|
+
scoped and an unscoped copy both matched the same element and fought
|
|
575
|
+
over properties neither set (see the git history on this block for
|
|
576
|
+
that). Dark pill + pointer triangle, matching the Figma "Sticky Note
|
|
577
|
+
Toolbar" spec `TextAnnotationToolbar`'s cells were originally built
|
|
578
|
+
against. */
|
|
579
|
+
.oa-toolbar [data-tooltip] {
|
|
549
580
|
position: relative;
|
|
550
581
|
}
|
|
551
582
|
|
|
552
|
-
.
|
|
553
|
-
|
|
583
|
+
.oa-toolbar [data-tooltip]::after,
|
|
584
|
+
.oa-toolbar [data-tooltip]::before {
|
|
554
585
|
position: absolute;
|
|
555
586
|
left: 50%;
|
|
556
587
|
bottom: 100%;
|
|
557
|
-
transform: translateX(-50%)
|
|
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;
|
|
588
|
+
transform: translateX(-50%);
|
|
565
589
|
pointer-events: none;
|
|
566
|
-
z-index: 99;
|
|
567
590
|
opacity: 0;
|
|
568
591
|
transition: opacity 0.15s;
|
|
592
|
+
z-index: 99;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/* margin-bottom (not `bottom: calc(100% - Npx)` + a shared translateY) so
|
|
596
|
+
the pill and the triangle below it stack with a clean, exact seam - the
|
|
597
|
+
triangle's `border` trick makes its box 0-height, so its margin-bottom
|
|
598
|
+
directly sets the gap between the pill's bottom edge and the target;
|
|
599
|
+
getting this via two competing `bottom`/`transform` offsets previously
|
|
600
|
+
left the triangle's flat top 2px inside the pill's own box, where the
|
|
601
|
+
pill (painted after, per pseudo-element order) covered all but a sliver
|
|
602
|
+
of it - functionally invisible. */
|
|
603
|
+
.oa-toolbar [data-tooltip]::after {
|
|
604
|
+
content: attr(data-tooltip);
|
|
605
|
+
margin-bottom: 8px;
|
|
606
|
+
background: var(--oa-tooltip-bg, #303030);
|
|
607
|
+
color: var(--oa-tooltip-fg, #ffffff);
|
|
608
|
+
white-space: nowrap;
|
|
609
|
+
font-size: 12px;
|
|
610
|
+
padding: 4px 8px;
|
|
611
|
+
border-radius: 4px;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.oa-toolbar [data-tooltip]::before {
|
|
615
|
+
content: "";
|
|
616
|
+
margin-bottom: 0px;
|
|
617
|
+
border: 4px solid transparent;
|
|
618
|
+
border-top-color: var(--oa-tooltip-bg, #303030);
|
|
569
619
|
}
|
|
570
620
|
|
|
571
|
-
.
|
|
621
|
+
.oa-toolbar [data-tooltip]:hover::after,
|
|
622
|
+
.oa-toolbar [data-tooltip]:hover::before {
|
|
572
623
|
opacity: 1;
|
|
573
624
|
}
|
|
625
|
+
|
|
626
|
+
/* --- Floating text-annotation toolbar (TextAnnotationToolbar) ---
|
|
627
|
+
Anchored above the selected Text/sticky-note annotation via an Ogma
|
|
628
|
+
overlay layer, not docked like `.annotation-panel`/`.annotation-toolbar`
|
|
629
|
+
above. `.annotation-style-toolbar-anchor` is the element handed to
|
|
630
|
+
`ogma.layers.addOverlay()` - Ogma writes its own `transform`
|
|
631
|
+
(translate/rotate/scale) onto it directly on every pan/zoom/rotate, so it
|
|
632
|
+
must stay zero-size and untouched by our own CSS `transform`.
|
|
633
|
+
`.annotation-style-toolbar` (the actual visible pill, a child of the
|
|
634
|
+
anchor) carries all the positioning that's ours to set - centered
|
|
635
|
+
horizontally and lifted fully above the anchor point - plus every visual
|
|
636
|
+
rule. Keeping the two separate is what avoids fighting Ogma for control
|
|
637
|
+
of one element's `transform` property.
|
|
638
|
+
|
|
639
|
+
z-index: this overlay is a sibling of every other Ogma layer inside the
|
|
640
|
+
same container (Shapes, the resize-Handles canvas, a TextArea edit
|
|
641
|
+
overlay) - without an explicit z-index it paints in creation order,
|
|
642
|
+
which (Handles is created once, early, at Control construction, long
|
|
643
|
+
before any selection) puts it *underneath* the note it's editing and
|
|
644
|
+
the resize handles around it. `Handles` (`renderer/handles.ts`) hits the
|
|
645
|
+
same problem the other way and fixes it the same way: a permanent CSS
|
|
646
|
+
z-index, no reordering. 1000 is Handles' own value (to stay above a
|
|
647
|
+
TextArea edit overlay); this needs to beat *that*, hence 1100. */
|
|
648
|
+
.annotation-style-toolbar-anchor {
|
|
649
|
+
position: relative;
|
|
650
|
+
width: 0;
|
|
651
|
+
height: 0;
|
|
652
|
+
z-index: 1100;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/* Slide-up-and-fade on appear. A fresh `.annotation-style-toolbar` element
|
|
656
|
+
is created every time the pill (re)appears (see `AnnotationStyleToolbar`
|
|
657
|
+
- `TextAnnotationToolbar` destroys and recreates it, never reuses one
|
|
658
|
+
across a hide/show), so this just replays naturally on each mount - no
|
|
659
|
+
JS needed. Only animates `transform`/`opacity`, which are exclusively
|
|
660
|
+
this element's own (Ogma only ever touches its parent
|
|
661
|
+
`.annotation-style-toolbar-anchor`'s transform - see that rule's own
|
|
662
|
+
comment), so there's nothing here to fight for control of either
|
|
663
|
+
property. */
|
|
664
|
+
@keyframes oa-toolbar-pop-in {
|
|
665
|
+
from {
|
|
666
|
+
opacity: 0;
|
|
667
|
+
transform: translate(-50%, calc(-100% + 6px));
|
|
668
|
+
}
|
|
669
|
+
to {
|
|
670
|
+
opacity: 1;
|
|
671
|
+
transform: translate(-50%, -100%);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.annotation-style-toolbar {
|
|
676
|
+
--oa-toolbar-bg: #ffffff;
|
|
677
|
+
--oa-toolbar-radius: 12px;
|
|
678
|
+
--oa-toolbar-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
|
|
679
|
+
|
|
680
|
+
position: absolute;
|
|
681
|
+
left: 0;
|
|
682
|
+
top: 0;
|
|
683
|
+
transform: translate(-50%, -100%);
|
|
684
|
+
animation: oa-toolbar-pop-in 150ms ease-out;
|
|
685
|
+
|
|
686
|
+
background: var(--oa-toolbar-bg);
|
|
687
|
+
border-radius: var(--oa-toolbar-radius);
|
|
688
|
+
box-shadow: var(--oa-toolbar-shadow);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
@media (prefers-reduced-motion: reduce) {
|
|
692
|
+
.annotation-style-toolbar {
|
|
693
|
+
animation: none;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/* The dropdown cells' (Color, Font family, Font size) outer wrapper - just
|
|
698
|
+
a popover-positioning context, all visible styling is on
|
|
699
|
+
`.oa-toolbar-dropdown-trigger` (an `.oa-toolbar-button`) inside it. */
|
|
700
|
+
.oa-toolbar-dropdown {
|
|
701
|
+
position: relative;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.oa-toolbar-dropdown-trigger {
|
|
705
|
+
font-size: 14px;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.oa-toolbar-dropdown-label:empty {
|
|
709
|
+
display: none;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
.oa-toolbar-dropdown-chevron {
|
|
713
|
+
display: inline-flex;
|
|
714
|
+
transition: transform 0.15s;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.oa-toolbar-dropdown.open .oa-toolbar-dropdown-chevron {
|
|
718
|
+
transform: rotate(180deg);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.oa-toolbar-dropdown-panel {
|
|
722
|
+
display: none;
|
|
723
|
+
position: absolute;
|
|
724
|
+
top: calc(100% + 8px);
|
|
725
|
+
left: 50%;
|
|
726
|
+
transform: translateX(-50%);
|
|
727
|
+
background: var(--oa-toolbar-bg);
|
|
728
|
+
border-radius: 8px;
|
|
729
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
|
730
|
+
padding: 8px;
|
|
731
|
+
z-index: 1;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.oa-toolbar-dropdown.open .oa-toolbar-dropdown-panel {
|
|
735
|
+
display: block;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.oa-toolbar-dropdown-option {
|
|
739
|
+
display: block;
|
|
740
|
+
width: 100%;
|
|
741
|
+
border: none;
|
|
742
|
+
background: transparent;
|
|
743
|
+
cursor: pointer;
|
|
744
|
+
padding: 6px 12px;
|
|
745
|
+
font-size: 14px;
|
|
746
|
+
text-align: left;
|
|
747
|
+
white-space: nowrap;
|
|
748
|
+
border-radius: 4px;
|
|
749
|
+
color: var(--oa-text-color, #333);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.oa-toolbar-dropdown-option:hover {
|
|
753
|
+
background: var(--oa-control-bg, #eee);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/* Color cell */
|
|
757
|
+
.oa-toolbar-swatch {
|
|
758
|
+
--oa-swatch-fill: #fff;
|
|
759
|
+
width: 20px;
|
|
760
|
+
height: 20px;
|
|
761
|
+
border-radius: 50%;
|
|
762
|
+
background: var(--oa-swatch-fill);
|
|
763
|
+
border: 1px solid rgba(0, 0, 0, 0.25);
|
|
764
|
+
flex-shrink: 0;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
.oa-toolbar-swatch-grid {
|
|
768
|
+
display: grid;
|
|
769
|
+
grid-template-columns: repeat(3, 28px);
|
|
770
|
+
gap: 4px;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.oa-toolbar-swatch-cell {
|
|
774
|
+
--oa-swatch-fill: #fff;
|
|
775
|
+
--oa-swatch-stroke: #ccc;
|
|
776
|
+
width: 28px;
|
|
777
|
+
height: 28px;
|
|
778
|
+
border-radius: 2px;
|
|
779
|
+
border: none;
|
|
780
|
+
background: #fff;
|
|
781
|
+
cursor: pointer;
|
|
782
|
+
display: flex;
|
|
783
|
+
align-items: center;
|
|
784
|
+
justify-content: center;
|
|
785
|
+
padding: 0;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.oa-toolbar-swatch-cell::after {
|
|
789
|
+
content: "";
|
|
790
|
+
width: 20px;
|
|
791
|
+
height: 20px;
|
|
792
|
+
border-radius: 50%;
|
|
793
|
+
background: var(--oa-swatch-fill);
|
|
794
|
+
border: 1px solid var(--oa-swatch-stroke);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* "transparent" swatch - a checkerboard circle instead of a solid fill
|
|
798
|
+
(which, for `background: transparent`, would be indistinguishable from
|
|
799
|
+
an empty/missing swatch against the white cell/trigger behind it). Same
|
|
800
|
+
"no fill" convention `ui/config.ts`'s `BACKGROUNDS` already uses for the
|
|
801
|
+
docked `AnnotationPanel`, just drawn instead of dashed-bordered since
|
|
802
|
+
these swatches are filled circles, not outlined ones. */
|
|
803
|
+
.oa-toolbar-swatch-transparent,
|
|
804
|
+
.oa-toolbar-swatch-cell-transparent::after {
|
|
805
|
+
background-image: conic-gradient(
|
|
806
|
+
#ccc 90deg,
|
|
807
|
+
transparent 90deg 180deg,
|
|
808
|
+
#ccc 180deg 270deg,
|
|
809
|
+
transparent 270deg
|
|
810
|
+
);
|
|
811
|
+
background-size: 8px 8px;
|
|
812
|
+
background-color: #fff;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.oa-toolbar-more-colors {
|
|
816
|
+
display: block;
|
|
817
|
+
width: 100%;
|
|
818
|
+
margin-top: 8px;
|
|
819
|
+
border: none;
|
|
820
|
+
border-top: 1px solid var(--oa-toolbar-divider, #ccc);
|
|
821
|
+
background: transparent;
|
|
822
|
+
cursor: pointer;
|
|
823
|
+
padding: 8px 4px 0;
|
|
824
|
+
font-size: 13px;
|
|
825
|
+
color: var(--oa-muted-color, #666);
|
|
826
|
+
text-align: center;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
.oa-toolbar-more-colors:hover {
|
|
830
|
+
color: var(--oa-text-color, #333);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.oa-toolbar-more-colors-host {
|
|
834
|
+
margin-top: 8px;
|
|
835
|
+
}
|
package/dist/ui.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var j=Object.defineProperty;var X=(s,t,e)=>t in s?j(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var r=(s,t,e)=>X(s,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const K=require("vanilla-colorful/lib/entrypoints/rgba"),c=require("./Polygon-DVGwsFvt.cjs"),C="rgba-color-picker";class J extends K.RgbaBase{}function k(){return customElements.get(C)||customElements.define(C,J),document.createElement(C)}const x=[{value:"#f5f5f5",style:"--circle-color: #f5f5f5;"},{value:"#EDE6FF",style:"--circle-color: #EDE6FF;"},{value:"transparent",style:"--circle-color: white; border: 2px dashed #ccc;"}],g=[{value:"sans-serif",label:"Sans Serif",icon:"type"},{value:"serif",label:"Serif",icon:"italic"},{value:"monospace",label:"Monospace",icon:"code"}],P=[{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"}],L=[{value:"plain",icon:"circle"},{value:"dashed",icon:"circle-dashed"}],M=["#0099FF","#FF7523","#44AA99"];function E(s){return`rgba(${s.r}, ${s.g}, ${s.b}, ${s.a})`}const N=3;function $(){return{colors:[...M],activeIndex:0}}function F(s,t){const e=s.colors.indexOf(t);return e===-1?{colors:[t,...s.colors].slice(0,N),activeIndex:0}:{colors:s.colors,activeIndex:e}}const O={"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"/>',bold:'<path d="M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8"/>',user:'<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',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 y(s,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">${O[s]}</svg>`}const Z=150;function A(s,{onShow:t,onHide:e,hideWhenNotEditable:o=!0}){const n=u=>!o||s.isAnnotationEditable(u);let i=null,a=null,h=null,p=null;const d=()=>{p!==null&&(clearTimeout(p),p=null)},l=()=>{if(d(),i){const u=i;i=null,n(u.id)?(a=u,t(u)):m();return}if(!a&&h!=null){const u=s.getAnnotation(h);u&&n(u.id)&&(a=u,t(u))}},m=()=>{d(),i=null,a=null,e()},f=u=>{if(d(),u.ids.length===1){const b=s.getAnnotation(u.ids[0]);if(!b)return;if(h=u.ids[0],i=b,s.isDrawing()){s.once("cancelDrawing",l),s.once("completeDrawing",l);return}p=setTimeout(l,Z)}else h=null,m()},v=()=>m(),w=u=>{const b=i??a;b&&!u.ids.includes(b.id)||(h=null,m())};return s.on("select",f),s.on("click",l),s.on("dragend",l),s.on("dragstart",v),s.on("unselect",w),()=>{d(),s.off("select",f),s.off("click",l),s.off("dragend",l),s.off("dragstart",v),s.off("unselect",w),s.off("cancelDrawing",l),s.off("completeDrawing",l)}}const B="right",I="vertical",_=["arrow","text","box","comment","polygon"];function D(s){return c.isArrow(s)?"arrow":c.isText(s)?"text":c.isBox(s)?"box":c.isComment(s)?"comment":c.isPolygon(s)?"polygon":null}class Q{constructor(t){r(this,"control");r(this,"panel");r(this,"panelBody");r(this,"mode",null);r(this,"currentAnnotation",null);r(this,"currentColor","#0099FF");r(this,"recent",$());r(this,"colorCircles",[]);r(this,"colorPickerOverlay",null);r(this,"colorPicker",null);r(this,"detachVisibility");r(this,"documentClickHandler");r(this,"enabledTypes");r(this,"hide",()=>{this.panel.style.display="none",this.closeColorPicker(),this.currentAnnotation=null,this.mode=null});this.control=t.control,this.enabledTypes=t.enabledTypes??_;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??B,this.panel.dataset.orientation=t.orientation??I,this.panelBody=document.createElement("div"),this.panelBody.className="panel-body",this.panel.appendChild(this.panelBody),e.appendChild(this.panel),this.detachVisibility=A(this.control,{onShow:o=>{const n=D(o);if(!n||!this.enabledTypes.includes(n)){this.hide();return}this.setAnnotation(o),this.show()},onHide:this.hide,hideWhenNotEditable:t.hideWhenNotEditable}),["click","mousedown","mousemove"].forEach(o=>this.panel.addEventListener(o,n=>n.stopPropagation())),this.documentClickHandler=o=>{this.colorPickerOverlay&&!this.colorPickerOverlay.contains(o.target)&&!this.colorCircles.some(n=>n.contains(o.target))&&this.closeColorPicker(),this.panelBody.querySelectorAll(".custom-select").forEach(n=>n.classList.remove("open"))},document.addEventListener("click",this.documentClickHandler)}setAnnotation(t){this.currentAnnotation=t,c.isArrow(t)?(this.mode="arrow",this.renderArrow(t)):c.isText(t)||c.isBox(t)||c.isComment(t)?(this.mode="text",this.renderText(t)):c.isPolygon(t)&&(this.mode="polygon",this.renderPolygon(t))}renderArrow(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.strokeColor||c.defaultArrowStyle.strokeColor),this.panelBody.innerHTML=`
|
|
2
2
|
${this.section("Color",this.colorSelector())}
|
|
3
3
|
${this.section("Extremities",`<div class="custom-select-section">
|
|
4
4
|
${this.extremitySelector("head",t)}
|
|
5
5
|
${this.extremitySelector("tail",t)}
|
|
6
6
|
</div>`)}
|
|
7
|
-
${this.slider("Stroke width","line-width",e.strokeWidth||
|
|
7
|
+
${this.slider("Stroke width","line-width",e.strokeWidth||c.defaultArrowStyle.strokeWidth,1,20)}
|
|
8
8
|
${this.lineTypeButtons(e.strokeType||"plain")}
|
|
9
|
-
`,this.bind()}renderText(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.color||
|
|
9
|
+
`,this.bind()}renderText(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.color||c.defaultTextStyle.color);const o=typeof e.fontSize=="number"?e.fontSize:typeof c.defaultTextStyle.fontSize=="number"?c.defaultTextStyle.fontSize:18;this.panelBody.innerHTML=`
|
|
10
10
|
${this.section("Color",this.colorSelector())}
|
|
11
|
-
${this.section("Background",this.backgroundSelector(e.background||
|
|
12
|
-
${this.section("Font",`<div class="custom-select-section">${this.fontSelector(e.font||
|
|
11
|
+
${this.section("Background",this.backgroundSelector(e.background||c.defaultTextStyle.background))}
|
|
12
|
+
${this.section("Font",`<div class="custom-select-section">${this.fontSelector(e.font||c.defaultTextStyle.font)}</div>`)}
|
|
13
13
|
${this.slider("Font size","font-size",o,8,72)}
|
|
14
|
-
${this.slider("Stroke width","line-width",e.strokeWidth||
|
|
14
|
+
${this.slider("Stroke width","line-width",e.strokeWidth||c.defaultTextStyle.strokeWidth,1,20)}
|
|
15
15
|
${this.lineTypeButtons(e.strokeType||"plain")}
|
|
16
16
|
`,this.bind()}renderPolygon(t){const e=t.properties.style||{};this.updateColorFromAnnotation(e.strokeColor||"#000000"),this.panelBody.innerHTML=`
|
|
17
17
|
${this.section("Color",this.colorSelector())}
|
|
18
18
|
${this.section("Fill",this.backgroundSelector(e.background||"transparent"))}
|
|
19
19
|
${this.slider("Stroke width","line-width",e.strokeWidth||2,1,20)}
|
|
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)">${
|
|
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)">${y(t)}</span>`:y(t)}colorSelector(){return`<div class="color-selector">${this.recent.colors.map((t,e)=>`
|
|
22
22
|
<button class="color-circle ${e===0?"color-circle-primary":""}" data-index="${e}" data-color="${t}">
|
|
23
23
|
<div class="color-inner"></div>
|
|
24
24
|
</button>
|
|
25
|
-
`).join("")}</div>`}backgroundSelector(t){return`<div class="color-selector">${
|
|
25
|
+
`).join("")}</div>`}backgroundSelector(t){return`<div class="color-selector">${x.map(({value:e,style:o})=>`
|
|
26
26
|
<button class="color-circle ${e===t?"color-circle-primary":""}" data-background-color="${e}">
|
|
27
27
|
<div class="color-inner" style="${o}"></div>
|
|
28
28
|
</button>
|
|
29
|
-
`).join("")}</div>`}fontSelector(t){const e=
|
|
29
|
+
`).join("")}</div>`}fontSelector(t){const e=g.find(o=>o.value===t)||g[0];return this.dropdown("font",e,g.map(o=>({...o,selected:o.value===t})))}extremitySelector(t,e){var a;const o=((a=e.properties.style)==null?void 0:a[t])||"none",n=P.map(h=>({...h,icon:h.value==="arrow"&&t==="tail"?"arrow-left":h.value==="arrow"?"arrow-right":h.icon,selected:h.value===o,rotate:h.value==="arrow-plain"&&t==="tail"})),i=n.find(h=>h.selected)||n[0];return`<div class="extremity-wrapper"><label>${t}</label>${this.dropdown(t,i,n,`data-end="${t}"`)}</div>`}dropdown(t,e,o,n=""){return`<div class="custom-select" data-type="${t}" ${n}>
|
|
30
30
|
<div class="custom-select-trigger">
|
|
31
31
|
${this.icon(e.icon,e.rotate)}
|
|
32
32
|
<span>${e.label}</span>
|
|
33
33
|
${this.icon("chevron-down")}
|
|
34
34
|
</div>
|
|
35
|
-
<div class="custom-select-options">${o.map(
|
|
36
|
-
<div class="custom-select-option ${
|
|
37
|
-
${this.icon(
|
|
38
|
-
<span>${
|
|
35
|
+
<div class="custom-select-options">${o.map(i=>`
|
|
36
|
+
<div class="custom-select-option ${i.selected?"selected":""}" data-value="${i.value}" data-icon="${i.icon}" data-rotate="${i.rotate?"1":""}" title="${i.label}">
|
|
37
|
+
${this.icon(i.icon,i.rotate)}
|
|
38
|
+
<span>${i.label}</span>
|
|
39
39
|
</div>
|
|
40
40
|
`).join("")}</div>
|
|
41
|
-
</div>`}slider(t,e,o,i
|
|
42
|
-
<input type="range" id="${e}-slider" class="slider" min="${
|
|
41
|
+
</div>`}slider(t,e,o,n,i){return`${this.section(t,`<div class="slider-section">
|
|
42
|
+
<input type="range" id="${e}-slider" class="slider" min="${n}" max="${i}" value="${o}">
|
|
43
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">${
|
|
44
|
+
</div>`)}`}lineTypeButtons(t){return`${this.section("Line type",`<div class="linetype-section">${L.map(({value:e,icon:o})=>`
|
|
45
45
|
<button class="linetype-button ${t===e?"active":""}" data-linetype="${e}" title="${e}">
|
|
46
46
|
${this.icon(o)}
|
|
47
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;
|
|
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 n=this.recent.activeIndex===e&&t.classList.contains("color-circle-primary");this.recent={...this.recent,activeIndex:e},this.currentColor=this.recent.colors[e],this.updateColorCircles(),n?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",n=>{n.stopPropagation(),this.panelBody.querySelectorAll(".custom-select").forEach(i=>{i!==t&&i.classList.remove("open")}),t.classList.toggle("open")}),o.forEach(n=>{n.addEventListener("click",i=>{i.stopPropagation();const a=n.dataset.value;o.forEach(v=>v.classList.remove("selected")),n.classList.add("selected");const h=n.dataset.icon,p=n.dataset.rotate==="1",d=n.querySelector("span").textContent||"",l=e.querySelector("svg, span[style]");l&&(l.outerHTML=this.icon(h,p)),e.querySelector("span").textContent=d,t.classList.remove("open");const m=t.dataset.type,f=t.dataset.end;m==="font"?this.updateStyle({font:a}):f==="head"?this.updateStyle({head:a}):f==="tail"&&this.updateStyle({tail:a})})})}),["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 n=parseInt(e.value,10);o.textContent=n.toString(),t==="line-width"?this.updateStyle(this.mode==="text"?{strokeWidth:n,strokeColor:this.currentColor}:{strokeWidth:n}):t==="font-size"&&this.updateStyle({fontSize:n})})}),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=F(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=k(),this.colorPicker.color=c.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=E(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&&(c.isArrow(this.currentAnnotation)?this.control.updateStyle(this.currentAnnotation.id,t):c.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 tt="bottom",et="horizontal",T=["arrow","comment","sticky-note","box","text","polygon"];class ot{constructor(t){r(this,"control");r(this,"root");r(this,"activeButton",null);r(this,"undoButton");r(this,"redoButton");r(this,"handleDrawingEnd",()=>this.setActiveMode(null));r(this,"handleHistory",()=>this.updateUndoRedo());this.control=t.control;const e=t.container??document.body;this.root=document.createElement("div"),this.root.className="annotation-toolbar oa-toolbar oa-toolbar-bar",this.root.dataset.placement=t.placement??tt,this.root.dataset.orientation=t.orientation??et,e.appendChild(this.root),["click","mousedown","mousemove"].forEach(a=>this.root.addEventListener(a,h=>h.stopPropagation()));const o=t.enabledTypes??T,n=t.styles??{};T.filter(a=>o.includes(a)).forEach(a=>this.root.appendChild(this.drawingButton(a,n))),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 i=t.deleteMode??"erase";(i==="erase"||i==="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"))}))),(i==="select"||i==="both")&&(i==="select"&&this.root.appendChild(this.separator()),this.root.appendChild(this.button(null,"trash","Delete selected",()=>{const h=this.control.getSelectedAnnotations().features.filter(p=>this.control.isAnnotationEditable(p.id));h.length>0&&this.control.remove({type:"FeatureCollection",features:h})}))),(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(c.EVT_COMPLETE_DRAWING,this.handleDrawingEnd),this.control.on(c.EVT_CANCEL_DRAWING,this.handleDrawingEnd),this.control.on(c.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 i,a,h,p;const o=(i=e.comment)==null?void 0:i.commentStyle,n=(a=e.comment)==null?void 0:a.arrowStyle;this.control.enableCommentDrawing({offsetX:((h=e.comment)==null?void 0:h.offsetX)??200,offsetY:((p=e.comment)==null?void 0:p.offsetY)??-150,commentStyle:{content:"",...o,style:{color:"#3A03CF",background:"#EDE6FF",fontSize:16,font:"IBM Plex Sans",...o==null?void 0:o.style}},arrowStyle:{...n,style:{strokeType:"plain",strokeColor:"#3A03CF",strokeWidth:2,head:"halo-dot",...n==null?void 0:n.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,n){const i=document.createElement("button");return i.className="oa-toolbar-button",i.dataset.tooltip=o,i.innerHTML=y(e,16),i.addEventListener("click",n),t&&(i.dataset.mode=t),i}separator(){const t=document.createElement("span");return t.className="oa-toolbar-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(c.EVT_COMPLETE_DRAWING,this.handleDrawingEnd),this.control.off(c.EVT_CANCEL_DRAWING,this.handleDrawingEnd),this.control.off(c.EVT_HISTORY,this.handleHistory),this.root.remove()}}class H{constructor(t,e){r(this,"element");r(this,"onClick",()=>{this.item.action(this.ctx)});this.ctx=t,this.item=e,this.element=document.createElement("button"),this.element.type="button",this.element.className=e.danger?"oa-toolbar-button oa-toolbar-button-danger":"oa-toolbar-button",this.element.dataset.tooltip=e.title,this.element.innerHTML=y(e.icon,16),this.element.addEventListener("click",this.onClick)}update(t){if(!this.item.isActive)return;const e=this.item.isActive(t);this.element.classList.toggle("active",e),this.element.setAttribute("aria-pressed",String(e))}destroy(){this.element.removeEventListener("click",this.onClick)}}function R(s,t){const e=document.createElement("div");e.className="oa-toolbar-dropdown";const o=document.createElement("button");o.type="button",o.className="oa-toolbar-button oa-toolbar-dropdown-trigger",o.dataset.tooltip=s;const n=document.createElement("span");n.className="oa-toolbar-dropdown-label",n.textContent=t;const i=document.createElement("span");i.className="oa-toolbar-dropdown-chevron",i.innerHTML=y("chevron-down",14),o.appendChild(n),o.appendChild(i);const a=document.createElement("div");a.className="oa-toolbar-dropdown-panel";const h=()=>e.classList.remove("open");return o.addEventListener("click",p=>{var l;p.stopPropagation();const d=!e.classList.contains("open");(l=e.closest(".annotation-style-toolbar"))==null||l.querySelectorAll(".oa-toolbar-dropdown.open").forEach(m=>{m!==e&&m.classList.remove("open")}),e.classList.toggle("open",d)}),e.appendChild(o),e.appendChild(a),{element:e,panel:a,close:h,setLabel:p=>{n.textContent=p}}}class z{constructor(t,e){r(this,"element");r(this,"dropdown");this.ctx=t,this.item=e,this.dropdown=R(e.title,""),this.element=this.dropdown.element,e.options.forEach(o=>{const n=document.createElement("button");n.type="button",n.className="oa-toolbar-dropdown-option",n.textContent=o.label,o.style&&Object.assign(n.style,o.style),n.addEventListener("click",i=>{i.stopPropagation(),e.onSelect(o.value,this.ctx),this.dropdown.close()}),this.dropdown.panel.appendChild(n)})}update(t){const e=this.item.getValue(t),o=this.item.options.find(i=>i.value===e),n=this.item.getLabel?this.item.getLabel(e,t):(o==null?void 0:o.label)??`${e}`;this.dropdown.setLabel(n),this.element.title=(o==null?void 0:o.label)??`${e}`}destroy(){}}const nt=12;class V{constructor(t,e){r(this,"control");r(this,"ogma");r(this,"options");r(this,"annotationId");r(this,"overlay");r(this,"anchor");r(this,"root");r(this,"cells",[]);r(this,"documentClickHandler",t=>{this.root.contains(t.target)||this.root.querySelectorAll(".oa-toolbar-dropdown.open").forEach(e=>e.classList.remove("open"))});this.control=t.control,this.options=t,this.ogma=this.control.getOgma(),this.annotationId=e.id,this.anchor=document.createElement("div"),this.anchor.className="annotation-style-toolbar-anchor",this.root=document.createElement("div"),this.root.className="annotation-style-toolbar oa-toolbar oa-toolbar-bar",this.anchor.appendChild(this.root),["click","mousedown","mousemove"].forEach(n=>this.root.addEventListener(n,i=>i.stopPropagation()));const o={getAnnotation:()=>this.control.getAnnotation(this.annotationId),updateStyle:n=>this.control.updateStyle(this.annotationId,n),deleteAnnotation:()=>{const n=this.control.getAnnotation(this.annotationId);n&&this.control.remove(n)}};this.setItems(this.getItems(o),o),this.cells.forEach(n=>n.update(e)),this.overlay=this.ogma.layers.addOverlay({element:this.anchor,position:this.getAnchor(e),scaled:!1}),document.addEventListener("click",this.documentClickHandler)}buildCell(t,e){switch(t.kind){case"separator":return null;case"custom":return t.build(e);case"button":return new H(e,t);case"dropdown":return new z(e,t)}}setItems(t,e){this.cells=[],t.forEach(o=>{if(o.kind==="separator"){const i=document.createElement("span");i.className="oa-toolbar-separator",this.root.appendChild(i);return}const n=this.buildCell(o,e);this.cells.push(n),this.root.appendChild(n.element)})}getAnchor(t){var l;const e=this.control.getZoom(),o=this.control.getRotation(),n=((l=t.properties.style)==null?void 0:l.fixedSize)===!0;let{height:i}=c.getBoxSize(t);n&&(i/=e);const a=c.getBoxCenter(t),h=-(i/2+nt/e),p=Math.sin(o),d=Math.cos(o);return{x:a.x-h*p,y:a.y+h*d}}update(t){this.cells.forEach(e=>e.update(t)),this.overlay.setPosition(this.getAnchor(t))}destroy(){document.removeEventListener("click",this.documentClickHandler),this.cells.forEach(t=>t.destroy()),this.overlay.destroy()}}class W{constructor(t,e){r(this,"element");r(this,"dropdown");r(this,"swatch");r(this,"more");r(this,"morePicker",null);r(this,"morePickerHost",null);this.ctx=t,this.options=e;const{swatches:o}=e;this.dropdown=R("Color",""),this.element=this.dropdown.element,this.element.classList.add("oa-toolbar-color-cell"),this.swatch=document.createElement("span"),this.swatch.className="oa-toolbar-swatch",this.dropdown.element.querySelector(".oa-toolbar-dropdown-trigger").insertBefore(this.swatch,this.dropdown.element.querySelector(".oa-toolbar-dropdown-label"));const n=document.createElement("div");n.className="oa-toolbar-swatch-grid",o.forEach(i=>{const a=document.createElement("button");a.type="button",a.className="oa-toolbar-swatch-cell",a.classList.toggle("oa-toolbar-swatch-cell-transparent",i.fill==="transparent"),a.title=i.fill,a.style.setProperty("--oa-swatch-fill",i.fill),a.style.setProperty("--oa-swatch-stroke",i.stroke),a.addEventListener("click",h=>{h.stopPropagation(),this.pick(i.fill),this.dropdown.close()}),n.appendChild(a)}),this.dropdown.panel.appendChild(n),this.more=document.createElement("button"),this.more.type="button",this.more.className="oa-toolbar-more-colors",this.more.textContent="More colors…",this.more.addEventListener("click",i=>{i.stopPropagation(),this.openMorePicker()}),this.dropdown.panel.appendChild(this.more)}pick(t){this.ctx.updateStyle({background:t})}openMorePicker(){var e;if(this.options.onMoreColors){this.dropdown.close(),this.options.onMoreColors(this.ctx,this.more);return}if(this.morePickerHost){this.closeMorePicker();return}this.morePickerHost=document.createElement("div"),this.morePickerHost.className="oa-toolbar-more-colors-host",this.morePicker=k();const t=((e=this.ctx.getAnnotation().properties.style)==null?void 0:e.background)||c.defaultTextStyle.background;this.morePicker.color=c.parseColor(t),this.morePicker.addEventListener("color-changed",o=>{this.pick(E(o.detail.value))}),this.morePickerHost.appendChild(this.morePicker),this.dropdown.panel.appendChild(this.morePickerHost)}closeMorePicker(){var t;(t=this.morePickerHost)==null||t.remove(),this.morePickerHost=null,this.morePicker=null}update(t){var o;const e=((o=t.properties.style)==null?void 0:o.background)||c.defaultTextStyle.background;this.swatch.style.setProperty("--oa-swatch-fill",e),this.swatch.classList.toggle("oa-toolbar-swatch-transparent",e==="transparent")}destroy(){this.closeMorePicker()}}const U=[{fill:"#FFE49B",stroke:"#D9A926"},{fill:"#FFC8A7",stroke:"#CC8C66"},{fill:"#FFA7B5",stroke:"#C2707D"},{fill:"#D9F3B0",stroke:"#A2C270"},{fill:"#C7F7EF",stroke:"#8CD9CC"},{fill:"#99D6FF",stroke:"#5CA5D6"},{fill:"#D1C7FA",stroke:"#9B8CD9"},{fill:"#C3DAFE",stroke:"#668ECC"},{fill:"transparent",stroke:"#CCCCCC"}],q=[{value:"sans-serif",label:"Sans Serif"},{value:"serif",label:"Serif",style:{fontFamily:"serif"}},{value:"monospace",label:"Monospace",style:{fontFamily:"monospace"}},{value:"IBM Plex Sans",label:"IBM Plex Sans",style:{fontFamily:"IBM Plex Sans"}},{value:"IBM Plex Mono",label:"IBM Plex Mono",style:{fontFamily:"IBM Plex Mono"}}],Y=[12,14,16,18,24,32,48,64];class S extends V{getItems(t){var h,p;const e=this.options.fonts??q,o=this.options.fontSizes??Y,n=this.options.swatches??U,i=this.options.onMoreColors,a=[{kind:"custom",id:"color",build:d=>new W(d,{swatches:n,onMoreColors:i})},{kind:"separator"},{kind:"dropdown",id:"font",title:"Font",options:e,getValue:d=>{var l;return((l=d.properties.style)==null?void 0:l.font)||c.defaultTextStyle.font},getLabel:()=>"Aa",onSelect:(d,l)=>l.updateStyle({font:`${d}`})},{kind:"dropdown",id:"fontSize",title:"Font size",options:o.map(d=>({value:d,label:`${d}`})),getValue:d=>{const l=d.properties.style;return Math.round(c.getEffectiveFontSize((l==null?void 0:l.fontSize)??c.defaultTextStyle.fontSize,l==null?void 0:l.fontScale))},onSelect:(d,l)=>l.updateStyle({fontSize:d,fontScale:1})},{kind:"separator"},{kind:"button",id:"bold",title:"Bold",icon:"bold",isActive:d=>{var l;return((l=d.properties.style)==null?void 0:l.fontWeight)==="bold"},action:d=>{var m;const l=((m=d.getAnnotation().properties.style)==null?void 0:m.fontWeight)==="bold";d.updateStyle({fontWeight:l?"normal":"bold"})}},{kind:"separator"},{kind:"button",id:"showAuthor",title:"Show author",icon:"user",isActive:d=>{var l;return((l=d.properties.style)==null?void 0:l.showAuthor)===!0},action:d=>{var m;const l=((m=d.getAnnotation().properties.style)==null?void 0:m.showAuthor)===!0;d.updateStyle({showAuthor:!l})}},{kind:"separator"},{kind:"button",id:"delete",title:"Delete",icon:"trash",danger:!0,action:d=>d.deleteAnnotation()}];return((p=(h=this.options).items)==null?void 0:p.call(h,a,t))??a}}class G extends S{}class it{constructor(t){r(this,"control");r(this,"options");r(this,"current",null);r(this,"detachVisibility");r(this,"handleUpdate",t=>{this.current&&t.id===this.current.annotationId&&c.isText(t)&&this.current.update(t)});this.control=t.control,this.options=t,this.detachVisibility=A(this.control,{onShow:e=>this.show(e),onHide:()=>this.hide(),hideWhenNotEditable:t.hideWhenNotEditable}),this.control.on(c.EVT_UPDATE,this.handleUpdate)}show(t){if(!c.isText(t)){this.hide();return}const e=c.isStickyNote(t)?G:S;if(this.current&&this.current.annotationId===t.id&&this.current instanceof e){this.current.update(t);return}this.hide(),this.current=new e(this.options,t)}hide(){var t;(t=this.current)==null||t.destroy(),this.current=null}destroy(){this.detachVisibility(),this.control.off(c.EVT_UPDATE,this.handleUpdate),this.hide()}}exports.ALL_PANEL_ANNOTATION_TYPES=_;exports.AnnotationPanel=Q;exports.AnnotationStyleToolbar=V;exports.AnnotationToolbar=ot;exports.BACKGROUNDS=x;exports.ButtonItemCell=H;exports.ColorCell=W;exports.DEFAULT_PANEL_ORIENTATION=I;exports.DEFAULT_PANEL_PLACEMENT=B;exports.DEFAULT_RECENT_COLORS=M;exports.DEFAULT_TOOLBAR_FONTS=q;exports.DEFAULT_TOOLBAR_FONT_SIZES=Y;exports.DropdownItemCell=z;exports.EXTREMITY_OPTIONS=P;exports.FONTS=g;exports.ICON_PATHS=O;exports.LINE_TYPES=L;exports.MAX_RECENT_COLORS=N;exports.STICKY_SWATCHES=U;exports.StickyNoteStyleToolbar=G;exports.TextAnnotationToolbar=it;exports.TextStyleToolbar=S;exports.attachPanelVisibility=A;exports.classifyPanelAnnotationType=D;exports.createRgbaColorPicker=k;exports.initialRecentColors=$;exports.rgbaToString=E;exports.svgIcon=y;exports.withColorFromAnnotation=F;
|