@khanglvm/relay 0.12.2 → 0.13.0
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 +1 -0
- package/docs/AGENT.md +75 -6
- package/package.json +1 -1
- package/skills/relay/SKILL.md +180 -4
- package/src/cli.js +98 -17
- package/src/mcp-ui/board.js +213 -10
- package/src/server.js +8 -3
- package/src/spec.js +272 -47
- package/src/ui/annotate.css +75 -10
- package/src/ui/annotate.js +90 -12
- package/src/ui/app.js +232 -8
- package/src/ui/blocks.css +164 -4
- package/src/ui/blocks.js +430 -33
- package/src/ui/style.css +90 -0
package/src/ui/blocks.css
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
.blk-markdown .md h2 { font-size: 1.2rem; }
|
|
34
34
|
.blk-markdown .md h3 { font-size: 1.05rem; }
|
|
35
35
|
.blk-markdown .md p { margin: 10px 0; }
|
|
36
|
+
.blk-markdown .md img.md-img { max-width: 100%; height: auto; border-radius: 8px; margin: 8px 0; }
|
|
36
37
|
.blk-markdown .md a { color: var(--accent); text-decoration: none; border-bottom: 1px solid transparent; transition: border-color 150ms var(--ease); }
|
|
37
38
|
.blk-markdown .md a:hover { border-bottom-color: var(--accent); }
|
|
38
39
|
.blk-markdown .md strong { font-weight: 600; }
|
|
@@ -237,6 +238,36 @@
|
|
|
237
238
|
}
|
|
238
239
|
.blk-difftoggle:hover { color: var(--accent); border-color: var(--accent); }
|
|
239
240
|
|
|
241
|
+
/* multi-file diff: per-file filename header + a jump bar of file chips */
|
|
242
|
+
.diff-file + .diff-file { margin-top: 6px; }
|
|
243
|
+
.diff-filehead {
|
|
244
|
+
position: sticky; top: 0; z-index: 1;
|
|
245
|
+
padding: 5px 12px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
246
|
+
font-size: 0.76rem; color: var(--fg-2);
|
|
247
|
+
background: var(--card); border-bottom: 1px solid var(--border);
|
|
248
|
+
}
|
|
249
|
+
.diff-files {
|
|
250
|
+
display: flex; flex-wrap: wrap; gap: 6px;
|
|
251
|
+
padding: 8px 0;
|
|
252
|
+
}
|
|
253
|
+
.diff-file-chip {
|
|
254
|
+
cursor: pointer; font: inherit; font-size: 0.72rem;
|
|
255
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
256
|
+
color: var(--fg-2); background: var(--bg-sunken);
|
|
257
|
+
border: 1px solid var(--border); border-radius: 6px; padding: 3px 8px;
|
|
258
|
+
max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
259
|
+
transition: color 150ms var(--ease), border-color 150ms var(--ease);
|
|
260
|
+
}
|
|
261
|
+
.diff-file-chip:hover { color: var(--accent); border-color: var(--accent); }
|
|
262
|
+
|
|
263
|
+
/* clickable line-number gutter: hover a number to comment on that line */
|
|
264
|
+
.blk-gutter-c { padding: 14px 0; }
|
|
265
|
+
.blk-gutter-c .blk-gutterline {
|
|
266
|
+
padding: 0 10px 0 14px; cursor: pointer; position: relative;
|
|
267
|
+
transition: background 120ms var(--ease), color 120ms var(--ease);
|
|
268
|
+
}
|
|
269
|
+
.blk-gutter-c .blk-gutterline:hover { background: var(--accent-soft); color: var(--accent); }
|
|
270
|
+
|
|
240
271
|
/* ---------- video (iframe embed / local stream / direct URL) ---------- */
|
|
241
272
|
.blk-videowrap { margin: 0; }
|
|
242
273
|
.blk-video, .blk-video-embed {
|
|
@@ -277,6 +308,23 @@
|
|
|
277
308
|
.blk-table tbody tr:hover { background: var(--bg-sunken); }
|
|
278
309
|
.blk-table tbody tr:last-child td { border-bottom: 0; }
|
|
279
310
|
|
|
311
|
+
/* table toolbar: live filter box + CSV export (opt-in via filterable/exportable) */
|
|
312
|
+
.blk-tablebar { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
313
|
+
.blk-tablefilter {
|
|
314
|
+
flex: 1; min-width: 0; max-width: 280px;
|
|
315
|
+
padding: 6px 10px; font: inherit; font-size: 0.85rem;
|
|
316
|
+
background: var(--bg-sunken); color: var(--fg);
|
|
317
|
+
border: 1px solid var(--border); border-radius: 8px;
|
|
318
|
+
}
|
|
319
|
+
.blk-tablefilter:focus { outline: none; border-color: var(--accent); }
|
|
320
|
+
.blk-tableexport {
|
|
321
|
+
flex: none; padding: 6px 12px; font: inherit; font-size: 0.8rem; cursor: pointer;
|
|
322
|
+
background: var(--card); color: var(--fg-2);
|
|
323
|
+
border: 1px solid var(--border-strong); border-radius: 8px;
|
|
324
|
+
transition: border-color 150ms var(--ease), color 150ms var(--ease);
|
|
325
|
+
}
|
|
326
|
+
.blk-tableexport:hover { border-color: var(--accent); color: var(--accent); }
|
|
327
|
+
|
|
280
328
|
/* ---------- chart ---------- */
|
|
281
329
|
/* NO height here: renderChart always sets the inline height, and this class
|
|
282
330
|
also lands on the outer .blk.blk-chart dispatch wrapper — a CSS height
|
|
@@ -316,7 +364,7 @@
|
|
|
316
364
|
/* ---------- mermaid ---------- */
|
|
317
365
|
.blk-mermaid {
|
|
318
366
|
overflow: auto;
|
|
319
|
-
max-height:
|
|
367
|
+
max-height: 800px;
|
|
320
368
|
text-align: center;
|
|
321
369
|
}
|
|
322
370
|
.blk-mermaid svg {
|
|
@@ -392,7 +440,7 @@
|
|
|
392
440
|
/* ---------- graphviz (offline, vendored Viz.js) ---------- */
|
|
393
441
|
.blk-graphviz {
|
|
394
442
|
overflow: auto;
|
|
395
|
-
max-height:
|
|
443
|
+
max-height: 800px;
|
|
396
444
|
text-align: center;
|
|
397
445
|
/* graphviz draws on its own white canvas; frame it as a deliberate card so
|
|
398
446
|
it reads intentional in dark mode instead of a stray white rectangle */
|
|
@@ -411,7 +459,7 @@
|
|
|
411
459
|
/* ---------- plantuml (server-rendered image) ---------- */
|
|
412
460
|
.blk-plantuml {
|
|
413
461
|
overflow: auto;
|
|
414
|
-
max-height:
|
|
462
|
+
max-height: 800px;
|
|
415
463
|
text-align: center;
|
|
416
464
|
background: #fff;
|
|
417
465
|
border: 1px solid var(--border);
|
|
@@ -426,7 +474,7 @@
|
|
|
426
474
|
/* ---------- image ---------- */
|
|
427
475
|
.blk-imagewrap {
|
|
428
476
|
overflow: auto;
|
|
429
|
-
max-height:
|
|
477
|
+
max-height: 800px;
|
|
430
478
|
border: 1px solid var(--border);
|
|
431
479
|
border-radius: 10px;
|
|
432
480
|
background: var(--bg-sunken);
|
|
@@ -483,6 +531,13 @@ body.blk-full-open { overflow: hidden; }
|
|
|
483
531
|
background: var(--card); border-bottom: 1px solid var(--border);
|
|
484
532
|
z-index: 51;
|
|
485
533
|
}
|
|
534
|
+
/* When the comment rail is docked open (≥980px), inset the full-screen overlay
|
|
535
|
+
AND its toolbar from the right by the rail width — otherwise the overlay slides
|
|
536
|
+
under the (higher z-index) rail and its close/comment buttons get hidden. */
|
|
537
|
+
@media (min-width: 980px) {
|
|
538
|
+
body.ann-rail-open .blk-full { right: 340px; }
|
|
539
|
+
body.ann-rail-open .blk-full > .blk-tools { right: 340px; }
|
|
540
|
+
}
|
|
486
541
|
.blk-chart.blk-full {
|
|
487
542
|
height: 100vh !important; width: auto !important;
|
|
488
543
|
padding: 44px 16px 16px;
|
|
@@ -585,3 +640,108 @@ body.blk-full-open { overflow: hidden; }
|
|
|
585
640
|
.pal-tag.tone-nature { background: #EAF3DE; color: #3B6D11; }
|
|
586
641
|
.pal-tag.tone-bold { background: #FBEAF0; color: #72243E; }
|
|
587
642
|
.pal-tag.tone-digital { background: #EEEDFE; color: #3C3489; }
|
|
643
|
+
|
|
644
|
+
/* ---------- kpi (stat cards) ---------- */
|
|
645
|
+
.blk-kpi { margin: 4px 0; }
|
|
646
|
+
.kpi-title { font-weight: 600; color: var(--fg-2); margin-bottom: 10px; }
|
|
647
|
+
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
|
|
648
|
+
.kpi-card {
|
|
649
|
+
border: 1px solid var(--border); border-radius: 12px;
|
|
650
|
+
background: var(--card); padding: 14px 16px;
|
|
651
|
+
}
|
|
652
|
+
.kpi-label { color: var(--muted); font-size: 0.82rem; }
|
|
653
|
+
.kpi-value { font-family: var(--serif); font-size: 1.8rem; line-height: 1.1; margin: 4px 0 2px; letter-spacing: -0.02em; }
|
|
654
|
+
.kpi-delta { font-size: 0.85rem; font-weight: 600; color: var(--fg-2); }
|
|
655
|
+
.kpi-delta.kpi-up { color: var(--ok); }
|
|
656
|
+
.kpi-delta.kpi-down { color: var(--danger); }
|
|
657
|
+
.kpi-sub { color: var(--muted); font-size: 0.78rem; margin-top: 2px; }
|
|
658
|
+
|
|
659
|
+
/* ---------- typography (specimens) ---------- */
|
|
660
|
+
.blk-typography { margin: 4px 0; }
|
|
661
|
+
.typo-title { font-weight: 600; color: var(--fg-2); margin-bottom: 10px; }
|
|
662
|
+
.typo-row { padding: 10px 0; border-bottom: 1px solid var(--border); }
|
|
663
|
+
.typo-row:last-child { border-bottom: 0; }
|
|
664
|
+
.typo-meta { color: var(--muted); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
|
|
665
|
+
.typo-sample { color: var(--fg); font-size: 1.1rem; line-height: 1.3; overflow-wrap: anywhere; }
|
|
666
|
+
|
|
667
|
+
/* ---------- compare (before/after slider) ---------- */
|
|
668
|
+
.blk-comparewrap { margin: 4px 0; }
|
|
669
|
+
.cmp-frame {
|
|
670
|
+
position: relative; overflow: hidden; user-select: none; touch-action: none;
|
|
671
|
+
border: 1px solid var(--border); border-radius: 12px; line-height: 0;
|
|
672
|
+
cursor: ew-resize;
|
|
673
|
+
}
|
|
674
|
+
.cmp-img { display: block; width: 100%; height: auto; }
|
|
675
|
+
.cmp-before { position: absolute; inset: 0; width: 50%; overflow: hidden; }
|
|
676
|
+
.cmp-before .cmp-img-before { position: absolute; left: 0; top: 0; height: 100%; max-width: none; }
|
|
677
|
+
.cmp-handle {
|
|
678
|
+
position: absolute; top: 0; bottom: 0; left: 50%; width: 2px;
|
|
679
|
+
background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.25); transform: translateX(-1px);
|
|
680
|
+
}
|
|
681
|
+
.cmp-handle-grip {
|
|
682
|
+
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
|
683
|
+
width: 30px; height: 30px; border-radius: 50%;
|
|
684
|
+
background: #fff; color: #333; box-shadow: 0 1px 4px rgba(0,0,0,0.35);
|
|
685
|
+
display: grid; place-items: center; font-size: 13px; cursor: ew-resize;
|
|
686
|
+
}
|
|
687
|
+
.cmp-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
688
|
+
.cmp-tag {
|
|
689
|
+
position: absolute; bottom: 10px; padding: 3px 8px; border-radius: 6px;
|
|
690
|
+
font-size: 0.72rem; line-height: 1.4; color: #fff; background: rgba(0,0,0,0.55);
|
|
691
|
+
pointer-events: none;
|
|
692
|
+
}
|
|
693
|
+
.cmp-tag-before { left: 10px; }
|
|
694
|
+
.cmp-tag-after { right: 10px; }
|
|
695
|
+
|
|
696
|
+
/* ---------- reference links (open a visual in a modal) ---------- */
|
|
697
|
+
.rly-reflink {
|
|
698
|
+
display: inline-flex; align-items: center; gap: 0.3em;
|
|
699
|
+
color: var(--accent); cursor: pointer; text-decoration: none;
|
|
700
|
+
border-bottom: 1px solid transparent; border-radius: 4px;
|
|
701
|
+
transition: border-color 150ms var(--ease);
|
|
702
|
+
}
|
|
703
|
+
.rly-reflink:hover { border-bottom-color: var(--accent); }
|
|
704
|
+
.rly-reflink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
705
|
+
.rly-reflink-ico {
|
|
706
|
+
flex: none; width: 0.85em; height: 0.85em;
|
|
707
|
+
border: 1.6px solid currentColor; border-radius: 50%;
|
|
708
|
+
position: relative;
|
|
709
|
+
}
|
|
710
|
+
.rly-reflink-ico::after {
|
|
711
|
+
content: ''; position: absolute; width: 0.42em; height: 1.6px;
|
|
712
|
+
background: currentColor; right: -0.28em; bottom: 0.02em;
|
|
713
|
+
transform: rotate(45deg); transform-origin: left center;
|
|
714
|
+
}
|
|
715
|
+
/* floating "↩ Back" pill shown after a reference jumps to a non-modal block */
|
|
716
|
+
.rly-refback {
|
|
717
|
+
position: fixed; left: 18px; bottom: 18px; z-index: 60;
|
|
718
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
719
|
+
padding: 8px 14px; font: inherit; font-size: 0.85rem; font-weight: 500;
|
|
720
|
+
color: var(--accent-fg); background: var(--accent);
|
|
721
|
+
border: 0; border-radius: 999px; cursor: pointer;
|
|
722
|
+
box-shadow: var(--shadow-lift);
|
|
723
|
+
animation: rly-refback-in 180ms var(--ease);
|
|
724
|
+
}
|
|
725
|
+
.rly-refback:hover { filter: brightness(1.06); }
|
|
726
|
+
@keyframes rly-refback-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
|
|
727
|
+
/* brief highlight when a reference jumps to a non-modal block */
|
|
728
|
+
.rly-refflash { animation: rly-refflash 1.2s var(--ease); }
|
|
729
|
+
@keyframes rly-refflash {
|
|
730
|
+
0%, 100% { box-shadow: 0 0 0 0 transparent; }
|
|
731
|
+
20% { box-shadow: 0 0 0 3px var(--accent); }
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/* ---------- image coordinate pins (block.pins) ---------- */
|
|
735
|
+
.blk-img-pinnable { cursor: crosshair; }
|
|
736
|
+
.blk-imgpins { position: absolute; inset: 0; pointer-events: none; }
|
|
737
|
+
.blk-imgpin {
|
|
738
|
+
position: absolute; transform: translate(-50%, -50%);
|
|
739
|
+
min-width: 22px; height: 22px; padding: 0 6px;
|
|
740
|
+
border-radius: 11px; border: 2px solid #fff;
|
|
741
|
+
background: var(--accent); color: #fff;
|
|
742
|
+
font: inherit; font-size: 0.72rem; font-weight: 600; line-height: 1;
|
|
743
|
+
cursor: pointer; pointer-events: auto;
|
|
744
|
+
box-shadow: 0 1px 4px rgba(0,0,0,0.35);
|
|
745
|
+
display: grid; place-items: center;
|
|
746
|
+
}
|
|
747
|
+
.blk-imgpin:hover { filter: brightness(1.08); }
|