visualproof 0.3.0 → 0.4.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 +52 -11
- package/dist/assets/tips/phone-fingers.light.mp4 +0 -0
- package/dist/assets/tips/phone-fingers.light.webp +0 -0
- package/dist/assets/tips/tour-agent.webp +0 -0
- package/dist/assets/tips/tour-arrange.webp +0 -0
- package/dist/assets/tips/tour-artwork.webp +0 -0
- package/dist/assets/tips/tour-checks.webp +0 -0
- package/dist/assets/tips/tour-export.webp +0 -0
- package/dist/assets/tips/tour-keys.webp +0 -0
- package/dist/assets/tips/tour-library.webp +0 -0
- package/dist/assets/tips/tour-project.webp +0 -0
- package/dist/assets/tips/tour-review.webp +0 -0
- package/dist/assets/tips/tour-share.webp +0 -0
- package/dist/assets/tips/tour-source.webp +0 -0
- package/dist/assets/tips/tour-target.webp +0 -0
- package/dist/assets/tips/tour-view.webp +0 -0
- package/dist/assets/tips/tour.json +289 -0
- package/dist/assets/tips/tour.webp +0 -0
- package/dist/mcp/visualproof-mcp.mjs +3 -1
- package/dist/server/agent.js +10 -5
- package/dist/server/children.js +85 -0
- package/dist/server/doctor.js +105 -42
- package/dist/server/events.js +10 -0
- package/dist/server/export.js +11 -4
- package/dist/server/extract.js +3 -2
- package/dist/server/figures.js +3 -2
- package/dist/server/film.js +380 -0
- package/dist/server/history.js +11 -1
- package/dist/server/hover.js +8 -5
- package/dist/server/live.js +66 -9
- package/dist/server/main.js +217 -16
- package/dist/server/media.js +114 -0
- package/dist/server/pipeline.js +6 -1
- package/dist/server/poppler.js +3 -2
- package/dist/server/readonlygate.js +4 -4
- package/dist/server/sourcestore.js +3 -2
- package/dist/server/status.js +3 -2
- package/dist/server/supervise.js +219 -0
- package/dist/server/updates.js +951 -0
- package/dist/server/usage.js +3 -1
- package/dist/server/version.js +183 -0
- package/dist/shared/timeline.js +5 -0
- package/dist/web/bundle/app.js +2298 -254
- package/dist/web/index.html +13 -1
- package/dist/web/src/canvas.js +22 -0
- package/dist/web/style.css +189 -1
- package/docs/agent-api/export.md +2 -2
- package/docs/agent-api/history.md +3 -2
- package/package.json +3 -1
package/dist/web/index.html
CHANGED
|
@@ -77,7 +77,12 @@
|
|
|
77
77
|
<button id="who" class="who" hidden></button>
|
|
78
78
|
<div id="who-menu" class="glass" role="menu" aria-label="Your name and visibility" hidden></div>
|
|
79
79
|
</div>
|
|
80
|
-
|
|
80
|
+
<!-- help: a menu of the tips, the keys, the tour, and what the project and VisualProof are
|
|
81
|
+
(GuideSpec decision 8, web/src/guide.ts) -->
|
|
82
|
+
<div class="help-wrap">
|
|
83
|
+
<button id="help-btn" class="help-btn" title="Help: tips, keys, the tour (?)" aria-label="Help" aria-haspopup="menu" aria-expanded="false">?</button>
|
|
84
|
+
<div id="help-menu" class="glass" role="menu" aria-label="Help" hidden></div>
|
|
85
|
+
</div>
|
|
81
86
|
<!-- on a phone the bar's buttons are in one menu (web/src/phone.ts) -->
|
|
82
87
|
<div class="more-wrap">
|
|
83
88
|
<button id="more-btn" class="act-btn act-icon" aria-label="More" aria-haspopup="menu" aria-expanded="false" title="Share, the library, export, activity, your name, help"><svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><circle cx="3.5" cy="8" r="1.3"/><circle cx="8" cy="8" r="1.3"/><circle cx="12.5" cy="8" r="1.3"/></svg><span id="more-badge" class="act-badge" hidden></span></button>
|
|
@@ -229,6 +234,13 @@
|
|
|
229
234
|
<div class="tour-spot"></div><div class="tour-card glass" role="dialog" aria-live="polite"></div>
|
|
230
235
|
</div>
|
|
231
236
|
<div id="help" hidden></div>
|
|
237
|
+
<!-- a tip in place, beside the control it is about (GuideSpec decision 9, web/src/intip.ts); What's
|
|
238
|
+
new, said once when the server runs a newer release than this browser saw (decision 11) -->
|
|
239
|
+
<div id="intip" class="glass" role="dialog" aria-live="polite" hidden></div>
|
|
240
|
+
<div id="whatsnew" class="glass" role="status" hidden></div>
|
|
241
|
+
<!-- a first visit: the tour and the film offered, never imposed; no backdrop, never the keyboard's
|
|
242
|
+
(GuideSpec decision 1) -->
|
|
243
|
+
<div id="welcome" class="glass" role="region" aria-label="Welcome" aria-live="polite" hidden></div>
|
|
232
244
|
<div id="modal" hidden>
|
|
233
245
|
<form id="who-form" class="modal-box glass" autocomplete="off">
|
|
234
246
|
<div class="modal-title" id="who-title">Who is reviewing?</div>
|
package/dist/web/src/canvas.js
CHANGED
|
@@ -405,6 +405,10 @@ export class GraphCanvas {
|
|
|
405
405
|
* fitBoxes) */
|
|
406
406
|
fitExtra = null;
|
|
407
407
|
/** The canvas element: what is laid over it sends it the wheel. */
|
|
408
|
+
/** Whether the pointer is down on the board (a drag, a pan): no moment to reload in (web/src/reload.ts). */
|
|
409
|
+
get pressed() {
|
|
410
|
+
return this.pressing;
|
|
411
|
+
}
|
|
408
412
|
get element() {
|
|
409
413
|
return this.canvas;
|
|
410
414
|
}
|
|
@@ -1439,6 +1443,24 @@ export class GraphCanvas {
|
|
|
1439
1443
|
const k = Math.min(4, (Math.min(this.w, this.h) * 0.42) / Math.max(S.drawnR[c], 20));
|
|
1440
1444
|
this.moveTo(S.cwx[c], S.cwy[c], Math.min(ZOOM_MOST, Math.max(k, minPx / Math.max(S.drawnR[c], 1e-6))), true);
|
|
1441
1445
|
}
|
|
1446
|
+
/** Frame the declarations `set` marks (the board's numbering) in the room the bars and panels
|
|
1447
|
+
* leave, never nearer than a declaration is pointed at well: the tour's views of what a theorem
|
|
1448
|
+
* rests on (GuideSpec decision 2). */
|
|
1449
|
+
fitTo(set, animate = true) {
|
|
1450
|
+
let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
|
|
1451
|
+
for (let i = 0; i < set.length; i++) {
|
|
1452
|
+
if (!set[i])
|
|
1453
|
+
continue;
|
|
1454
|
+
const [x, y] = this.posOf(i);
|
|
1455
|
+
[x0, y0, x1, y1] = [Math.min(x0, x), Math.min(y0, y), Math.max(x1, x), Math.max(y1, y)];
|
|
1456
|
+
}
|
|
1457
|
+
if (!isFinite(x0))
|
|
1458
|
+
return;
|
|
1459
|
+
const vw = this.w - this.insets.left - this.insets.right;
|
|
1460
|
+
const vh = this.h - this.insets.top - this.insets.bottom;
|
|
1461
|
+
const k = Math.min(vw / (x1 - x0 + 80), vh / (y1 - y0 + 80)) * 0.9;
|
|
1462
|
+
this.moveTo((x0 + x1) / 2, (y0 + y1) / 2, Math.min(1.6, Math.max(ZOOM_LEAST, k)), animate);
|
|
1463
|
+
}
|
|
1442
1464
|
/** Bring world point (x, y) to the middle of the unobstructed area at zoom k. */
|
|
1443
1465
|
moveTo(px, py, k, animate, dur = 520) {
|
|
1444
1466
|
if (this.anim)
|
package/dist/web/style.css
CHANGED
|
@@ -607,7 +607,7 @@ button.o-trust:hover { color: var(--accent); background: var(--code-bg); }
|
|
|
607
607
|
#windows > * { pointer-events: auto; }
|
|
608
608
|
/* a popover lies above the windows: it was opened last, and goes on a press anywhere else. Those
|
|
609
609
|
inside a bar raise the bar with them while they are open */
|
|
610
|
-
#bar:has(#share-pop:not([hidden]), #results:not([hidden]), #who-menu:not([hidden])), #viewbar:has(#views-menu:not([hidden]), #focus-menu:not([hidden])), #zoom:has(#eyes-pop:not([hidden])) { z-index: 36; }
|
|
610
|
+
#bar:has(#share-pop:not([hidden]), #results:not([hidden]), #who-menu:not([hidden]), #help-menu:not([hidden])), #viewbar:has(#views-menu:not([hidden]), #focus-menu:not([hidden])), #zoom:has(#eyes-pop:not([hidden])) { z-index: 36; }
|
|
611
611
|
/* a source window (web/src/sourcewin.ts): floating, not modal; as large as its code needs until the
|
|
612
612
|
reader moves or resizes it (floatwin.ts sets its place, and its bounds while it is fitted to its
|
|
613
613
|
code), scrolling down beyond that */
|
|
@@ -1961,6 +1961,9 @@ a.link:hover { text-decoration: underline; }
|
|
|
1961
1961
|
.tour-text { font-size: 13px; line-height: 1.5; color: var(--text); }
|
|
1962
1962
|
.tour-actions { display: flex; align-items: center; gap: 6px; margin-top: 14px; }
|
|
1963
1963
|
.tour-gap { flex: 1; }
|
|
1964
|
+
/* the TCB step's three views of one theorem (GuideSpec decision 2) */
|
|
1965
|
+
.tour-seg { display: inline-flex; margin: 0 0 8px; }
|
|
1966
|
+
@media (prefers-reduced-motion: reduce) { .tour-shade, .tour-spot, .tour-card { transition: none; } }
|
|
1964
1967
|
#help { position: fixed; inset: 0; z-index: 45; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.22); }
|
|
1965
1968
|
.help-box { width: min(660px, calc(100vw - 32px)); max-height: calc(100vh - 48px); overflow: auto; outline: none; }
|
|
1966
1969
|
.help-head { display: flex; justify-content: space-between; align-items: center; }
|
|
@@ -1989,6 +1992,183 @@ kbd {
|
|
|
1989
1992
|
color: var(--text-2); font: 600 14px var(--font); cursor: pointer;
|
|
1990
1993
|
}
|
|
1991
1994
|
.help-btn:hover { border-color: var(--accent); color: var(--accent); }
|
|
1995
|
+
/* the help menu (GuideSpec decision 8): the tips, the keys, the tour; then what the project and
|
|
1996
|
+
VisualProof are, said in it */
|
|
1997
|
+
.help-wrap { position: relative; display: flex; }
|
|
1998
|
+
#help-menu {
|
|
1999
|
+
position: absolute; top: 38px; right: 0; width: min(340px, calc(100vw - 24px)); padding: 6px; border-radius: 14px; z-index: 40;
|
|
2000
|
+
display: flex; flex-direction: column; background: color-mix(in srgb, var(--surface-solid) 96%, transparent);
|
|
2001
|
+
box-shadow: 0 0 0 1px var(--line), var(--shadow-lg);
|
|
2002
|
+
}
|
|
2003
|
+
#help-menu[hidden] { display: none; }
|
|
2004
|
+
.hm-item {
|
|
2005
|
+
display: flex; flex-direction: column; gap: 2px; width: 100%; padding: 7px 10px; border: 0; border-radius: 9px;
|
|
2006
|
+
background: transparent; color: var(--text); font: 13px var(--font); text-align: left; text-decoration: none; cursor: pointer;
|
|
2007
|
+
}
|
|
2008
|
+
.hm-item:hover, .hm-item:focus-visible { background: var(--code-bg); outline: none; }
|
|
2009
|
+
.hm-item[aria-disabled="true"] { cursor: default; }
|
|
2010
|
+
.hm-item[aria-disabled="true"]:hover { background: none; }
|
|
2011
|
+
.hm-t { font-weight: 500; }
|
|
2012
|
+
.hm-h { font-size: 11.5px; font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.04em; }
|
|
2013
|
+
.hm-d { font-size: 12px; line-height: 1.4; color: var(--text-2); }
|
|
2014
|
+
.hm-d code { font: 11px var(--mono); background: var(--code-bg); padding: 1px 4px; border-radius: 4px; overflow-wrap: anywhere; }
|
|
2015
|
+
.hm-sep { height: 1px; margin: 5px 4px; background: var(--line); }
|
|
2016
|
+
.hm-link { color: var(--accent); }
|
|
2017
|
+
/* the tour has pointed at the tips: a dot on the help until the menu is first opened */
|
|
2018
|
+
.help-btn.has-dot, #more-btn.has-dot { position: relative; }
|
|
2019
|
+
.help-btn.has-dot::after, #more-btn.has-dot::after {
|
|
2020
|
+
content: ""; position: absolute; top: -1px; right: -1px; width: 8px; height: 8px; border-radius: 50%;
|
|
2021
|
+
background: var(--accent); box-shadow: 0 0 0 2px var(--surface-solid);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/* the sheet's tabs: the tips first, then the keys (GuideSpec decision 8) */
|
|
2025
|
+
.help-tabs { display: inline-flex; }
|
|
2026
|
+
.help-tabs button { padding: 4px 14px; font-size: 13px; }
|
|
2027
|
+
.help-pane { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
|
|
2028
|
+
.help-pane[hidden] { display: none; }
|
|
2029
|
+
/* the Tips tab (GuideSpec decisions 5–8): the tour film with its chapters, then the tips it does not
|
|
2030
|
+
show, one row each. On a larger screen the sheet is as wide as the film needs, within the window */
|
|
2031
|
+
@media (min-width: 641px) {
|
|
2032
|
+
.help-box:has([data-help-pane="tips"]:not([hidden])) { width: min(1340px, calc(100vw - 48px)); }
|
|
2033
|
+
}
|
|
2034
|
+
.help-pane [hidden] { display: none !important; }
|
|
2035
|
+
.tips-filter { font-family: var(--font); }
|
|
2036
|
+
.tips-list { display: flex; flex-direction: column; gap: 14px; }
|
|
2037
|
+
.tips-group { display: flex; flex-direction: column; gap: 6px; }
|
|
2038
|
+
/* a part of the panel with the ⓘ of its tip beside its heading (GuideSpec decision 15) */
|
|
2039
|
+
.sec-row { display: flex; align-items: center; gap: 4px; }
|
|
2040
|
+
.sec-row > .sec-h { flex: 1; min-width: 0; }
|
|
2041
|
+
.p-info { flex: none; width: 22px; height: 22px; border: none; border-radius: 50%; background: none; color: var(--text-3); font-size: 14px; cursor: pointer; }
|
|
2042
|
+
.p-info:hover { color: var(--accent); background: var(--code-bg); }
|
|
2043
|
+
@keyframes tip-flash { from { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 60%, transparent); } to { box-shadow: 0 0 0 3px transparent; } }
|
|
2044
|
+
/* the film: the player, its chapters beside it (under it, where the sheet is narrow) */
|
|
2045
|
+
.film-h { font-weight: 650; font-size: 15px; letter-spacing: -0.01em; }
|
|
2046
|
+
.film { display: grid; grid-template-columns: minmax(0, 960px) minmax(240px, 320px); gap: 16px; align-items: start; }
|
|
2047
|
+
@media (max-width: 1100px) { .film { grid-template-columns: minmax(0, 1fr); } }
|
|
2048
|
+
/* the film is light: in the dark theme, a thin frame of the theme's own, so that it does not glare */
|
|
2049
|
+
.film-stage { outline: none; border-radius: 12px; }
|
|
2050
|
+
.film-stage:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent); }
|
|
2051
|
+
.film-frame { position: relative; aspect-ratio: 16 / 10; border-radius: 12px; overflow: hidden; background: #f5f5f7; border: 1px solid var(--line); box-shadow: var(--shadow); }
|
|
2052
|
+
:root[data-theme="dark"] .film-frame { border: 6px solid #2c2c2e; box-shadow: 0 0 0 1px var(--line), var(--shadow); }
|
|
2053
|
+
:root[data-theme="dark"] .film-video, :root[data-theme="dark"] .film-still { filter: brightness(0.92); }
|
|
2054
|
+
.film-video, .film-still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
|
|
2055
|
+
/* the controls over the film: play, captions, larger — light, as the film is */
|
|
2056
|
+
.film-controls { position: absolute; left: 12px; right: 12px; bottom: 12px; display: flex; align-items: center; gap: 8px; pointer-events: none; }
|
|
2057
|
+
.film-controls button {
|
|
2058
|
+
pointer-events: auto; min-width: 36px; height: 36px; padding: 0 10px; border-radius: 18px; border: 1px solid rgba(0, 0, 0, 0.08);
|
|
2059
|
+
background: rgba(255, 255, 255, 0.86); color: #1d1d1f; font: 600 13px var(--font); box-shadow: var(--shadow); cursor: pointer;
|
|
2060
|
+
backdrop-filter: blur(10px);
|
|
2061
|
+
}
|
|
2062
|
+
.film-controls button:hover { color: var(--accent); }
|
|
2063
|
+
.film-controls [data-film-cc][aria-pressed="false"] { color: #a1a1a6; text-decoration: line-through; }
|
|
2064
|
+
.film-gap { flex: 1; }
|
|
2065
|
+
/* a caption: over the film at the bottom, in the page's own type, a soft pill readable on the light film */
|
|
2066
|
+
.film-video::cue { color: transparent; background: transparent; }
|
|
2067
|
+
.film-cc {
|
|
2068
|
+
position: absolute; left: 50%; bottom: 60px; transform: translateX(-50%); max-width: min(78%, 760px); padding: 6px 14px;
|
|
2069
|
+
border-radius: 14px; background: rgba(255, 255, 255, 0.84); color: #1d1d1f; font: 500 14px/1.4 var(--font); text-align: center;
|
|
2070
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12); backdrop-filter: blur(10px); pointer-events: none;
|
|
2071
|
+
}
|
|
2072
|
+
/* the film while the server fetches it: said quietly, over the poster */
|
|
2073
|
+
.film-wait {
|
|
2074
|
+
position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 6px 14px; border-radius: 14px;
|
|
2075
|
+
background: rgba(255, 255, 255, 0.84); color: #6e6e73; font: 500 13px/1.4 var(--font); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
2076
|
+
backdrop-filter: blur(10px); pointer-events: none;
|
|
2077
|
+
}
|
|
2078
|
+
.film-controls button[disabled] { opacity: 0.45; cursor: default; }
|
|
2079
|
+
/* a chapter's captions where the film does not play them: listed under its words */
|
|
2080
|
+
.film-cues { margin: 2px 0 0; padding-left: 16px; color: var(--text-2); font-size: 12px; line-height: 1.45; display: flex; flex-direction: column; gap: 2px; }
|
|
2081
|
+
.film-side { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
2082
|
+
.film-list-btn { display: none; align-self: flex-start; }
|
|
2083
|
+
/* large: the film fills the sheet, its chapters beside it (folded away at a press); then the screen */
|
|
2084
|
+
.help-box.film-large { width: calc(100vw - 48px); height: calc(100vh - 48px); max-height: none; }
|
|
2085
|
+
.help-box.film-large [data-help-pane="tips"] > :not([data-film]) { display: none; }
|
|
2086
|
+
.help-box.film-large .film { grid-template-columns: minmax(0, 1fr) minmax(240px, 320px); align-items: start; }
|
|
2087
|
+
.help-box.film-large .film.list-hidden { grid-template-columns: minmax(0, 1fr); }
|
|
2088
|
+
.help-box.film-large .film.list-hidden .film-list { display: none; }
|
|
2089
|
+
.help-box.film-large .film-list-btn { display: inline-flex; padding: 4px 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface-solid); color: var(--text-2); font: 12.5px var(--font); cursor: pointer; }
|
|
2090
|
+
.help-box.film-large .film-frame, .help-box.film-large .film-bar { width: min(100%, calc((100vh - 230px) * 1.6)); margin-left: auto; margin-right: auto; }
|
|
2091
|
+
.help-box.film-large .film-cc { font-size: 19.5px; bottom: 70px; padding: 8px 18px; border-radius: 18px; }
|
|
2092
|
+
@media (max-width: 1100px) { .help-box.film-large .film { grid-template-columns: minmax(0, 1fr); } }
|
|
2093
|
+
.film-stage:fullscreen { background: #000; display: flex; flex-direction: column; justify-content: center; padding: 24px; }
|
|
2094
|
+
.film-stage:fullscreen .film-frame { width: min(100%, calc((100vh - 80px) * 1.6)); margin: 0 auto; border: none; }
|
|
2095
|
+
.film-stage:fullscreen .film-cc { font-size: 24px; bottom: 80px; }
|
|
2096
|
+
.film-stage:fullscreen .film-bar { width: min(100%, calc((100vh - 80px) * 1.6)); margin: 8px auto 0; }
|
|
2097
|
+
.film-stage:fullscreen .film-track { background: rgba(255, 255, 255, 0.22); }
|
|
2098
|
+
/* under the player, a segment per chapter: the one playing fills */
|
|
2099
|
+
.film-bar { display: flex; gap: 3px; margin-top: 6px; }
|
|
2100
|
+
.film-seg { flex-basis: 0; flex-shrink: 1; padding: 5px 0; border: none; background: none; cursor: pointer; min-width: 4px; }
|
|
2101
|
+
.film-track { display: block; height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; }
|
|
2102
|
+
.film-seg:hover .film-track { background: color-mix(in srgb, var(--accent) 22%, var(--line)); }
|
|
2103
|
+
.film-fill { display: block; height: 100%; background: var(--accent); transform-origin: left; transform: scaleX(0); }
|
|
2104
|
+
/* the chapters: one row each, the one playing open */
|
|
2105
|
+
.film-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
2106
|
+
.film-item { border: 1px solid transparent; border-radius: 12px; }
|
|
2107
|
+
.film-item.on { border-color: var(--line); background: var(--surface-solid); box-shadow: var(--shadow); }
|
|
2108
|
+
.film-card { display: flex; gap: 10px; align-items: baseline; padding: 7px 10px; border-radius: 11px; cursor: pointer; outline: none; }
|
|
2109
|
+
.film-card:hover { background: var(--code-bg); }
|
|
2110
|
+
.film-item.on .film-card:hover { background: none; }
|
|
2111
|
+
.film-card:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent); }
|
|
2112
|
+
.film-n { flex: none; width: 1.4em; text-align: right; color: var(--text-3); font-size: 12px; font-variant-numeric: tabular-nums; }
|
|
2113
|
+
.film-item.on .film-n { color: var(--accent); font-weight: 600; }
|
|
2114
|
+
.film-title { font-weight: 600; font-size: 13px; }
|
|
2115
|
+
.film-body { display: flex; flex-direction: column; gap: 6px; padding: 0 12px 11px calc(1.4em + 20px); }
|
|
2116
|
+
/* the tips the film does not show: a row each, its title and its first line; one open */
|
|
2117
|
+
.refs-head { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
|
|
2118
|
+
.refs-head .help-h { margin: 0; }
|
|
2119
|
+
.refs-head .tips-filter { flex: 1; max-width: 320px; margin-left: auto; }
|
|
2120
|
+
.refs { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--surface-solid); }
|
|
2121
|
+
.ref + .ref { border-top: 1px solid var(--line); }
|
|
2122
|
+
.ref.flash { animation: tip-flash 1.6s ease-out; }
|
|
2123
|
+
@media (prefers-reduced-motion: reduce) { .ref.flash { animation: none; box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 60%, transparent); } }
|
|
2124
|
+
.ref-head { display: flex; gap: 12px; align-items: baseline; width: 100%; padding: 9px 12px; border: none; background: none; text-align: left; font: inherit; color: var(--text); cursor: pointer; }
|
|
2125
|
+
.ref-head:hover { background: var(--code-bg); }
|
|
2126
|
+
.ref-title { flex: none; font-weight: 600; font-size: 13px; }
|
|
2127
|
+
.ref-line { flex: 1; min-width: 0; color: var(--text-2); font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2128
|
+
.ref.open .ref-line { display: none; }
|
|
2129
|
+
.ref-body { display: flex; flex-direction: column; gap: 6px; padding: 0 12px 12px; }
|
|
2130
|
+
.ref-clip video { display: block; width: 100%; max-height: 70vh; border-radius: 10px; background: #f5f5f7; object-fit: contain; }
|
|
2131
|
+
.tip-title { font-weight: 650; font-size: 13.5px; letter-spacing: -0.01em; }
|
|
2132
|
+
.tip-text { font-size: 12.5px; line-height: 1.45; color: var(--text-2); }
|
|
2133
|
+
.tip-text b { color: var(--text); font-weight: 600; }
|
|
2134
|
+
.tip-acts { display: flex; gap: 12px; margin-top: 2px; font-size: 12.5px; }
|
|
2135
|
+
.tip-acts a { color: var(--accent); text-decoration: none; }
|
|
2136
|
+
.tip-new { font-size: 10.5px; font-weight: 600; color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 999px; padding: 0 6px; vertical-align: 1px; }
|
|
2137
|
+
.tips-off { display: flex; align-items: center; gap: 6px; }
|
|
2138
|
+
.help-update { margin-top: 6px; color: var(--text); }
|
|
2139
|
+
.help-about.flash { animation: tip-flash 1.6s ease-out; border-radius: 8px; }
|
|
2140
|
+
/* a tip in place, beside its control, its arrow pointing at it (GuideSpec decision 9) */
|
|
2141
|
+
#intip {
|
|
2142
|
+
position: fixed; left: 0; top: 0; z-index: 44; width: min(280px, calc(100vw - 16px)); padding: 11px 13px 10px;
|
|
2143
|
+
border-radius: 12px; background: var(--surface-solid); box-shadow: var(--shadow-lg);
|
|
2144
|
+
}
|
|
2145
|
+
#intip::before {
|
|
2146
|
+
content: ""; position: absolute; left: calc(var(--arrow-x, 50%) - 6px); top: -6px; width: 12px; height: 12px;
|
|
2147
|
+
background: var(--surface-solid); transform: rotate(45deg); border-left: 1px solid var(--line); border-top: 1px solid var(--line);
|
|
2148
|
+
}
|
|
2149
|
+
#intip.above::before { top: auto; bottom: -6px; border: none; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
|
|
2150
|
+
.intip-title { font-weight: 650; font-size: 13.5px; margin-bottom: 4px; }
|
|
2151
|
+
.intip-text { font-size: 12.5px; line-height: 1.45; color: var(--text-2); }
|
|
2152
|
+
.intip-text b { color: var(--text); font-weight: 600; }
|
|
2153
|
+
.intip-acts { display: flex; justify-content: flex-end; gap: 6px; margin-top: 10px; }
|
|
2154
|
+
/* the welcome of a first visit (GuideSpec decision 1): beside the side panel, over the legend; it
|
|
2155
|
+
folds into the dot on ? */
|
|
2156
|
+
#welcome {
|
|
2157
|
+
position: fixed; left: 300px; bottom: 64px; z-index: 44; width: min(360px, calc(100vw - 24px)); padding: 14px 16px 12px;
|
|
2158
|
+
border-radius: 14px; background: var(--surface-solid); box-shadow: var(--shadow-lg);
|
|
2159
|
+
transform-origin: top right; transition: transform 0.36s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.36s;
|
|
2160
|
+
}
|
|
2161
|
+
#welcome.folding { opacity: 0; }
|
|
2162
|
+
@media (prefers-reduced-motion: reduce) { #welcome { transition: none; } }
|
|
2163
|
+
.wel-title { font-weight: 700; font-size: 15px; letter-spacing: -0.01em; margin-bottom: 4px; }
|
|
2164
|
+
.wel-text { font-size: 13px; line-height: 1.45; color: var(--text-2); }
|
|
2165
|
+
.wel-acts { display: flex; align-items: center; gap: 6px; margin-top: 12px; }
|
|
2166
|
+
/* What's new, once: at the bottom, in the middle, quiet (GuideSpec decision 11) */
|
|
2167
|
+
#whatsnew {
|
|
2168
|
+
position: fixed; left: 50%; bottom: 56px; transform: translateX(-50%); z-index: 44; display: flex; align-items: center; gap: 4px;
|
|
2169
|
+
padding: 4px 6px 4px 14px; border-radius: 999px; background: var(--surface-solid); box-shadow: var(--shadow);
|
|
2170
|
+
}
|
|
2171
|
+
.news-open { border: none; background: none; color: var(--accent); font: 600 13px var(--font); cursor: pointer; padding: 4px 0; }
|
|
1992
2172
|
|
|
1993
2173
|
/* the zoom buttons: the bottom right of the canvas, beside the panel when it is open */
|
|
1994
2174
|
#zoom {
|
|
@@ -2441,6 +2621,8 @@ span.tm-row { color: var(--text-2); cursor: default; }
|
|
|
2441
2621
|
#more-badge { position: absolute; top: -5px; right: -5px; }
|
|
2442
2622
|
#more-pop { position: fixed; top: 58px; right: 8px; width: min(260px, calc(100vw - 16px)); z-index: 46; border-radius: 14px; padding: 6px; display: flex; flex-direction: column; background: var(--surface-solid); box-shadow: 0 0 0 0.5px var(--line), var(--shadow-lg); }
|
|
2443
2623
|
#more-pop[hidden] { display: none; }
|
|
2624
|
+
/* the help menu, from ⋯ → Help: at the top right, as ⋯'s own */
|
|
2625
|
+
#help-menu { position: fixed; top: 58px; right: 8px; z-index: 46; background: var(--surface-solid); }
|
|
2444
2626
|
.more-item { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 12px; border: 0; border-radius: 10px; background: none; color: var(--text); font: 15px var(--font); text-align: left; }
|
|
2445
2627
|
.more-item:active { background: var(--code-bg); }
|
|
2446
2628
|
.more-item svg { flex: none; width: 18px; height: 18px; color: var(--text-2); fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
|
|
@@ -2486,6 +2668,12 @@ span.tm-row { color: var(--text-2); cursor: default; }
|
|
|
2486
2668
|
#eyes-pop kbd { display: none; }
|
|
2487
2669
|
.help-touch .help-row { grid-template-columns: 116px minmax(0, 1fr); font-size: 14px; padding: 5px 0; }
|
|
2488
2670
|
.help-touch .help-g { color: var(--text); font-weight: 600; }
|
|
2671
|
+
.film { grid-template-columns: minmax(0, 1fr); }
|
|
2672
|
+
.refs-head .tips-filter { max-width: none; }
|
|
2673
|
+
#whatsnew { bottom: calc(64px + env(safe-area-inset-bottom)); }
|
|
2674
|
+
/* over the bottom of the screen, where the sheet comes up */
|
|
2675
|
+
#welcome { left: 8px; right: 8px; width: auto; bottom: calc(64px + env(safe-area-inset-bottom)); }
|
|
2676
|
+
.wel-acts { flex-wrap: wrap; }
|
|
2489
2677
|
#zoom #zoom-in, #zoom #zoom-out { display: none; }
|
|
2490
2678
|
#foot { left: 8px; bottom: calc(8px + env(safe-area-inset-bottom)); }
|
|
2491
2679
|
/* under the view bar, the review strip, then the selection bar (--strip-h: main.ts) */
|
package/docs/agent-api/export.md
CHANGED
|
@@ -148,8 +148,8 @@ Every field is optional; left out, as a new artwork has it.
|
|
|
148
148
|
names; `from` `none` (default) or `board`.
|
|
149
149
|
- `targets`: `all` (default), `none`, `faded`, or a list of targets marked alone. `keys`, `notes`:
|
|
150
150
|
default true. `edges`: `all` (under a selection, the rest faint), `selection`, `none`.
|
|
151
|
-
- `selection`: `{name, mode}` (`mode` as `POST view`'s
|
|
152
|
-
true). `view`: a view's id; left out, the Project.
|
|
151
|
+
- `selection`: `{name, mode}` (`mode` as `POST view`'s, or `refs`, what it uses directly; default
|
|
152
|
+
`tcb`), lit while `lit` (default true). `view`: a view's id; left out, the Project.
|
|
153
153
|
|
|
154
154
|
Answer: `{ok, link, length, size, names: {clusters, decls, ruled}, targets, selection, left, note}`;
|
|
155
155
|
`left`: names or targets beyond what an artwork carries, left out. Saving both files, the page says
|
|
@@ -33,7 +33,8 @@ name (a private reader's; their opinions, targets, key marks and trust keep thei
|
|
|
33
33
|
`note` its id, `text` then, `shown` whether the view shows it by it), `note` (`what` created,
|
|
34
34
|
edited or deleted; `view`, `title` for a view's own note, "" for a project note; `note` its id;
|
|
35
35
|
`text` after, or before a deletion; `carried` `{mode, from, to}` where a build carried a project
|
|
36
|
-
note to the cluster its declarations moved to, an edit by VisualProof)
|
|
36
|
+
note to the cluster its declarations moved to, an edit by VisualProof), `tool` (the VisualProof
|
|
37
|
+
version serving the site changed: `from`, `to`; `setAside`, a version that failed).
|
|
37
38
|
|
|
38
39
|
## History
|
|
39
40
|
|
|
@@ -51,7 +52,7 @@ on a saved graph (`--graph`): 404. MCP: `history` (`snapshots`, `diff`, `moves`,
|
|
|
51
52
|
"current": 2, "diskBytes": 415893 }
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
Oldest first. `at`: when the build finished (newest `.olean`); `approx`: only an extraction made
|
|
55
|
+
Oldest first. `tool`: the VisualProof version that read it. `at`: when the build finished (newest `.olean`); `approx`: only an extraction made
|
|
55
56
|
before the history dates it. `commit`: checked out when read (`dirty`: `.lean` files differed;
|
|
56
57
|
`guessed`: imported, the last commit before it). `missing`: modules not read (unknown at that
|
|
57
58
|
build, not gone). `bytes`: `new` written to keep it, `all` its files. `renames`: found against the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "visualproof",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "See a Lean codebase's declaration graph and the TCB of its theorems.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
"prepack": "npm run build",
|
|
22
22
|
"serve": "node src/server/main.ts serve",
|
|
23
23
|
"showcase": "node scripts/showcase.mjs",
|
|
24
|
+
"tips:record": "node scripts/tips-record.mjs",
|
|
24
25
|
"typecheck": "tsc --noEmit -p .",
|
|
25
26
|
"test": "node --test --import ./test/setup.ts \"test/*.test.ts\"",
|
|
26
27
|
"test:toolchains": "node scripts/test-toolchains.mjs",
|
|
28
|
+
"test:updates": "node scripts/test-updates.mjs",
|
|
27
29
|
"golden:update": "VP_GOLDEN_UPDATE=1 node --test --import ./test/setup.ts test/compat.test.ts"
|
|
28
30
|
},
|
|
29
31
|
"engines": {
|