@khanglvm/relay 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -1
- package/docs/AGENT.md +58 -14
- package/package.json +1 -1
- package/skills/relay/SKILL.md +41 -7
- package/src/cli.js +22 -11
- package/src/mcp-ui/board.js +46 -8
- package/src/mcp.js +9 -3
- package/src/server.js +110 -11
- package/src/spec.js +5 -0
- package/src/store.js +15 -0
- package/src/ui/annotate.js +68 -22
- package/src/ui/app.js +25 -6
- package/src/ui/blocks.css +90 -9
- package/src/ui/blocks.js +359 -30
package/src/ui/blocks.css
CHANGED
|
@@ -648,26 +648,37 @@
|
|
|
648
648
|
}
|
|
649
649
|
.blk-imagewrap .blk-img {
|
|
650
650
|
display: block;
|
|
651
|
-
|
|
651
|
+
width: 100%;
|
|
652
|
+
max-width: none;
|
|
652
653
|
height: auto;
|
|
654
|
+
-webkit-user-drag: none;
|
|
655
|
+
user-select: none;
|
|
653
656
|
border-radius: 6px;
|
|
654
657
|
object-fit: contain;
|
|
655
658
|
object-position: left top;
|
|
656
659
|
}
|
|
660
|
+
.blk-imgstage {
|
|
661
|
+
position: relative;
|
|
662
|
+
width: 100%;
|
|
663
|
+
max-width: 100%;
|
|
664
|
+
line-height: 0;
|
|
665
|
+
}
|
|
657
666
|
/* In full-screen a per-block height must never keep the image small — that
|
|
658
667
|
height only shapes the inline preview; the detail view needs every pixel.
|
|
659
668
|
(Belt-and-suspenders alongside the viewer's reapply() on full-screen toggle.) */
|
|
660
669
|
.blk-imagewrap.blk-full .blk-img { max-height: none !important; }
|
|
661
670
|
|
|
662
671
|
/* ---------- viewer controls (full-screen) ---------- */
|
|
663
|
-
/* The
|
|
664
|
-
|
|
665
|
-
the
|
|
666
|
-
.blk-viewer { position: relative;
|
|
672
|
+
/* The controls participate in layout above the visual and use native sticky
|
|
673
|
+
positioning. The previous JS counter-translation chased scrollTop one event
|
|
674
|
+
behind the compositor, which made the bar visibly trail trackpad scrolling. */
|
|
675
|
+
.blk-viewer { position: relative; }
|
|
667
676
|
.blk-tools {
|
|
668
|
-
position:
|
|
677
|
+
position: sticky; top: 0; left: 0; width: 100%; height: 34px;
|
|
669
678
|
display: flex; gap: 2px; align-items: center; justify-content: flex-end;
|
|
670
|
-
|
|
679
|
+
box-sizing: border-box; padding: 4px;
|
|
680
|
+
background: var(--bg-sunken); border-bottom: 1px solid var(--border);
|
|
681
|
+
z-index: 16;
|
|
671
682
|
}
|
|
672
683
|
.blk-tools button {
|
|
673
684
|
background: var(--card); border: 1px solid var(--border); color: var(--fg-2);
|
|
@@ -693,6 +704,7 @@ body.blk-full-open { overflow: hidden; }
|
|
|
693
704
|
/* detach the toolbar from the scrolling content and fix it to the viewport top */
|
|
694
705
|
.blk-full > .blk-tools {
|
|
695
706
|
position: fixed; top: 0; left: 0; right: 0; height: 44px;
|
|
707
|
+
width: auto;
|
|
696
708
|
margin: 0; padding: 0 12px;
|
|
697
709
|
background: var(--card); border-bottom: 1px solid var(--border);
|
|
698
710
|
z-index: 51;
|
|
@@ -727,6 +739,7 @@ body.blk-full-open { overflow: hidden; }
|
|
|
727
739
|
.blk-plantuml.blk-full > svg,
|
|
728
740
|
.blk-plantuml.blk-full > .blk-plantuml-img,
|
|
729
741
|
.blk-imagewrap.blk-full > .blk-img { margin: auto; }
|
|
742
|
+
.blk-imagewrap.blk-full > .blk-imgstage { margin: auto; max-width: none; }
|
|
730
743
|
|
|
731
744
|
/* Small frame on charts + mermaid so they read as a deliberate card, matching
|
|
732
745
|
the graphviz/plantuml/image blocks (already framed). Scoped to the inner
|
|
@@ -746,6 +759,9 @@ body.blk-full-open { overflow: hidden; }
|
|
|
746
759
|
dragging. During an active drag the inner svg/img/canvas ignore the pointer
|
|
747
760
|
so hover pins/cursors don't flicker and the whole surface shows "grabbing". */
|
|
748
761
|
.blk-pannable { cursor: grab; }
|
|
762
|
+
.blk-has-regions.blk-pannable { cursor: crosshair; }
|
|
763
|
+
body.blk-space-pan .blk-has-regions.blk-pannable,
|
|
764
|
+
body.blk-space-pan .blk-has-regions.blk-pannable * { cursor: grab !important; }
|
|
749
765
|
.blk-panning { cursor: grabbing; user-select: none; }
|
|
750
766
|
.blk-panning svg,
|
|
751
767
|
.blk-panning img,
|
|
@@ -778,6 +794,19 @@ body.blk-full-open { overflow: hidden; }
|
|
|
778
794
|
background: var(--accent); border-color: var(--accent); color: var(--accent-fg);
|
|
779
795
|
}
|
|
780
796
|
.blk-tools .tool-comment.has-comment:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-fg); }
|
|
797
|
+
.blk-tools .tool-region {
|
|
798
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
799
|
+
}
|
|
800
|
+
.blk-tools .tool-region svg { display: block; }
|
|
801
|
+
.blk-tools .tool-region.is-active {
|
|
802
|
+
background: var(--accent); border-color: var(--accent); color: var(--accent-fg);
|
|
803
|
+
}
|
|
804
|
+
.blk-tools .tool-region.is-active:hover {
|
|
805
|
+
background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-fg);
|
|
806
|
+
}
|
|
807
|
+
@media (max-width: 520px) {
|
|
808
|
+
.blk-tools .tool-region-label { display: none; }
|
|
809
|
+
}
|
|
781
810
|
|
|
782
811
|
/* code blocks reuse the viewer toolbar (comment + full-screen); the pre keeps
|
|
783
812
|
its own card, the wrapper only hosts the toolbar strip */
|
|
@@ -836,7 +865,7 @@ body.blk-full-open { overflow: hidden; }
|
|
|
836
865
|
.cmp-frame {
|
|
837
866
|
position: relative; overflow: hidden; user-select: none; touch-action: none;
|
|
838
867
|
border: 1px solid var(--border); border-radius: 12px; line-height: 0;
|
|
839
|
-
cursor:
|
|
868
|
+
cursor: crosshair;
|
|
840
869
|
}
|
|
841
870
|
.cmp-img { display: block; width: 100%; height: auto; }
|
|
842
871
|
.cmp-before { position: absolute; inset: 0; width: 50%; overflow: hidden; }
|
|
@@ -844,6 +873,7 @@ body.blk-full-open { overflow: hidden; }
|
|
|
844
873
|
.cmp-handle {
|
|
845
874
|
position: absolute; top: 0; bottom: 0; left: 50%; width: 2px;
|
|
846
875
|
background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.25); transform: translateX(-1px);
|
|
876
|
+
cursor: ew-resize;
|
|
847
877
|
}
|
|
848
878
|
.cmp-handle-grip {
|
|
849
879
|
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
|
@@ -898,7 +928,7 @@ body.blk-full-open { overflow: hidden; }
|
|
|
898
928
|
20% { box-shadow: 0 0 0 3px var(--accent); }
|
|
899
929
|
}
|
|
900
930
|
|
|
901
|
-
/* ---------- image
|
|
931
|
+
/* ---------- image point + area comments ---------- */
|
|
902
932
|
.blk-img-pinnable { cursor: crosshair; }
|
|
903
933
|
.blk-imgpins { position: absolute; inset: 0; pointer-events: none; }
|
|
904
934
|
.blk-imgpin {
|
|
@@ -912,3 +942,54 @@ body.blk-full-open { overflow: hidden; }
|
|
|
912
942
|
display: grid; place-items: center;
|
|
913
943
|
}
|
|
914
944
|
.blk-imgpin:hover { filter: brightness(1.08); }
|
|
945
|
+
.blk-region-layer { position: absolute; inset: 0; pointer-events: none; }
|
|
946
|
+
.blk-region-selection,
|
|
947
|
+
.blk-imgregion {
|
|
948
|
+
position: absolute;
|
|
949
|
+
border: 2px solid var(--accent);
|
|
950
|
+
background: color-mix(in srgb, var(--accent) 16%, transparent);
|
|
951
|
+
box-shadow: 0 0 0 1px rgba(255,255,255,0.75) inset;
|
|
952
|
+
border-radius: 5px;
|
|
953
|
+
}
|
|
954
|
+
.blk-region-selection { display: none; z-index: 7; }
|
|
955
|
+
.blk-imgregion {
|
|
956
|
+
z-index: 6;
|
|
957
|
+
pointer-events: auto;
|
|
958
|
+
cursor: pointer;
|
|
959
|
+
color: var(--accent-fg);
|
|
960
|
+
padding: 0;
|
|
961
|
+
min-width: 10px;
|
|
962
|
+
min-height: 10px;
|
|
963
|
+
appearance: none;
|
|
964
|
+
}
|
|
965
|
+
.blk-imgregion-badge {
|
|
966
|
+
position: absolute; top: -11px; right: -11px;
|
|
967
|
+
min-width: 24px; height: 22px; padding: 0 6px;
|
|
968
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 3px;
|
|
969
|
+
border: 2px solid #fff; border-radius: 999px;
|
|
970
|
+
background: var(--accent); color: #fff;
|
|
971
|
+
font: 600 0.68rem/1 var(--sans);
|
|
972
|
+
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
|
|
973
|
+
pointer-events: none;
|
|
974
|
+
}
|
|
975
|
+
.blk-imgregion-badge svg { width: 10px; height: 10px; }
|
|
976
|
+
.blk-imgregion-count { min-width: 0.7em; text-align: center; }
|
|
977
|
+
.blk-imgregion-provisional {
|
|
978
|
+
z-index: 8;
|
|
979
|
+
border-style: dashed;
|
|
980
|
+
background: color-mix(in srgb, var(--card) 34%, var(--accent) 20%);
|
|
981
|
+
}
|
|
982
|
+
.blk-imgregion-provisional .blk-imgregion-badge { opacity: 0.9; }
|
|
983
|
+
.blk-region-mode,
|
|
984
|
+
.blk-region-mode * { cursor: crosshair !important; }
|
|
985
|
+
.blk-region-mode { touch-action: none; }
|
|
986
|
+
.blk-region-arming { cursor: crosshair !important; }
|
|
987
|
+
.blk-region-selecting { cursor: crosshair !important; touch-action: none; }
|
|
988
|
+
.blk-region-status {
|
|
989
|
+
position: absolute; left: 50%; bottom: 12px; z-index: 9;
|
|
990
|
+
transform: translateX(-50%);
|
|
991
|
+
padding: 6px 10px; border-radius: 8px;
|
|
992
|
+
background: rgba(28,27,25,0.86); color: #fff;
|
|
993
|
+
font: 500 0.74rem/1.2 var(--sans);
|
|
994
|
+
pointer-events: none;
|
|
995
|
+
}
|