pi-weave 0.3.9 → 0.3.11
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 +7 -3
- package/package.json +1 -1
- package/src/web/client/context/context.model.ts +5 -0
- package/src/web/client/dist/app.js +400 -167
- package/src/web/client/graph/Graph.tsx +148 -12
- package/src/web/client/graph/column.model.ts +58 -1
- package/src/web/client/graph/graph.model.ts +114 -0
- package/src/web/client/graph/renderer.ts +21 -7
- package/src/web/client/graph/spotlight.model.ts +476 -0
- package/src/web/client/note/Note.tsx +212 -59
- package/src/web/client/note/Replay.tsx +18 -7
- package/src/web/client/note/drafts.ts +69 -6
- package/src/web/client/note/editbar.model.ts +153 -0
- package/src/web/client/note/note.model.ts +65 -1
- package/src/web/client/note/replay.model.ts +75 -0
- package/src/web/client/search/SearchPalette.tsx +103 -34
- package/src/web/client/search/search.model.ts +533 -26
- package/src/web/client/shell/Shell.tsx +79 -21
- package/src/web/client/shell/StatusBar.tsx +1 -0
- package/src/web/client/shell/icons.model.ts +68 -1
- package/src/web/client/shell/keys.model.ts +11 -1
- package/src/web/client/shell/shell.model.ts +48 -1
- package/src/web/client/shell/theme.model.ts +3 -0
- package/src/web/client/shell/theme.ts +260 -61
- package/src/web/client/shell/workspace.css.ts +38 -11
- package/src/web/client/trail/TrailStrip.tsx +0 -1
- package/src/web/client/trail/trail.model.ts +61 -6
- package/src/web/client/tree/Tree.tsx +3 -7
- package/src/web/shared/themes.ts +1 -1
- package/src/web/shared/workspace.ts +10 -2
|
@@ -67,8 +67,9 @@ export const THEME_CSS = `
|
|
|
67
67
|
--weave-note-gutter:18px;
|
|
68
68
|
/* The desk-and-page split. The workspace is a desk of instruments — tree,
|
|
69
69
|
graph, rail, bars — on the --weave-bg ground; the note column is the one
|
|
70
|
-
*page* lying on it: crust
|
|
71
|
-
|
|
70
|
+
*page* lying on it: crust under dark, plain white under Latte (the
|
|
71
|
+
refresh's "quiet page": paper reads as paper), the ground that sits
|
|
72
|
+
furthest from the desk. Two
|
|
72
73
|
voices in total: sans for instruments and prose alike, mono for data — a
|
|
73
74
|
third face was tried (serif prose) and withdrawn at the user's call; two
|
|
74
75
|
voices read calmer than three. The CSP allows nothing fetched, and both
|
|
@@ -79,7 +80,7 @@ export const THEME_CSS = `
|
|
|
79
80
|
two overlays that float above the grid. Tag pills are 999px — a capsule
|
|
80
81
|
shape, not a scale step. The gate test below refuses any literal px
|
|
81
82
|
radius so the scale cannot drift back. */
|
|
82
|
-
--weave-radius:
|
|
83
|
+
--weave-radius:6px;--weave-radius-pop:10px;
|
|
83
84
|
/* The type ramp, role-named because sizes drift and roles stick. Nine
|
|
84
85
|
steps; every font-size in this sheet is one of these vars — that is a
|
|
85
86
|
gate, not a convention:
|
|
@@ -91,7 +92,7 @@ export const THEME_CSS = `
|
|
|
91
92
|
body 13.5 the note column's prose
|
|
92
93
|
subhead 14 palette input, note-body h2, ribbon icon buttons
|
|
93
94
|
title 15 note-body h1
|
|
94
|
-
display
|
|
95
|
+
display 26 the note's page title (20 before the refresh)
|
|
95
96
|
Two earlier sizes were merged into neighbours: 9px glyphs to prov, and
|
|
96
97
|
the 10px column overlines to caption (caps plus .09em tracking already
|
|
97
98
|
read larger than their point size suggests). \`display\` and \`body\` are
|
|
@@ -106,7 +107,7 @@ export const THEME_CSS = `
|
|
|
106
107
|
rubber stamp. */
|
|
107
108
|
--weave-px-prov:9.5px;--weave-px-caption:10.5px;--weave-px-ui:11.5px;
|
|
108
109
|
--weave-px-row:12px;--weave-px-base:13px;--weave-px-body:13.5px;
|
|
109
|
-
--weave-px-subhead:14px;--weave-px-title:15px;--weave-px-display:
|
|
110
|
+
--weave-px-subhead:14px;--weave-px-title:15px;--weave-px-display:26px;
|
|
110
111
|
}
|
|
111
112
|
@media (prefers-color-scheme: light){
|
|
112
113
|
:root:not([data-weave-theme]){${paletteTokens("light")}}
|
|
@@ -163,10 +164,14 @@ body{font-size:var(--weave-px-base)}
|
|
|
163
164
|
provenance glyph shape carries the distinction the colour swap drops;
|
|
164
165
|
elsewhere the hues are unaffected. The palette's hit rows need the same
|
|
165
166
|
remap: same selected ground, same failure. The label is restated last
|
|
166
|
-
so the selected row is always readable.
|
|
167
|
+
so the selected row is always readable. The ground itself is the Context
|
|
168
|
+
rail's selection: the --weave-new tint plus a 2px inset accent bar, kept
|
|
169
|
+
under the pointer too. It is the only tinted row: the tree is where you
|
|
170
|
+
are, not what the agent touched (the graph shows that). */
|
|
171
|
+
.weave-row-on,.weave-row-on:hover{background:var(--weave-new);box-shadow:inset 2px 0 0 var(--weave-accent)}
|
|
167
172
|
.weave-row-on .weave-twisty,.weave-row-on .weave-kind,.weave-row-on .weave-prov,
|
|
168
173
|
.weave-row-on .weave-meta,.weave-row-on .weave-label{color:var(--weave-fg)}
|
|
169
|
-
.weave-hit-on .weave-hit-
|
|
174
|
+
.weave-hit-on .weave-hit-icon,.weave-hit-on .weave-hit-detail,.weave-hit-on .weave-hit-meta{color:var(--weave-fg)}
|
|
170
175
|
/* A newly-arrived node (a file or note added since the last update, ):
|
|
171
176
|
one short highlight that fades while the label settles from bold back to
|
|
172
177
|
normal. The class is computed from the frame diff in workspace.ts and
|
|
@@ -178,16 +183,6 @@ body{font-size:var(--weave-px-base)}
|
|
|
178
183
|
40%{font-weight:700}
|
|
179
184
|
100%{background:transparent;font-weight:400}
|
|
180
185
|
}
|
|
181
|
-
/* Recall trail (issue #78): a note the agent searched, read or wrote. The
|
|
182
|
-
tint follows the graph's palette for the same kinds (warn → ok → accent)
|
|
183
|
-
and steps down through three strength buckets as the glow fades. */
|
|
184
|
-
.weave-row-trail{--weave-trail:var(--weave-warn);box-shadow:inset 2px 0 0 color-mix(in srgb,var(--weave-trail) var(--weave-trail-mix),transparent);background:color-mix(in srgb,var(--weave-trail) calc(var(--weave-trail-mix) / 6),transparent)}
|
|
185
|
-
.weave-row-trail-read{--weave-trail:var(--weave-ok)}
|
|
186
|
-
.weave-row-trail-wrote{--weave-trail:var(--weave-accent)}
|
|
187
|
-
.weave-row-trail-3{--weave-trail-mix:90%}
|
|
188
|
-
.weave-row-trail-2{--weave-trail-mix:55%}
|
|
189
|
-
.weave-row-trail-1{--weave-trail-mix:25%}
|
|
190
|
-
.weave-row-trail-wrote.weave-row-trail-3 .weave-label{font-weight:600}
|
|
191
186
|
.weave-twisty{width:16px;height:16px;flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--weave-faint);cursor:pointer}
|
|
192
187
|
.weave-kind{flex:none;color:var(--weave-faint);font-size:var(--weave-px-ui)}
|
|
193
188
|
.weave-prov{flex:none;font-size:var(--weave-px-prov)}
|
|
@@ -245,7 +240,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
245
240
|
.weave-note-head{position:sticky;top:0;z-index:2;padding:14px var(--weave-note-gutter) 9px;background:var(--weave-page);border-bottom:1px solid var(--weave-line)}
|
|
246
241
|
/* The page's largest voice, and the point of the review's headline finding:
|
|
247
242
|
a 15px title sat 1.5px above the body it named. --weave-px-display puts the
|
|
248
|
-
title where a page's title belongs, weight 650 for presence at
|
|
243
|
+
title where a page's title belongs, weight 650 for presence at 26px (600
|
|
249
244
|
reads thin at that size, 700 reads as a poster), tracking pulled in by a
|
|
250
245
|
hair because large sans needs it. */
|
|
251
246
|
.weave-note-title{margin:0 0 4px;font-size:var(--weave-px-display);font-weight:650;line-height:1.25;letter-spacing:-.005em;color:var(--weave-fg)}
|
|
@@ -262,20 +257,67 @@ body{font-size:var(--weave-px-base)}
|
|
|
262
257
|
}
|
|
263
258
|
.weave-note-open:hover{color:var(--weave-fg);background:var(--weave-line)}
|
|
264
259
|
.weave-note-open-mark{display:inline-flex;line-height:0}
|
|
265
|
-
/*
|
|
266
|
-
|
|
267
|
-
.
|
|
260
|
+
/* The note's own actions, at the end of the meta line. History is a quiet
|
|
261
|
+
word with an icon; Edit is the one bordered control, and neither outweighs
|
|
262
|
+
the title. */
|
|
263
|
+
.weave-note-actions{margin-left:auto;display:inline-flex;align-items:center;gap:4px}
|
|
264
|
+
.weave-note-meta .weave-note-action{
|
|
265
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
268
266
|
font:inherit;font-size:var(--weave-px-caption);line-height:1;white-space:nowrap;cursor:pointer;
|
|
269
|
-
color:var(--weave-dim);background:
|
|
270
|
-
border:1px solid
|
|
271
|
-
}
|
|
272
|
-
.weave-note-
|
|
273
|
-
|
|
274
|
-
.weave-note-
|
|
275
|
-
.weave-note-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
267
|
+
color:var(--weave-dim);background:none;padding:5px 8px;
|
|
268
|
+
border:1px solid transparent;border-radius:var(--weave-radius);
|
|
269
|
+
}
|
|
270
|
+
.weave-note-meta .weave-note-action .weave-icon{width:13px;height:13px}
|
|
271
|
+
.weave-note-meta .weave-note-action:hover{color:var(--weave-fg);background:var(--weave-new)}
|
|
272
|
+
.weave-note-meta .weave-note-action:disabled{color:var(--weave-faint);background:none;cursor:default}
|
|
273
|
+
.weave-note-meta .weave-note-edit{color:var(--weave-fg);background:var(--weave-page);border-color:var(--weave-line-strong)}
|
|
274
|
+
.weave-note-meta .weave-note-edit:hover{border-color:var(--weave-accent);background:var(--weave-page)}
|
|
275
|
+
.weave-note-meta .weave-note-history[aria-pressed="true"]{color:var(--weave-accent);background:var(--weave-new)}
|
|
276
|
+
/* Where the note lives, above its title: a crumb, not a heading. */
|
|
277
|
+
.weave-note-crumb{margin:0 0 6px;display:flex;align-items:center;gap:5px;font-size:var(--weave-px-caption);color:var(--weave-faint)}
|
|
278
|
+
.weave-note-crumb .weave-icon{width:12px;height:12px}
|
|
279
|
+
/* Who wrote it, in words, with the spine's colour as a dot. */
|
|
280
|
+
.weave-note-meta .weave-prov{display:inline-flex;align-items:center;gap:6px;font-size:var(--weave-px-ui);color:var(--weave-dim)}
|
|
281
|
+
.weave-prov-dot{width:7px;height:7px;border-radius:999px;background:var(--weave-spine,var(--weave-accent))}
|
|
282
|
+
/* The edit bar (E1): one row while editing, pinned over the text it edits.
|
|
283
|
+
Formatting on the left, where the words are; the save state and the two
|
|
284
|
+
ways out on the right. Saving is automatic, so Done is the only
|
|
285
|
+
affirmative control and the only one in the accent. */
|
|
286
|
+
.weave-editbar{
|
|
287
|
+
position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:6px;flex-wrap:wrap;
|
|
288
|
+
min-height:40px;padding:5px 12px;font-size:var(--weave-px-ui);
|
|
289
|
+
background:var(--weave-page);border-bottom:1px solid var(--weave-line);
|
|
290
|
+
}
|
|
291
|
+
.weave-editbar .weave-icon{width:14px;height:14px}
|
|
292
|
+
.weave-editbar-badge{
|
|
293
|
+
display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;
|
|
294
|
+
font-size:var(--weave-px-caption);font-weight:600;color:var(--weave-accent);background:var(--weave-new);
|
|
295
|
+
}
|
|
296
|
+
.weave-editbar-badge .weave-icon{width:12px;height:12px}
|
|
297
|
+
.weave-editbar-tools{display:inline-flex;align-items:center;gap:1px;margin-left:4px;padding-left:8px;border-left:1px solid var(--weave-line)}
|
|
298
|
+
.weave-editbar .weave-editbar-tool{
|
|
299
|
+
display:inline-grid;place-items:center;width:28px;height:28px;padding:0;cursor:pointer;
|
|
300
|
+
color:var(--weave-dim);background:none;border:0;border-radius:var(--weave-radius);
|
|
301
|
+
}
|
|
302
|
+
.weave-editbar .weave-editbar-tool:hover{color:var(--weave-fg);background:var(--weave-new)}
|
|
303
|
+
.weave-editbar-status{margin-left:auto;display:inline-flex;align-items:center;gap:5px;white-space:nowrap;font-size:var(--weave-px-caption);color:var(--weave-faint)}
|
|
304
|
+
.weave-editbar-pending,.weave-editbar-saving{color:var(--weave-dim)}
|
|
305
|
+
.weave-editbar-saved{color:var(--weave-ok)}
|
|
306
|
+
.weave-editbar-failed{color:var(--weave-bad);font-weight:600}
|
|
307
|
+
.weave-editbar .weave-editbar-retry{font:inherit;color:var(--weave-accent);background:none;border:0;padding:2px 4px;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
|
|
308
|
+
.weave-editbar .weave-editbar-discard,.weave-editbar .weave-editbar-done{font:inherit;font-size:var(--weave-px-caption);line-height:1;white-space:nowrap;cursor:pointer;border-radius:var(--weave-radius)}
|
|
309
|
+
.weave-editbar .weave-editbar-discard{padding:7px 9px;color:var(--weave-dim);background:none;border:1px solid transparent}
|
|
310
|
+
.weave-editbar .weave-editbar-discard:hover{color:var(--weave-fg);background:var(--weave-new)}
|
|
311
|
+
.weave-editbar .weave-editbar-done{padding:7px 14px;font-weight:600;color:var(--weave-page);background:var(--weave-accent);border:1px solid var(--weave-accent)}
|
|
312
|
+
.weave-editbar .weave-editbar-done:hover{filter:brightness(1.08)}
|
|
313
|
+
.weave-editbar .weave-editbar-discard:disabled,.weave-editbar .weave-editbar-done:disabled{opacity:.5;cursor:default;filter:none}
|
|
314
|
+
/* A finalized note's opening TLDR, set apart as the first thing to read.
|
|
315
|
+
The label is the card's own; task boxes keep their row and lose the bullet. */
|
|
316
|
+
.weave-tldr{margin:0 0 18px;padding:12px 16px;background:var(--weave-new);border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius)}
|
|
317
|
+
.weave-tldr>p,.weave-tldr>ul,.weave-tldr>ol{margin:0 0 6px}
|
|
318
|
+
.weave-tldr>*:last-child{margin-bottom:0}
|
|
319
|
+
.weave-tldr ul:has(>li>input[type="checkbox"]){list-style:none;padding-left:2px}
|
|
320
|
+
.weave-tldr-label{display:block;margin-bottom:3px;font-size:var(--weave-px-prov);font-weight:700;letter-spacing:.08em;color:var(--weave-accent)}
|
|
279
321
|
/* The replay band sits under the header like the header itself: full width,
|
|
280
322
|
the note's gutter, one line of words, one line of controls. Dots on the
|
|
281
323
|
track are the versions, coloured by who made them. */
|
|
@@ -306,25 +348,28 @@ body{font-size:var(--weave-px-base)}
|
|
|
306
348
|
.weave-replay-controls button:disabled{color:var(--weave-faint);cursor:default;opacity:.6}
|
|
307
349
|
.weave-replay-controls .weave-replay-play{color:var(--weave-page);background:var(--weave-accent);border-color:var(--weave-accent)}
|
|
308
350
|
.weave-replay-controls .weave-replay-play:hover:not(:disabled){filter:brightness(1.08)}
|
|
309
|
-
|
|
351
|
+
/* The change bars (the refresh's H2): one bar per version, as tall as the
|
|
352
|
+
change was big, coloured by who made it; the version on screen is ringed.
|
|
353
|
+
The day labels sit under the band. Heights and label positions arrive as
|
|
354
|
+
custom properties through Preact's CSSOM style path, never an attribute. */
|
|
355
|
+
.weave-replay-track{--weave-replay-at:100%;position:relative;flex:1;min-width:80px;height:46px;margin-left:8px}
|
|
310
356
|
.weave-replay-track::before{
|
|
311
|
-
content:"";position:absolute;left:7px;right:7px;top:
|
|
357
|
+
content:"";position:absolute;left:7px;right:7px;top:31px;height:2px;border-radius:999px;
|
|
312
358
|
background:linear-gradient(to right,color-mix(in srgb,var(--weave-accent) 55%,transparent) var(--weave-replay-at),var(--weave-line-strong) var(--weave-replay-at));
|
|
313
359
|
}
|
|
314
|
-
.weave-replay-
|
|
315
|
-
.weave-replay-
|
|
316
|
-
.weave-replay-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
.weave-replay-ahead::before{opacity:.4}
|
|
360
|
+
.weave-replay-bars{position:absolute;left:7px;right:7px;top:2px;height:26px;pointer-events:none}
|
|
361
|
+
.weave-replay-bar{position:absolute;bottom:0;left:var(--weave-bar-at,0);width:max(1px,min(8px,calc(100% / var(--weave-bars,1) - 2px)));transform:translateX(-50%);height:var(--weave-bar,14%);border-radius:var(--weave-radius);background:var(--weave-who);opacity:.85}
|
|
362
|
+
.weave-replay-ahead{opacity:.35}
|
|
363
|
+
.weave-replay-current{opacity:1;outline:2px solid var(--weave-accent);outline-offset:1px}
|
|
364
|
+
.weave-replay-days{position:absolute;left:7px;right:7px;top:34px;height:12px;pointer-events:none}
|
|
365
|
+
.weave-replay-day{position:absolute;left:var(--weave-day-at,0);transform:translateX(-2px);font-size:var(--weave-px-prov);line-height:12px;color:var(--weave-faint);white-space:nowrap}
|
|
321
366
|
.weave-replay-slider{position:absolute;inset:0;width:100%;height:100%;margin:0;background:transparent;-webkit-appearance:none;appearance:none;cursor:pointer}
|
|
322
367
|
.weave-replay-slider:disabled{cursor:default}
|
|
323
368
|
.weave-replay-slider:focus{outline:none}
|
|
324
|
-
.weave-replay-slider::-webkit-slider-runnable-track{height:
|
|
325
|
-
.weave-replay-slider::-moz-range-track{height:
|
|
369
|
+
.weave-replay-slider::-webkit-slider-runnable-track{height:46px;background:transparent}
|
|
370
|
+
.weave-replay-slider::-moz-range-track{height:46px;background:transparent}
|
|
326
371
|
.weave-replay-slider::-webkit-slider-thumb{
|
|
327
|
-
-webkit-appearance:none;appearance:none;width:14px;height:14px;margin-top:
|
|
372
|
+
-webkit-appearance:none;appearance:none;width:14px;height:14px;margin-top:25px;border-radius:999px;
|
|
328
373
|
background:var(--weave-page);border:2px solid var(--weave-accent);box-sizing:border-box;
|
|
329
374
|
}
|
|
330
375
|
.weave-replay-slider::-moz-range-thumb{
|
|
@@ -342,7 +387,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
342
387
|
display:block;width:100%;flex:1 0 auto;min-height:12em;resize:none;
|
|
343
388
|
padding:12px var(--weave-note-gutter) 28px;box-sizing:border-box;
|
|
344
389
|
font-family:var(--weave-mono);font-size:var(--weave-px-row);line-height:1.6;
|
|
345
|
-
color:var(--weave-fg);background:var(--weave-
|
|
390
|
+
color:var(--weave-fg);background:var(--weave-page);border:0;outline:0;
|
|
346
391
|
}
|
|
347
392
|
/* The \`## Raw\` box under the editor: folded by default so a long
|
|
348
393
|
dictation never outgrows the note, a dashed edge to say "captured, not
|
|
@@ -516,6 +561,114 @@ body{font-size:var(--weave-px-base)}
|
|
|
516
561
|
border-top:1px solid var(--weave-line);
|
|
517
562
|
}
|
|
518
563
|
|
|
564
|
+
/* graph spotlight (G1) ---------------------------------------------------
|
|
565
|
+
The field floating top-left over the canvas, and the side sheet top-right.
|
|
566
|
+
Both are overlays on the stage, so they sit on the panel ground with a
|
|
567
|
+
hairline and the pop radius — no elevation shadow, per the sheet's rule.
|
|
568
|
+
The spotlight's voice is --weave-warn: the highlighter colour the WebGL
|
|
569
|
+
side paints lit edges in (graph.model.ts SPOTLIGHT_EDGE_SLOT), so the chip,
|
|
570
|
+
the legend, the marked words and the lit dots all say "lit" in one hue.
|
|
571
|
+
The sheet stops short of the control strip and count line under the
|
|
572
|
+
canvas (about 54px together) and scrolls inside itself. Button rules are
|
|
573
|
+
qualified by their overlay (.weave-sheet .weave-sheet-open) because the
|
|
574
|
+
workspace sheet's \`.weave-workbench button{font:inherit;color:inherit}\`
|
|
575
|
+
reset is installed later and would outrank a single class. */
|
|
576
|
+
.weave-spotlight{
|
|
577
|
+
position:absolute;z-index:3;top:10px;left:10px;width:min(330px,calc(100% - 20px));box-sizing:border-box;
|
|
578
|
+
display:flex;align-items:center;gap:6px;padding:3px 5px 3px 9px;
|
|
579
|
+
color:var(--weave-faint);background:var(--weave-panel);
|
|
580
|
+
border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius-pop);
|
|
581
|
+
}
|
|
582
|
+
/* The pill is the focus ring: the input inside it drops the global outline
|
|
583
|
+
and the frame takes a 2px accent edge (border plus an inset hairline). */
|
|
584
|
+
.weave-spotlight:focus-within{border-color:var(--weave-accent);box-shadow:inset 0 0 0 1px var(--weave-accent)}
|
|
585
|
+
.weave-spotlight-input:focus-visible{outline:none}
|
|
586
|
+
.weave-spotlight-on{color:var(--weave-warn)}
|
|
587
|
+
.weave-spotlight-icon{flex:none;display:block}
|
|
588
|
+
.weave-spotlight-input{
|
|
589
|
+
flex:1;min-width:0;height:24px;padding:0;font:inherit;font-size:var(--weave-px-row);
|
|
590
|
+
color:var(--weave-fg);background:transparent;border:0;outline:0;
|
|
591
|
+
}
|
|
592
|
+
.weave-spotlight-input::placeholder{color:var(--weave-faint)}
|
|
593
|
+
.weave-spotlight-input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
|
|
594
|
+
.weave-spotlight-count{
|
|
595
|
+
flex:none;padding:1px 7px;font-size:var(--weave-px-caption);font-weight:650;white-space:nowrap;
|
|
596
|
+
color:var(--weave-warn);background:color-mix(in srgb,var(--weave-warn) 16%,transparent);border-radius:999px;
|
|
597
|
+
}
|
|
598
|
+
.weave-spotlight-none{color:var(--weave-dim);background:var(--weave-line)}
|
|
599
|
+
.weave-spotlight-by{flex:none;font-size:var(--weave-px-caption);color:var(--weave-dim);white-space:nowrap}
|
|
600
|
+
.weave-spotlight .weave-spotlight-clear{
|
|
601
|
+
flex:none;padding:1px 5px;cursor:pointer;font-family:var(--weave-mono);font-size:var(--weave-px-prov);
|
|
602
|
+
color:var(--weave-faint);background:transparent;border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);
|
|
603
|
+
}
|
|
604
|
+
.weave-spotlight .weave-spotlight-clear:hover{color:var(--weave-fg);border-color:var(--weave-accent)}
|
|
605
|
+
.weave-legend-lit{color:var(--weave-warn)}
|
|
606
|
+
.weave-sheet{
|
|
607
|
+
position:absolute;z-index:3;top:10px;right:10px;width:min(300px,calc(100% - 20px));max-height:calc(100% - 74px);
|
|
608
|
+
box-sizing:border-box;overflow:auto;padding:12px 14px 14px;
|
|
609
|
+
font-size:var(--weave-px-base);color:var(--weave-fg);background:var(--weave-panel);
|
|
610
|
+
border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius-pop);
|
|
611
|
+
}
|
|
612
|
+
.weave-sheet .weave-sheet-close{
|
|
613
|
+
position:absolute;top:6px;right:6px;width:24px;height:24px;padding:0;cursor:pointer;
|
|
614
|
+
font-size:var(--weave-px-display);line-height:1;color:var(--weave-dim);
|
|
615
|
+
background:transparent;border:0;border-radius:var(--weave-radius);
|
|
616
|
+
}
|
|
617
|
+
.weave-sheet .weave-sheet-close:hover{color:var(--weave-fg);background:var(--weave-line)}
|
|
618
|
+
.weave-sheet-crumb{
|
|
619
|
+
margin:0 28px 2px 0;display:flex;align-items:center;gap:5px;min-width:0;
|
|
620
|
+
font-size:var(--weave-px-caption);color:var(--weave-faint);
|
|
621
|
+
}
|
|
622
|
+
.weave-sheet-crumb span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
623
|
+
.weave-sheet-title{
|
|
624
|
+
margin:0 20px 4px 0;font-size:var(--weave-px-title);font-weight:650;line-height:1.3;overflow-wrap:anywhere;
|
|
625
|
+
}
|
|
626
|
+
.weave-sheet-meta{margin:0;display:flex;align-items:center;gap:5px;font-size:var(--weave-px-ui);color:var(--weave-dim);text-transform:capitalize}
|
|
627
|
+
.weave-sheet-when{color:var(--weave-faint);text-transform:none}
|
|
628
|
+
.weave-sheet-text{
|
|
629
|
+
margin:10px 0 0;padding:8px 10px;line-height:1.55;overflow-wrap:anywhere;
|
|
630
|
+
background:var(--weave-new);border:1px solid color-mix(in srgb,var(--weave-accent) 30%,transparent);
|
|
631
|
+
border-radius:var(--weave-radius-pop);
|
|
632
|
+
}
|
|
633
|
+
.weave-sheet-text-head{
|
|
634
|
+
display:block;margin:0 0 2px;font-size:var(--weave-px-prov);font-weight:700;letter-spacing:.09em;
|
|
635
|
+
text-transform:uppercase;color:var(--weave-accent);
|
|
636
|
+
}
|
|
637
|
+
.weave-sheet-mark{border-radius:var(--weave-radius)}
|
|
638
|
+
.weave-sheet-why{margin:8px 0 0;display:flex;gap:5px;font-size:var(--weave-px-caption);color:var(--weave-dim)}
|
|
639
|
+
.weave-sheet-why span{color:var(--weave-warn)}
|
|
640
|
+
.weave-sheet-section{margin:12px 0 0}
|
|
641
|
+
.weave-sheet-heading{
|
|
642
|
+
margin:0 0 3px;display:flex;align-items:center;font-size:var(--weave-px-caption);font-weight:600;
|
|
643
|
+
letter-spacing:.09em;text-transform:uppercase;color:var(--weave-faint);
|
|
644
|
+
}
|
|
645
|
+
.weave-sheet-count{margin-left:auto;font-family:var(--weave-mono);letter-spacing:0}
|
|
646
|
+
.weave-sheet-rows{margin:0;padding:0;list-style:none}
|
|
647
|
+
.weave-sheet .weave-sheet-row{
|
|
648
|
+
display:flex;align-items:center;gap:7px;width:100%;padding:3px 0;cursor:pointer;text-align:left;
|
|
649
|
+
font:inherit;font-size:var(--weave-px-row);color:var(--weave-fg);background:none;border:0;
|
|
650
|
+
}
|
|
651
|
+
.weave-sheet .weave-sheet-row:hover{color:var(--weave-accent)}
|
|
652
|
+
.weave-sheet-row-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
653
|
+
.weave-sheet-dot{flex:none;width:6px;height:6px;border-radius:999px;background:var(--weave-faint)}
|
|
654
|
+
.weave-sheet-dot-lit{background:var(--weave-warn)}
|
|
655
|
+
.weave-sheet-more{margin:2px 0 0;font-size:var(--weave-px-caption);color:var(--weave-faint)}
|
|
656
|
+
.weave-sheet-actions{margin:14px 0 0;display:flex;gap:6px;flex-wrap:wrap}
|
|
657
|
+
.weave-sheet .weave-sheet-open,.weave-sheet .weave-sheet-split{
|
|
658
|
+
padding:5px 11px;cursor:pointer;font:inherit;font-size:var(--weave-px-ui);font-weight:600;
|
|
659
|
+
border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);
|
|
660
|
+
}
|
|
661
|
+
.weave-sheet .weave-sheet-open{color:var(--weave-page);background:var(--weave-accent);border-color:var(--weave-accent)}
|
|
662
|
+
.weave-sheet .weave-sheet-open:hover{filter:brightness(1.08)}
|
|
663
|
+
.weave-sheet .weave-sheet-split{color:var(--weave-fg);background:var(--weave-page)}
|
|
664
|
+
.weave-sheet .weave-sheet-split:hover{border-color:var(--weave-accent)}
|
|
665
|
+
/* Side by side the field (330) and the sheet (300) need about 660px of
|
|
666
|
+
stage; a narrower graph — a split pane, a small window — drops the sheet
|
|
667
|
+
under the field instead of letting the two overlap. */
|
|
668
|
+
.weave-graph{container-type:inline-size}
|
|
669
|
+
@container (max-width:680px){.weave-sheet{top:50px;max-height:calc(100% - 114px)}}
|
|
670
|
+
/* end graph spotlight ---------------------------------------------------- */
|
|
671
|
+
|
|
519
672
|
/* context rail ---------------------------------------------------------- */
|
|
520
673
|
/* The \`.weave-empty\` block that used to sit above went with \`EmptyState.tsx\`
|
|
521
674
|
in P3: every column now has its own empty state (\`treeEmptyMessage\`,
|
|
@@ -535,9 +688,8 @@ body{font-size:var(--weave-px-base)}
|
|
|
535
688
|
.weave-trail{padding-top:6px;padding-bottom:6px;border-bottom:1px solid var(--weave-line)}
|
|
536
689
|
.weave-trail-head{display:flex;align-items:center;gap:6px;font-size:var(--weave-px-caption);font-weight:600;letter-spacing:.09em;color:var(--weave-faint);text-transform:uppercase}
|
|
537
690
|
.weave-trail-head .weave-ctx-count{margin-left:0}
|
|
538
|
-
.weave-trail-
|
|
539
|
-
.weave-trail-
|
|
540
|
-
.weave-trail-replay:hover,.weave-trail-turn:hover{color:var(--weave-fg)}
|
|
691
|
+
.weave-trail-turn{font:inherit;font-size:var(--weave-px-caption);letter-spacing:0;text-transform:none;color:var(--weave-dim);background:none;border:1px solid var(--weave-line);border-radius:var(--weave-radius);padding:0 6px;cursor:pointer}
|
|
692
|
+
.weave-trail-turn:hover{color:var(--weave-fg)}
|
|
541
693
|
.weave-trail-turn-on{color:var(--weave-accent);border-color:var(--weave-accent)}
|
|
542
694
|
.weave-trail-steps{margin:4px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:2px}
|
|
543
695
|
.weave-trail-step{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px;padding-left:10px;position:relative;line-height:1.45}
|
|
@@ -596,6 +748,7 @@ body{font-size:var(--weave-px-base)}
|
|
|
596
748
|
.weave-status-cwd,.weave-status-sel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
597
749
|
.weave-status-cwd{max-width:38%;color:var(--weave-faint)}
|
|
598
750
|
.weave-status-sel{color:var(--weave-fg)}
|
|
751
|
+
.weave-status-hint{margin-left:auto;padding-left:8px;white-space:nowrap;color:var(--weave-faint)}
|
|
599
752
|
|
|
600
753
|
/* overlays: the ⌘K palette and the ? help sheet (P4) --------------------- */
|
|
601
754
|
/* The scrim is a click target that closes, and the reason both overlays sit
|
|
@@ -611,31 +764,77 @@ body{font-size:var(--weave-px-base)}
|
|
|
611
764
|
overflow:hidden;background:var(--weave-panel);color:var(--weave-fg);
|
|
612
765
|
border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius-pop);
|
|
613
766
|
}
|
|
767
|
+
/* The ⌘K palette, grouped and compact: an input row (glyph, query, Esc), a
|
|
768
|
+
scope row of pills that Tab cycles, one line per result under small
|
|
769
|
+
capitals group heads, and a footer of key hints. Wider than the help sheet
|
|
770
|
+
because a row carries a title, a snippet and a meta column side by side. */
|
|
771
|
+
.weave-palette{max-width:640px}
|
|
772
|
+
.weave-palette-bar{
|
|
773
|
+
flex:none;display:flex;align-items:center;gap:8px;padding:0 11px;
|
|
774
|
+
border-bottom:1px solid var(--weave-line);
|
|
775
|
+
}
|
|
776
|
+
.weave-palette-glyph{color:var(--weave-faint)}
|
|
614
777
|
.weave-palette-input{
|
|
615
|
-
flex:
|
|
616
|
-
color:var(--weave-fg);background:transparent;border:0;
|
|
617
|
-
|
|
778
|
+
flex:1;min-width:0;height:36px;padding:0;font:inherit;font-size:var(--weave-px-subhead);
|
|
779
|
+
color:var(--weave-fg);background:transparent;border:0;border-radius:0;
|
|
780
|
+
}
|
|
781
|
+
.weave-palette-input:focus-visible{outline:0}
|
|
782
|
+
.weave-palette-input::-webkit-search-cancel-button{display:none}
|
|
783
|
+
.weave-palette-bar:focus-within{box-shadow:inset 0 -1px 0 var(--weave-accent)}
|
|
784
|
+
.weave-palette-kbd{
|
|
785
|
+
flex:none;padding:0 4px;font-family:inherit;font-size:var(--weave-px-prov);line-height:14px;
|
|
786
|
+
color:var(--weave-faint);border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius);
|
|
787
|
+
}
|
|
788
|
+
.weave-palette-scopes{
|
|
789
|
+
flex:none;display:flex;flex-wrap:wrap;gap:3px;padding:5px 8px;
|
|
790
|
+
border-bottom:1px solid var(--weave-line);
|
|
618
791
|
}
|
|
619
|
-
.weave-palette-
|
|
620
|
-
|
|
792
|
+
.weave-palette-scope{
|
|
793
|
+
font:inherit;font-size:var(--weave-px-caption);line-height:1;padding:3px 9px;cursor:pointer;
|
|
794
|
+
color:var(--weave-dim);background:none;border:0;border-radius:999px;
|
|
795
|
+
}
|
|
796
|
+
.weave-palette-scope:hover{color:var(--weave-fg);background:var(--weave-line)}
|
|
797
|
+
.weave-palette-scope[aria-pressed="true"]{color:var(--weave-panel);background:var(--weave-fg);font-weight:600}
|
|
798
|
+
.weave-palette-scope-count{font-variant-numeric:tabular-nums}
|
|
799
|
+
.weave-hits{flex:1;min-height:0;overflow:auto;margin:0;padding:0 0 4px;list-style:none}
|
|
800
|
+
.weave-hit-section{list-style:none}
|
|
801
|
+
.weave-hit-group{
|
|
802
|
+
padding:7px 11px 2px;font-size:var(--weave-px-prov);font-weight:700;letter-spacing:.08em;
|
|
803
|
+
text-transform:uppercase;color:var(--weave-faint);
|
|
804
|
+
}
|
|
805
|
+
.weave-hit-rows{margin:0;padding:0;list-style:none}
|
|
621
806
|
.weave-hit{
|
|
622
|
-
display:flex;align-items:
|
|
623
|
-
min-width:0;white-space:nowrap;
|
|
807
|
+
display:flex;align-items:center;gap:8px;padding:3px 11px;cursor:pointer;
|
|
808
|
+
min-width:0;white-space:nowrap;font-size:var(--weave-px-row);
|
|
624
809
|
}
|
|
625
810
|
.weave-hit-on{background:var(--weave-new);box-shadow:inset 2px 0 0 var(--weave-accent)}
|
|
626
|
-
.weave-hit-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
}
|
|
630
|
-
.weave-hit-note .weave-hit-badge{color:var(--weave-accent)}
|
|
631
|
-
.weave-hit-label{flex:none;max-width:46%;overflow:hidden;text-overflow:ellipsis}
|
|
811
|
+
.weave-hit-icon{color:var(--weave-faint)}
|
|
812
|
+
.weave-hit-notes .weave-hit-icon{color:var(--weave-accent)}
|
|
813
|
+
.weave-hit-label{flex:none;max-width:46%;overflow:hidden;text-overflow:ellipsis;font-weight:600;color:var(--weave-fg)}
|
|
814
|
+
.weave-hit-mono{font-family:var(--weave-mono);font-size:var(--weave-px-ui);font-weight:500}
|
|
632
815
|
.weave-hit-detail{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:var(--weave-px-ui);color:var(--weave-dim)}
|
|
816
|
+
/* The match marks (search rows, the graph sheet) are a find-in-page amber.
|
|
817
|
+
Dark themes tint their own light --weave-warn, and the marked words go
|
|
818
|
+
white: the theme's text on that tint measured 3.3–3.6:1 in the Catppuccin
|
|
819
|
+
darks, white is 5.5:1 or better in every dark theme. A light theme's
|
|
820
|
+
--weave-warn is a deep brown that tints to mud, so light schemes take a
|
|
821
|
+
fixed amber under their own text instead. */
|
|
822
|
+
.weave-hit-mark,.weave-sheet-mark{color:#fff;background:color-mix(in srgb,var(--weave-warn) 28%,transparent)}
|
|
823
|
+
.weave-hit-mark{border-radius:var(--weave-radius);padding:0 1px}
|
|
824
|
+
:root[data-weave-scheme="light"] .weave-hit-mark,:root[data-weave-scheme="light"] .weave-sheet-mark{color:var(--weave-fg);background:color-mix(in srgb,#f2a93b 34%,transparent)}
|
|
825
|
+
.weave-hit-meta{flex:none;margin-left:auto;font-size:var(--weave-px-caption);color:var(--weave-faint);font-variant-numeric:tabular-nums}
|
|
633
826
|
.weave-palette-status{margin:0;padding:14px 11px;color:var(--weave-dim);line-height:1.5}
|
|
634
827
|
.weave-palette-foot,.weave-help-foot{
|
|
635
828
|
display:flex;gap:12px;margin:0;padding:4px 11px;font-size:var(--weave-px-caption);color:var(--weave-faint);
|
|
636
829
|
border-top:1px solid var(--weave-line);
|
|
637
830
|
}
|
|
638
|
-
.weave-palette-
|
|
831
|
+
.weave-palette-foot{align-items:center;flex-wrap:wrap;row-gap:2px;min-height:26px;box-sizing:border-box;background:var(--weave-bg)}
|
|
832
|
+
.weave-palette-light{
|
|
833
|
+
margin-left:auto;display:flex;align-items:center;gap:6px;padding:0;cursor:pointer;white-space:nowrap;
|
|
834
|
+
font:inherit;font-weight:600;color:var(--weave-accent);background:none;border:0;
|
|
835
|
+
}
|
|
836
|
+
.weave-palette-light .weave-palette-kbd{color:inherit;border-color:currentColor}
|
|
837
|
+
.weave-help-hint{margin-left:auto}
|
|
639
838
|
.weave-help-title{margin:0;padding:9px 11px;font-size:var(--weave-px-base);font-weight:600;border-bottom:1px solid var(--weave-line)}
|
|
640
839
|
.weave-keys{flex:1;min-height:0;overflow:auto;margin:0;padding:5px 11px}
|
|
641
840
|
.weave-key-group{margin:0 0 3px;font-size:var(--weave-px-prov);letter-spacing:.09em;text-transform:uppercase;color:var(--weave-faint)}
|
|
@@ -5,7 +5,7 @@ export const WORKSPACE_CSS = `
|
|
|
5
5
|
.weave-workbench button:focus-visible,.weave-workbench summary:focus-visible{outline:2px solid var(--weave-accent);outline-offset:-2px}
|
|
6
6
|
.weave-workbench button:disabled{opacity:.35;cursor:default}
|
|
7
7
|
.weave-ribbon{width:44px;flex:none;display:flex;align-items:center;flex-direction:column;gap:8px;padding:12px 0;background:var(--weave-panel);border-right:1px solid var(--weave-line)}
|
|
8
|
-
.weave-ribbon button{width:32px;height:32px;border:0;border-radius:var(--weave-radius);background:transparent;font-size:var(--weave-px-display);color:var(--weave-dim)}
|
|
8
|
+
.weave-ribbon button{width:32px;height:32px;display:grid;place-items:center;border:0;border-radius:var(--weave-radius);background:transparent;font-size:var(--weave-px-display);color:var(--weave-dim)}
|
|
9
9
|
.weave-ribbon button:hover,.weave-ribbon button[aria-pressed=true]{color:var(--weave-accent);background:var(--weave-new)}
|
|
10
10
|
.weave-ribbon-space{flex:1}
|
|
11
11
|
.weave-sidebar{flex:none;min-width:0;display:flex;flex-direction:column;background:var(--weave-panel);overflow:hidden}
|
|
@@ -65,20 +65,24 @@ export const WORKSPACE_CSS = `
|
|
|
65
65
|
.weave-pane-menu button{text-align:left;border:0;background:none;padding:9px 10px;font-size:var(--weave-px-row)}
|
|
66
66
|
.weave-pane-menu button:hover{background:var(--weave-new)}
|
|
67
67
|
.weave-pane-content{min-width:0;min-height:0;display:flex;overflow:hidden;position:relative}
|
|
68
|
-
.
|
|
68
|
+
/* The reading column's gutters. Centred at the reading width; where the
|
|
69
|
+
floating Context card covers the right margin, the right gutter grows to
|
|
70
|
+
clear it and the column slides left before it narrows. */
|
|
71
|
+
.weave-document{display:flex;min-width:0;min-height:0;flex:1;
|
|
72
|
+
--weave-gutter-c:max(24px,calc((100% - var(--weave-reading-width,760px))/2));
|
|
73
|
+
--weave-gutter-r:max(var(--weave-gutter-c),var(--weave-card-space,0px));
|
|
74
|
+
--weave-gutter-l:max(24px,min(var(--weave-gutter-c),calc(100% - var(--weave-reading-width,760px) - var(--weave-gutter-r))))}
|
|
69
75
|
.weave-document .weave-note{width:100%;border-left:0}
|
|
70
|
-
.weave-document .weave-note-head{position:static;padding:28px
|
|
71
|
-
.weave-document .weave-note-title{font-size:var(--weave-px-display);letter-spacing:-.03em;margin-bottom:
|
|
72
|
-
.weave-document .weave-note-body{padding:10px
|
|
76
|
+
.weave-document .weave-note-head{position:static;padding:28px var(--weave-gutter-r) 18px var(--weave-gutter-l);border:0}
|
|
77
|
+
.weave-document .weave-note-title{font-size:var(--weave-px-display);letter-spacing:-.03em;margin-bottom:10px}
|
|
78
|
+
.weave-document .weave-note-body{padding:10px var(--weave-gutter-r) 64px var(--weave-gutter-l);font-size:var(--weave-note-size,var(--weave-px-subhead));line-height:1.8}
|
|
73
79
|
.weave-document .weave-note-body h1{font-size:var(--weave-px-display);line-height:1.4;margin-bottom:18px}
|
|
74
80
|
.weave-document .weave-note-body h2{font-size:var(--weave-px-title);margin-top:28px}
|
|
75
|
-
.weave-document .weave-note-editor{padding:14px
|
|
81
|
+
.weave-document .weave-note-editor{padding:14px var(--weave-gutter-r) 14px var(--weave-gutter-l);min-height:220px;flex:1;font-size:var(--weave-note-size,var(--weave-px-subhead))}
|
|
76
82
|
.weave-document .weave-note-tags{margin-top:12px}
|
|
77
|
-
.weave-document .weave-replay{padding:12px
|
|
78
|
-
.weave-document .weave-raw{margin:0
|
|
79
|
-
.weave-document .weave-
|
|
80
|
-
.weave-document .weave-note-edit{color:var(--weave-dim);background:transparent;border-color:transparent}
|
|
81
|
-
.weave-document .weave-note-edit:hover{color:var(--weave-accent);background:var(--weave-new);border-color:transparent}
|
|
83
|
+
.weave-document .weave-replay{padding:12px var(--weave-gutter-r) 14px var(--weave-gutter-l)}
|
|
84
|
+
.weave-document .weave-raw{margin:0 var(--weave-gutter-r) 28px var(--weave-gutter-l)}
|
|
85
|
+
.weave-document .weave-editbar{padding-right:calc(12px + var(--weave-card-space,0px))}
|
|
82
86
|
.weave-welcome{align-self:center;margin:auto;padding:35px;max-width:560px;color:var(--weave-dim);line-height:1.7}
|
|
83
87
|
.weave-welcome-mark{font-size:var(--weave-px-display);color:var(--weave-accent)}
|
|
84
88
|
.weave-welcome h1{font-size:var(--weave-px-display);line-height:1.4;letter-spacing:-.025em;color:var(--weave-fg);font-weight:550}
|
|
@@ -117,6 +121,29 @@ export const WORKSPACE_CSS = `
|
|
|
117
121
|
.weave-footer>.weave-status{flex:1;min-width:0;border:0}
|
|
118
122
|
.weave-footer>span{padding:4px 10px;white-space:nowrap}
|
|
119
123
|
.weave-footer>button{font:inherit;color:var(--weave-fg);background:none;border:0;padding:7px 12px;cursor:pointer}
|
|
124
|
+
/* Context as a floating card (C1): over the page's right margin, below the
|
|
125
|
+
pane toolbar, folding to a pill in the toolbar strip. Pinned, it is the
|
|
126
|
+
column it always was. The shadow is the card's only elevation, and lives
|
|
127
|
+
here rather than in THEME_CSS, whose surfaces are flat by rule. */
|
|
128
|
+
.weave-context-dock.weave-context-float{position:absolute;top:90px;right:14px;bottom:auto;z-index:10;width:var(--weave-card-width);max-height:calc(100% - 104px);border:1px solid var(--weave-line-strong);border-radius:var(--weave-radius-pop);background:var(--weave-panel);box-shadow:0 12px 32px #0000001f,0 2px 6px #00000014;transition:opacity 160ms ease,visibility 0s}
|
|
129
|
+
.weave-context-dock.weave-context-float[data-open=false]{width:var(--weave-card-width);opacity:0;visibility:hidden;transition:opacity 160ms ease,visibility 0s 160ms}
|
|
130
|
+
.weave-context-float>.weave-workspace-divider{display:none}
|
|
131
|
+
.weave-context-float>.weave-sidebar,.weave-context-float[data-open=false]>.weave-sidebar{width:100%;max-height:100%;border:0;background:none;transform:none}
|
|
132
|
+
.weave-context-float .weave-sidebar-heading{height:38px;padding:0 6px 0 12px;border-bottom:1px solid var(--weave-line)}
|
|
133
|
+
.weave-context-float .weave-rail{padding:4px 12px 10px}
|
|
134
|
+
.weave-context-float .weave-context-graph-slot{max-height:calc(100dvh - 260px)}
|
|
135
|
+
.weave-context-float .weave-context-tags{height:auto!important;max-height:220px}
|
|
136
|
+
.weave-context-float .weave-ctx-group>.weave-workspace-divider{display:none}
|
|
137
|
+
.weave-context-heading strong{color:var(--weave-fg)}
|
|
138
|
+
.weave-context-count{min-width:18px;padding:1px 6px;border-radius:999px;background:var(--weave-raise);color:var(--weave-dim);font-size:var(--weave-px-caption);line-height:1.4;text-align:center}
|
|
139
|
+
.weave-sidebar-heading .weave-context-pin{margin-left:auto}
|
|
140
|
+
.weave-context-heading button:last-child{margin-left:0}
|
|
141
|
+
.weave-context-heading .weave-context-pin[aria-pressed=true]{color:var(--weave-accent)}
|
|
142
|
+
.weave-context-heading button{display:grid;place-items:center;width:28px;height:28px;padding:0}
|
|
143
|
+
.weave-context-pill{position:absolute;top:47px;right:54px;z-index:10;display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 6px 0 9px;border:1px solid var(--weave-line-strong);border-radius:999px;background:var(--weave-panel);color:var(--weave-dim)!important;font-size:var(--weave-px-caption)!important;box-shadow:0 2px 8px #00000014}
|
|
144
|
+
.weave-context-pill:hover{color:var(--weave-fg)!important;border-color:var(--weave-accent)}
|
|
145
|
+
.weave-context-pill .weave-icon{width:13px;height:13px}
|
|
146
|
+
.weave-pane-under-card{--weave-card-space:calc(var(--weave-card-width) + 28px)}
|
|
120
147
|
@media(max-width:1049px){
|
|
121
148
|
.weave-context-dock{position:absolute;right:0;top:0;bottom:0;z-index:10;width:var(--weave-sidebar-width)}
|
|
122
149
|
.weave-sidebar-context{border-left:1px solid var(--weave-line-strong)}
|
|
@@ -27,7 +27,6 @@ export function TrailStrip(props: TrailStripProps) {
|
|
|
27
27
|
<h4 class="weave-ctx-head weave-trail-head">
|
|
28
28
|
<span class="weave-trail-title">{turnHeading(shown, shown === latest)}</span>
|
|
29
29
|
<span class="weave-ctx-count" title="Notes read or written">{shown.used}</span>
|
|
30
|
-
{shown.steps.length === 0 ? null : <button type="button" class="weave-trail-replay" title="Replay this turn's glow" onClick={() => props.onReplay(shown.turn)}>Replay</button>}
|
|
31
30
|
</h4>
|
|
32
31
|
{shown.steps.length === 0 ? <p class="weave-trail-empty">{TRAIL_EMPTY_TURN}</p> : null}
|
|
33
32
|
<ol class="weave-trail-steps">
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* steps one after another from the moment it was clicked.
|
|
10
10
|
* - {@link trailTurns}: the "This turn" strip — each turn's steps in order,
|
|
11
11
|
* worded as `searched "auth" → read Auth migration → appended Auth migration`.
|
|
12
|
+
* - {@link agentSearch}: the agent's newest search this turn, which the
|
|
13
|
+
* graph view lights up in its spotlight ({@link agentSpotlight}).
|
|
12
14
|
*
|
|
13
15
|
* Pure, DOM-free and clock-free (every function takes `now`), like the other
|
|
14
16
|
* `*.model.ts` files, so the whole feature is covered by unit tests.
|
|
@@ -179,17 +181,70 @@ export function trailTurns(trail: TrailPayload | null, graph: GraphPayload | nul
|
|
|
179
181
|
return views.slice(0, TRAIL_TURNS_SHOWN);
|
|
180
182
|
}
|
|
181
183
|
|
|
182
|
-
/** The strip's heading for a turn: the latest is "This turn", older ones are their time. */
|
|
183
184
|
/** What the strip says for a turn with no steps yet. */
|
|
184
185
|
export const TRAIL_EMPTY_TURN = "Nothing recalled yet.";
|
|
185
186
|
|
|
187
|
+
/** The strip's heading for a turn: the latest is "This turn", older ones are their time. */
|
|
186
188
|
export function turnHeading(view: TrailTurnView, latest: boolean): string {
|
|
187
189
|
return latest ? "This turn" : view.time === "" ? `Turn ${view.turn}` : view.time;
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
// --- the agent's search in the graph view's spotlight ----------------------------------
|
|
193
|
+
|
|
194
|
+
/** The agent's newest search this turn: what the graph view's spotlight lights. */
|
|
195
|
+
export interface AgentSearch {
|
|
196
|
+
/** The event's `seq`, so a new search is a new number even for the same words. */
|
|
197
|
+
seq: number;
|
|
198
|
+
query: string;
|
|
199
|
+
/** The notes the search returned, as node ids. */
|
|
200
|
+
ids: readonly string[];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* The agent's newest search in the current turn, or `null`.
|
|
205
|
+
*
|
|
206
|
+
* Only the current turn counts, so the spotlight a search lit goes out when
|
|
207
|
+
* the agent moves on to the next request. A search with no words (the wire
|
|
208
|
+
* allows one) has nothing to spell in the field and is skipped.
|
|
209
|
+
*/
|
|
210
|
+
export function agentSearch(trail: TrailPayload | null): AgentSearch | null {
|
|
211
|
+
if (trail === null) return null;
|
|
212
|
+
for (let index = trail.events.length - 1; index >= 0; index--) {
|
|
213
|
+
const event = trail.events[index]!;
|
|
214
|
+
if (event.turn !== trail.turn) return null;
|
|
215
|
+
if (event.kind !== "searched" || event.query === undefined || event.query.trim() === "") continue;
|
|
216
|
+
return { seq: event.seq, query: event.query, ids: event.slugs.map((slug) => `note:${slug}`) };
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** What the spotlight becomes: its query, the ids lit alongside, and the agent search that set it (`null`: the person's). */
|
|
222
|
+
export interface AgentSpotlight {
|
|
223
|
+
query: string;
|
|
224
|
+
ids: readonly string[];
|
|
225
|
+
agent: number | null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* How the graph view's spotlight follows the agent's searches, when
|
|
230
|
+
* {@link agentSearch} changes. `null` leaves the spotlight alone.
|
|
231
|
+
*
|
|
232
|
+
* A new search takes the spotlight over, the way the palette's "light up in
|
|
233
|
+
* graph" does, unless the person is in the middle of a query of their own:
|
|
234
|
+
* the field focused with words they typed. A focused field that is empty, or
|
|
235
|
+
* still shows an earlier agent search, is not theirs and follows along, so a
|
|
236
|
+
* field left focused never swallows a search. When the turn that searched is
|
|
237
|
+
* over, the spotlight it lit goes out, unless the person has made it theirs
|
|
238
|
+
* since by typing or lighting something up.
|
|
239
|
+
*/
|
|
240
|
+
export function agentSpotlight(
|
|
241
|
+
/** The `seq` of the agent search the spotlight shows now, or `null` when it is the person's (or empty). */
|
|
242
|
+
shown: number | null,
|
|
243
|
+
search: AgentSearch | null,
|
|
244
|
+
/** Whether the field has focus and holds words; `shown` says whose words they are. */
|
|
245
|
+
composing: boolean,
|
|
246
|
+
): AgentSpotlight | null {
|
|
247
|
+
if (search === null) return shown === null ? null : { query: "", ids: [], agent: null };
|
|
248
|
+
if (search.seq === shown || (composing && shown === null)) return null;
|
|
249
|
+
return { query: search.query, ids: search.ids, agent: search.seq };
|
|
195
250
|
}
|