@workerdeck/ui 2.7.2 → 2.9.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.
Files changed (71) hide show
  1. package/README.md +30 -30
  2. package/build/{SessionPanel-B5FfiBxE.mjs → SessionPanel-BClL7zUS.mjs} +694 -413
  3. package/build/SessionPanel-BClL7zUS.mjs.map +1 -0
  4. package/build/{SessionPanel-_lQLhWOw.d.mts → SessionPanel-BVbau2eR.d.mts} +68 -4
  5. package/build/format.mjs +1 -1
  6. package/build/index.d.mts +22 -15
  7. package/build/index.mjs +6 -6
  8. package/build/index.mjs.map +1 -1
  9. package/build/scoped.css +26 -2
  10. package/build/{status-BO9wJloK.mjs → status-kmsBhuFG.mjs} +3 -3
  11. package/build/status-kmsBhuFG.mjs.map +1 -0
  12. package/build/workspace.d.mts +3 -2
  13. package/build/workspace.mjs +7 -8
  14. package/build/workspace.mjs.map +1 -1
  15. package/package.json +18 -18
  16. package/src/components/agent/Composer.tsx +86 -84
  17. package/src/components/agent/ContextDialog.tsx +1 -1
  18. package/src/components/agent/EntryIcon.tsx +1 -1
  19. package/src/components/agent/FileTree.tsx +1 -1
  20. package/src/components/agent/FileViewer.tsx +1 -1
  21. package/src/components/agent/HostFilesDialog.tsx +2 -2
  22. package/src/components/agent/PermissionModeSelect.tsx +2 -2
  23. package/src/components/agent/PermissionPrompt.tsx +2 -2
  24. package/src/components/agent/SessionBrowser.tsx +1 -1
  25. package/src/components/agent/SessionItem.tsx +4 -2
  26. package/src/components/agent/SessionPanel.tsx +306 -226
  27. package/src/components/agent/SessionWorkspace.tsx +3 -0
  28. package/src/components/agent/SkillsDialog.tsx +3 -3
  29. package/src/components/agent/StatusBar.tsx +1 -1
  30. package/src/components/agent/TaskList.tsx +2 -2
  31. package/src/components/agent/TranscriptRows.tsx +1 -1
  32. package/src/components/agent/UsageDialog.tsx +1 -1
  33. package/src/components/agent/UsageMeters.tsx +17 -4
  34. package/src/components/agent/composer-commands.ts +142 -0
  35. package/src/components/agent/use-path-links.ts +2 -7
  36. package/src/components/agent/use-subagent-frame.ts +2 -2
  37. package/src/components/agent/use-transcript-jumps.ts +2 -2
  38. package/src/components/prompt-area/clipboard-helpers.ts +2 -2
  39. package/src/components/prompt-area/cursor-helpers.ts +7 -7
  40. package/src/components/prompt-area/dom-helpers.ts +8 -8
  41. package/src/components/prompt-area/html-to-markdown.ts +2 -2
  42. package/src/components/prompt-area/prompt-area-engine.ts +4 -4
  43. package/src/components/prompt-area/prompt-area-list-ops.ts +10 -10
  44. package/src/components/prompt-area/prompt-area.tsx +2 -2
  45. package/src/components/prompt-area/trigger-presets.ts +6 -6
  46. package/src/components/prompt-area/types.ts +6 -6
  47. package/src/components/prompt-area/use-chip-editing.ts +8 -8
  48. package/src/components/prompt-area/use-markdown-mode.ts +3 -3
  49. package/src/components/prompt-area/use-prompt-area-events.ts +3 -3
  50. package/src/components/prompt-area/use-prompt-area-keydown.ts +3 -3
  51. package/src/components/prompt-area/use-prompt-area-state.ts +4 -4
  52. package/src/components/prompt-area/use-prompt-area.ts +5 -5
  53. package/src/components/prompt-area/use-trigger-search.ts +1 -1
  54. package/src/components/terminal/PermissionPrompt.tsx +4 -4
  55. package/src/components/terminal/affordances.tsx +1 -1
  56. package/src/components/terminal/file-link.tsx +20 -0
  57. package/src/components/terminal/height.ts +2 -2
  58. package/src/components/terminal/items.tsx +2 -2
  59. package/src/components/terminal/markdown.tsx +31 -5
  60. package/src/components/terminal/scrubber.tsx +1 -1
  61. package/src/components/terminal/todos.ts +1 -1
  62. package/src/components/ui/Splitter.tsx +1 -1
  63. package/src/index.ts +11 -1
  64. package/src/lib/context-note.ts +3 -3
  65. package/src/lib/file-link.ts +70 -0
  66. package/src/lib/format.ts +2 -2
  67. package/src/styles/scoped.entry.css +2 -2
  68. package/src/styles/terminal.css +94 -79
  69. package/src/styles/theme.css +39 -39
  70. package/build/SessionPanel-B5FfiBxE.mjs.map +0 -1
  71. package/build/status-BO9wJloK.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /*
2
- * @workerdeck/ui theme — design tokens + Tailwind v4 theme mapping.
2
+ * @workerdeck/ui theme - design tokens + Tailwind v4 theme mapping.
3
3
  *
4
4
  * Consumer wiring (the app's tailwind entry CSS):
5
5
  *
@@ -7,7 +7,7 @@
7
7
  * @import '@workerdeck/ui/theme.css';
8
8
  * @source '../node_modules/@workerdeck/ui'; (or the package src path in a monorepo)
9
9
  *
10
- * Do NOT import tailwindcss here — the consumer owns that. Theme switching is driven by
10
+ * Do NOT import tailwindcss here - the consumer owns that. Theme switching is driven by
11
11
  * <html data-theme="light|dark"> (set it before first paint to avoid a flash).
12
12
  *
13
13
  * Two tiers: a raw palette swapped by [data-theme], then `@theme inline` mapping raw
@@ -15,7 +15,7 @@
15
15
  * data-theme re-themes with zero JS).
16
16
  */
17
17
 
18
- /* The terminal theme's geometry and palette — see the file's own header. Its
18
+ /* The terminal theme's geometry and palette - see the file's own header. Its
19
19
  * tokens are deliberately independent of the app palette below: a terminal
20
20
  * looks like a terminal wherever it is embedded. First, because `@import` is
21
21
  * only valid ahead of rules. */
@@ -37,8 +37,8 @@
37
37
  survive an unknown host surface, and it bought that at the cost of a hover
38
38
  that read differently on every one of them; the design draws one hover, so
39
39
  this is one colour. The hazard the alpha was guarding against is real and
40
- has a name — `--bg-surface-hover` on the dark sidebar landed one step of
41
- 255 from the sidebar itself, so the state did not exist — and the guard
40
+ has a name - `--bg-surface-hover` on the dark sidebar landed one step of
41
+ 255 from the sidebar itself, so the state did not exist - and the guard
42
42
  against it now is that both flat values are picked against the sidebar
43
43
  fills we actually ship (`--sidebar`), and that the extension repoints all
44
44
  three at `--vscode-list-*` rather than inheriting them.
@@ -51,13 +51,13 @@
51
51
  shape the design gives selection there. Light is a tint carrying dark text;
52
52
  dark is VS Code's `list.activeSelectionBackground` carrying light text.
53
53
 
54
- `--row-selected-weak` is the **secondary** selection — "this card holds what
54
+ `--row-selected-weak` is the **secondary** selection - "this card holds what
55
55
  you are looking at, but the thing you are looking at is one row inside it".
56
56
  It exists because a session card and its sub-agents are two selections at
57
57
  two grains, and the blue can only mean one of them: when a sub-agent is
58
58
  open, the blue belongs to that step and the card drops to this. It is VS
59
59
  Code's `list.inactiveSelectionBackground`, which is the same idea one
60
- surface over — selected, but not the thing with focus. Distinct from
60
+ surface over - selected, but not the thing with focus. Distinct from
61
61
  `--row-hover` on purpose: a card that answered the pointer and a card
62
62
  holding the open agent are different claims, and a list that painted them
63
63
  the same colour would be lying about one of them. */
@@ -92,7 +92,7 @@
92
92
  * This is the one place a brand colour is allowed in the product, and it earns
93
93
  * it by doing a job nothing else on the row does: the list already spends blue
94
94
  * on running, amber on waiting, red on failed and muted on idle, so none of
95
- * those can also say *whose engine this is* — and the mark alone is a 12px
95
+ * those can also say *whose engine this is* - and the mark alone is a 12px
96
96
  * silhouette.
97
97
  *
98
98
  * Two values per vendor, because that glyph has to hold against both grounds:
@@ -100,7 +100,7 @@
100
100
  *
101
101
  * **OpenAI's is monochrome, and that is their rule rather than our taste**:
102
102
  * their guidelines forbid adding colour to the mark, so it is pure white on
103
- * dark and a near-black on light — both sanctioned, and the only kind of pair
103
+ * dark and a near-black on light - both sanctioned, and the only kind of pair
104
104
  * legible on both grounds. A green was tried first and is wrong, however well
105
105
  * it reads. Near-black rather than `#000` because pure black would sit *harder*
106
106
  * than the session title above it, so the mark would out-weigh the name it is
@@ -109,7 +109,7 @@
109
109
  * That makes the two vendors asymmetric, which is the honest outcome: coral is
110
110
  * Anthropic's brand and monochrome is OpenAI's, so a rule that gave both an
111
111
  * accent would misrepresent one of them. It also means OpenAI's token is at
112
- * full contrast, which is why only the **mark** wears it — see
112
+ * full contrast, which is why only the **mark** wears it - see
113
113
  * `vendorTextClass` in `EngineIcon.tsx`.
114
114
  *
115
115
  * A third vendor is two declarations here and one map entry there. */
@@ -117,13 +117,13 @@
117
117
  --vendor-openai: #373737;
118
118
 
119
119
  /* ---------- Accent ----------
120
- * VS Code blue (`#0078d4`) — the product's primary. It is the *same* hue in
120
+ * VS Code blue (`#0078d4`) - the product's primary. It is the *same* hue in
121
121
  * both themes rather than the inverse of the canvas: a primary that flips
122
122
  * from near-black to near-white is a contrast device, not a brand colour, and
123
123
  * WorkerDeck now shares an editor's visual language.
124
124
  *
125
125
  * Not to be confused with the brand's live green (`docs/assets/BRAND.md`),
126
- * which stays what it is — a *signal*, not a primary. */
126
+ * which stays what it is - a *signal*, not a primary. */
127
127
  --accent: #0078d4;
128
128
  --accent-hover: #106ebe;
129
129
  --accent-dim: #6ca9d8;
@@ -151,7 +151,7 @@
151
151
  --shine: #dcdcdc;
152
152
  --frame-shadow: var(--shadow-xs);
153
153
 
154
- /* The overview rail's bookmark magenta — the app palette has no magenta,
154
+ /* The overview rail's bookmark magenta - the app palette has no magenta,
155
155
  and every other colour on the rail is already spoken for. */
156
156
  --wd-scrub-bookmark: #8b3a8b;
157
157
 
@@ -167,7 +167,7 @@
167
167
  --accent-tint: var(--accent-bg);
168
168
  --accent-fg: #ffffff;
169
169
  --warn: var(--warning);
170
- /* Focus ring is the accent, as in an editor — the comment below already said
170
+ /* Focus ring is the accent, as in an editor - the comment below already said
171
171
  * "accent-derived"; before the blue it was indistinguishable from fg-1. */
172
172
  --ring: var(--accent);
173
173
  }
@@ -210,7 +210,7 @@
210
210
 
211
211
  /* ---------- Accent ----------
212
212
  * The same blue as light. `--accent` stays `#0078d4` because it is a *fill*
213
- * carrying white text (4.6:1) — the brighter `#3794ff` would drop that to
213
+ * carrying white text (4.6:1) - the brighter `#3794ff` would drop that to
214
214
  * 2.9:1. The bright one is the hover and the ring, where nothing sits on top
215
215
  * of it and the extra lift is what a dark canvas needs. */
216
216
  --accent: #0078d4;
@@ -240,7 +240,7 @@
240
240
  --shine: #303030;
241
241
  --frame-shadow: 0 4px 24px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.45);
242
242
 
243
- /* See the light block — lifted for the dark ground. */
243
+ /* See the light block - lifted for the dark ground. */
244
244
  --wd-scrub-bookmark: #c586c0;
245
245
  --wd-shell-accent: #c586c0;
246
246
 
@@ -250,15 +250,15 @@
250
250
  --text: var(--fg-1);
251
251
  --text-muted: var(--fg-3);
252
252
  --accent-tint: var(--accent-bg);
253
- /* White on the blue fill in both themes — the accent no longer inverts. */
253
+ /* White on the blue fill in both themes - the accent no longer inverts. */
254
254
  --accent-fg: #ffffff;
255
255
  --warn: var(--warning);
256
- /* Focus ring is the accent, as in an editor — the comment below already said
256
+ /* Focus ring is the accent, as in an editor - the comment below already said
257
257
  * "accent-derived"; before the blue it was indistinguishable from fg-1. */
258
258
  --ring: var(--accent);
259
259
  }
260
260
 
261
- /* Theme-independent tokens — type tracking, easing, fonts.
261
+ /* Theme-independent tokens - type tracking, easing, fonts.
262
262
  * Hosts get real fonts by importing @fontsource/inter + @fontsource/jetbrains-mono;
263
263
  * the stacks below degrade gracefully without them. */
264
264
  :root {
@@ -303,7 +303,7 @@
303
303
  * transcript and its composer render monospace and read as part of the terminal
304
304
  * rather than as a web app beside one. The mono token itself is left alone: code
305
305
  * was already mono, and pointing both at the same stack is what makes the two
306
- * indistinguishable — which is the point.
306
+ * indistinguishable - which is the point.
307
307
  *
308
308
  * A subtree rule rather than `:root`, and deliberately: this is the *agent
309
309
  * panel's* preference, not the app's. A host's sidebar, dialogs and lists keep
@@ -314,7 +314,7 @@
314
314
  [data-agent-font='mono'] {
315
315
  --cw-font-sans: var(--cw-font-mono);
316
316
  /* Tailwind's `font-sans` utility reads `--font-sans`, whose `:root` value is
317
- `var(--cw-font-sans)` — and a `var()` inside a custom property is resolved
317
+ `var(--cw-font-sans)` - and a `var()` inside a custom property is resolved
318
318
  against the element that DECLARED it, not the one that inherits it. So
319
319
  repointing `--cw-font-sans` here leaves `--font-sans` still holding the sans
320
320
  stack it computed at `:root`. Both have to move. */
@@ -324,7 +324,7 @@
324
324
  and every descendant inherits that *resolved* stack. Nothing under here
325
325
  re-reads the token, so the subtree has to be told directly.
326
326
  (VS Code's webview gets away with tokens alone only because its override
327
- sits on `html` — the same element `:root` declares them on.) */
327
+ sits on `html` - the same element `:root` declares them on.) */
328
328
  font-family: var(--cw-font-mono);
329
329
  }
330
330
 
@@ -356,7 +356,7 @@
356
356
  --color-badge-fg: var(--badge-fg);
357
357
  /* Named code-bg (not code) so it can't shadow the --text-code font-size token:
358
358
  with a --color-code defined, `text-code` would resolve to the color namespace
359
- and paint text in the code *background* color — invisible in both themes. */
359
+ and paint text in the code *background* color - invisible in both themes. */
360
360
  --color-code-bg: var(--bg-code);
361
361
  --color-border-light: var(--border-light);
362
362
  --color-border-strong: var(--border-strong);
@@ -395,7 +395,7 @@
395
395
  --font-sans: var(--cw-font-sans);
396
396
  --font-mono: var(--cw-font-mono);
397
397
 
398
- /* Type scale — size + line-height. Display sizes carry tight tracking. */
398
+ /* Type scale - size + line-height. Display sizes carry tight tracking. */
399
399
  --text-display-xl: 2.5rem;
400
400
  --text-display-xl--line-height: 3rem;
401
401
  --text-display-xl--letter-spacing: -0.02em;
@@ -421,7 +421,7 @@
421
421
  --text-label: 0.75rem;
422
422
  --text-label--line-height: 1rem;
423
423
  --text-label--letter-spacing: 0.02em;
424
- /* 11px. The step rows under a session card, and nothing else yet — a size
424
+ /* 11px. The step rows under a session card, and nothing else yet - a size
425
425
  below `label` exists so a list *inside* a row can be visibly subordinate to
426
426
  it without dropping to a weight nobody can read. Tracking goes NEGATIVE
427
427
  here where `label` goes positive: `label` is a small-caps-ish UI word that
@@ -432,7 +432,7 @@
432
432
  --text-code: 0.84375rem;
433
433
  --text-code--line-height: 1.375rem;
434
434
 
435
- /* Radii — 6px is the workhorse. */
435
+ /* Radii - 6px is the workhorse. */
436
436
  --radius-sm: 4px;
437
437
  --radius-md: 6px;
438
438
  --radius-lg: 8px;
@@ -494,8 +494,8 @@
494
494
  * (utilities live in a layer; unlayered rules always win over layered ones).
495
495
  *
496
496
  * `--wd-font-size` is set on the session panel root by the `fontSize` prop.
497
- * When present it drives all text in the cards variant — body text, headings,
498
- * code, tables — through one value. When absent the fallback `var(--text-body-sm)`
497
+ * When present it drives all text in the cards variant - body text, headings,
498
+ * code, tables - through one value. When absent the fallback `var(--text-body-sm)`
499
499
  * resolves to the same `0.8125rem` the utility class used to set.
500
500
  *
501
501
  * Streamdown ships `rem`-based heading sizes (text-3xl … text-sm) that resolve
@@ -504,7 +504,7 @@
504
504
  * cards-mode assistant output; the terminal theme renders headings as weight-only
505
505
  * (no size change) through its own components and is unaffected.
506
506
  *
507
- * The heading scale mirrors Streamdown's hierarchy but at a tighter range — its
507
+ * The heading scale mirrors Streamdown's hierarchy but at a tighter range - its
508
508
  * 30 → 14 px span (h1 → h6) sits inside a 13px body, so the ratio is condensed:
509
509
  * h1 at 1.5em, descending to h6 at 1em.
510
510
  */
@@ -552,7 +552,7 @@
552
552
  font-size: inherit;
553
553
  }
554
554
  /* Table, cells, and headers: Streamdown puts `text-sm` (rem) on td/th directly,
555
- so overriding the table alone is not enough — the cell class wins. */
555
+ so overriding the table alone is not enough - the cell class wins. */
556
556
  [data-slot='message-content'] table {
557
557
  font-size: 0.95em;
558
558
  }
@@ -636,15 +636,15 @@
636
636
  * The replay hold's placeholder, revealed only if the wait is long enough to be
637
637
  * worth mentioning.
638
638
  *
639
- * The hold hides the transcript while the attach replay lands — typically ~0.5s
640
- * — and an unconditional "Loading…" line inside it is *worse than nothing*: it
639
+ * The hold hides the transcript while the attach replay lands - typically ~0.5s
640
+ * - and an unconditional "Loading…" line inside it is *worse than nothing*: it
641
641
  * appears and vanishes within half a second, so the flicker the hold exists to
642
642
  * remove comes straight back as a blinking line at the top of the panel. The
643
643
  * hold is the fix; announcing it is the regression.
644
644
  *
645
645
  * So the placeholder starts transparent and fades in only after a delay longer
646
- * than a healthy attach takes. A normal open paints it **never** — the element
647
- * unmounts while still at `opacity: 0` — and only a genuinely slow attach (a
646
+ * than a healthy attach takes. A normal open paints it **never** - the element
647
+ * unmounts while still at `opacity: 0` - and only a genuinely slow attach (a
648
648
  * cold gateway, a huge log) ever shows a line, which is exactly when a reader
649
649
  * needs to be told something is happening rather than assume the panel is dead.
650
650
  *
@@ -725,9 +725,9 @@
725
725
  *
726
726
  * The same lane/head/sentinel mechanism as the terminal theme's pinned prompt
727
727
  * (terminal.css scopes its rules under `[data-terminal]`; these key on the
728
- * lane's own `data-sticky-lane='cards'` value) — but the head's CONTENT is
728
+ * lane's own `data-sticky-lane='cards'` value) - but the head's CONTENT is
729
729
  * different in kind, and that is the whole design. The terminal head is the
730
- * row rendered again, clipped to one line — exact, because that theme is a
730
+ * row rendered again, clipped to one line - exact, because that theme is a
731
731
  * monospace grid. A proportional message card clipped by height is a sliced
732
732
  * bubble, so the cards head never renders the Message component at all:
733
733
  * `StickyPromptLane` (Transcript.tsx) hands it the prompt as one run of plain
@@ -738,7 +738,7 @@
738
738
  * ConversationContent's centred, padded column (`max-w` + `mx-auto` + `px-4`)
739
739
  * and spans it edge to edge, so the bar's text starts on the same left edge
740
740
  * as the response paragraphs and the ellipsis lands on the column's right
741
- * edge — no max-width or inline padding repeated here. The bar carries no
741
+ * edge - no max-width or inline padding repeated here. The bar carries no
742
742
  * gap class either (the measured row keeps it): it is not an overlay of the
743
743
  * row's first line, so it has no in-flow y to match, and the 1st prompt (no
744
744
  * gap) and every later one (pt-4/pt-2) share these rules unchanged. */
@@ -747,7 +747,7 @@
747
747
  pointer-events: none;
748
748
  }
749
749
 
750
- /* The head's own strip: the full lane, out of flow — see terminal.css for why
750
+ /* The head's own strip: the full lane, out of flow - see terminal.css for why
751
751
  sticky confinement wants the border box, not a cancelled margin box. */
752
752
  [data-sticky-lane='cards'] > [data-sticky-headlane] {
753
753
  position: absolute;
@@ -785,7 +785,7 @@
785
785
  /* ── Overview scrubber (cards variant) ──────────────────────────────────────
786
786
  *
787
787
  * The proportional rail (`components/agent/Scrubber.tsx`): same geometry as the
788
- * terminal rail — 12px, two 6px lanes plus full width — and the same palette
788
+ * terminal rail - 12px, two 6px lanes plus full width - and the same palette
789
789
  * mapped onto the app tokens. It is an annotation rail, never a scrollbar: the
790
790
  * container takes no pointer events, so the native scrollbar keeps working
791
791
  * straight through the paint. */