@workerdeck/ui 0.21.0 → 0.22.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 (37) hide show
  1. package/README.md +3 -2
  2. package/build/{SessionPanel-BjNAnWMF.d.mts → SessionPanel-13l25ubU.d.mts} +15 -5
  3. package/build/{SessionPanel-DNuPKg5c.mjs → SessionPanel-DgwjH4Ve.mjs} +624 -221
  4. package/build/SessionPanel-DgwjH4Ve.mjs.map +1 -0
  5. package/build/index.d.mts +54 -21
  6. package/build/index.mjs +7 -6
  7. package/build/index.mjs.map +1 -1
  8. package/build/scoped.css +3547 -0
  9. package/build/workspace.d.mts +1 -1
  10. package/build/workspace.mjs +1 -1
  11. package/package.json +10 -6
  12. package/src/components/agent/Composer.tsx +10 -10
  13. package/src/components/agent/ContextDialog.tsx +3 -2
  14. package/src/components/agent/Conversation.tsx +1 -1
  15. package/src/components/agent/McpDialog.tsx +3 -1
  16. package/src/components/agent/Scrubber.tsx +248 -0
  17. package/src/components/agent/SessionList.tsx +3 -1
  18. package/src/components/agent/SessionPanel.tsx +20 -7
  19. package/src/components/agent/SessionSteps.tsx +10 -4
  20. package/src/components/agent/SkillsDialog.tsx +3 -2
  21. package/src/components/agent/StatusBar.tsx +1 -1
  22. package/src/components/agent/Transcript.tsx +147 -73
  23. package/src/components/agent/UsageDialog.tsx +3 -1
  24. package/src/components/agent/scrubber-marks.ts +277 -0
  25. package/src/components/terminal/PermissionPrompt.tsx +3 -0
  26. package/src/components/terminal/QuestionPrompt.tsx +3 -0
  27. package/src/components/terminal/StatusLine.tsx +3 -1
  28. package/src/components/ui/AlertDialog.tsx +23 -20
  29. package/src/components/ui/Dialog.tsx +26 -23
  30. package/src/components/ui/Menu.tsx +20 -17
  31. package/src/components/ui/PortalScope.tsx +27 -0
  32. package/src/components/ui/Select.tsx +19 -16
  33. package/src/components/ui/Tooltip.tsx +13 -10
  34. package/src/styles/scoped.entry.css +16 -0
  35. package/src/styles/terminal.css +1 -1
  36. package/src/styles/theme.css +160 -0
  37. package/build/SessionPanel-DNuPKg5c.mjs.map +0 -1
package/build/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-ljc3lKpA.mjs";
2
- import { C as permissionModeChoices, S as PermissionModeSelectProps, _ as useAffordances, a as SessionVitals, b as PermissionModeMeta, c as TranscriptDensityProvider, d as TranscriptVariantProvider, f as useTranscriptDensity, g as WithActions, h as TerminalAffordances, i as SessionSurfacePanel, l as TranscriptFont, m as CopyAction, n as SessionPanel, o as TerminalMetrics, p as useTranscriptVariant, r as SessionPanelProps, s as TranscriptDensity, t as SessionControls, u as TranscriptVariant, v as PERMISSION_MODES, w as permissionModeMeta, x as PermissionModeSelect, y as PermissionModeChoice } from "./SessionPanel-BjNAnWMF.mjs";
2
+ import { C as permissionModeChoices, S as PermissionModeSelectProps, _ as useAffordances, a as SessionVitals, b as PermissionModeMeta, c as TranscriptDensityProvider, d as TranscriptVariantProvider, f as useTranscriptDensity, g as WithActions, h as TerminalAffordances, i as SessionSurfacePanel, l as TranscriptFont, m as CopyAction, n as SessionPanel, o as TerminalMetrics, p as useTranscriptVariant, r as SessionPanelProps, s as TranscriptDensity, t as SessionControls, u as TranscriptVariant, v as PERMISSION_MODES, w as permissionModeMeta, x as PermissionModeSelect, y as PermissionModeChoice } from "./SessionPanel-13l25ubU.mjs";
3
3
  import * as _$react from "react";
4
4
  import { ButtonHTMLAttributes, FunctionComponent, HTMLAttributes, InputHTMLAttributes, ReactElement, ReactNode, Ref, RefObject, TextareaHTMLAttributes } from "react";
5
5
  import { VariantProps } from "class-variance-authority";
@@ -883,17 +883,21 @@ interface TranscriptProps {
883
883
  /** Terminal theme only: the pointer affordances a real terminal cannot offer.
884
884
  * `false` for none. See {@link TerminalAffordances}. */
885
885
  affordances?: TerminalAffordances | boolean;
886
- /** Terminal theme only: hold the prompt of the turn being read at the top of
887
- * the scroller. The *real* row is pinned, not a copy see `TranscriptRows`. */
886
+ /** Hold the prompt of the turn being read at the top of the scroller. Works
887
+ * in both variants: the terminal clips to one line, cards shows a frosted
888
+ * bar. The *real* row is pinned, not a copy — see `TranscriptRows`. */
888
889
  stickyPrompt?: boolean;
889
890
  /**
890
- * Terminal theme only: mount the overview-ruler scrubber — a 2ch rail of
891
- * marks (your prompts, each turn's response and result as one mark, errors,
892
- * the pending approval, the catch-up boundary) that replaces the native
893
- * scrollbar. Ignored under `cards`: the rail's positions ride the height
894
- * calculator, which has no claim there. With `affordances={false}` the rail
895
- * degrades to passive paint no drag, peek or click and the native
896
- * scrollbar stays. See {@link TerminalScrubber}.
891
+ * Mount the overview scrubber — a 12px rail of marks (your prompts, each
892
+ * turn's response and result as one mark, errors, the pending approval, the
893
+ * catch-up boundary) over the scroller's right edge. Two rails behind one
894
+ * prop: under `terminal` it is the pixel-exact ruler that replaces the
895
+ * native scrollbar (positions ride the height calculator; drag scrubs), and
896
+ * under `cards` it is the **proportional annotation rail**positioned by
897
+ * `itemIndex / items.length`, because proportional text gives the
898
+ * calculator no claim there — where the native scrollbar stays and the rail
899
+ * only peeks and jumps. With `affordances={false}` either rail degrades to
900
+ * passive paint — no drag, peek or click.
897
901
  */
898
902
  scrubber?: boolean;
899
903
  /**
@@ -989,6 +993,12 @@ interface TranscriptProps {
989
993
  * sessions list instead.
990
994
  */
991
995
  onOpenSubagent?: (toolUseId: string) => void;
996
+ /**
997
+ * Replaces the default empty state when the transcript has no items. Pass a
998
+ * `ReactNode` to show your product's own onboarding instead of WorkerDeck's
999
+ * generic "`>_` Tell the agent what to do." placeholder.
1000
+ */
1001
+ emptyState?: ReactNode;
992
1002
  className?: string;
993
1003
  }
994
1004
  declare function Transcript({
@@ -1012,6 +1022,7 @@ declare function Transcript({
1012
1022
  reveal,
1013
1023
  frame,
1014
1024
  onOpenSubagent,
1025
+ emptyState,
1015
1026
  className
1016
1027
  }: TranscriptProps): _$react.JSX.Element;
1017
1028
  //#endregion
@@ -1115,6 +1126,7 @@ declare function TerminalTranscript({
1115
1126
  //#endregion
1116
1127
  //#region src/components/terminal/StatusLine.d.ts
1117
1128
  interface TerminalStatusLineProps {
1129
+ className?: string;
1118
1130
  state: TranscriptState;
1119
1131
  /** Plan windows to read from, when they should not be the session's own — the
1120
1132
  * gateway's per-profile state merged over this transcript's. See
@@ -1130,6 +1142,7 @@ interface TerminalStatusLineProps {
1130
1142
  onOpenUsage?: () => void;
1131
1143
  }
1132
1144
  declare function TerminalStatusLine({
1145
+ className,
1133
1146
  state,
1134
1147
  rateLimits,
1135
1148
  connection,
@@ -1161,11 +1174,13 @@ interface TerminalPermissionPromptProps {
1161
1174
  /** `message` is fed back to the agent, which can then try something else;
1162
1175
  * `interrupt` also stops the turn. */
1163
1176
  onDeny: (requestId: string, message?: string, interrupt?: boolean) => void;
1177
+ className?: string;
1164
1178
  }
1165
1179
  declare function TerminalPermissionPrompt({
1166
1180
  request,
1167
1181
  onApprove,
1168
- onDeny
1182
+ onDeny,
1183
+ className
1169
1184
  }: TerminalPermissionPromptProps): _$react.JSX.Element;
1170
1185
  //#endregion
1171
1186
  //#region src/components/terminal/QuestionPrompt.d.ts
@@ -1176,11 +1191,13 @@ interface TerminalQuestionPromptProps {
1176
1191
  onAnswer: (requestId: string, updatedInput: Record<string, unknown>) => void;
1177
1192
  /** Deny the tool — the model proceeds without an answer. */
1178
1193
  onDismiss: (requestId: string, message?: string) => void;
1194
+ className?: string;
1179
1195
  }
1180
1196
  declare function TerminalQuestionPrompt({
1181
1197
  request,
1182
1198
  onAnswer,
1183
- onDismiss
1199
+ onDismiss,
1200
+ className
1184
1201
  }: TerminalQuestionPromptProps): _$react.JSX.Element;
1185
1202
  //#endregion
1186
1203
  //#region src/components/terminal/diff.d.ts
@@ -1641,6 +1658,7 @@ interface ContextDialogProps {
1641
1658
  usage?: ContextUsage;
1642
1659
  open: boolean;
1643
1660
  onOpenChange: (open: boolean) => void;
1661
+ className?: string;
1644
1662
  }
1645
1663
  /**
1646
1664
  * What is in the model's context window right now, category by category.
@@ -1652,7 +1670,8 @@ interface ContextDialogProps {
1652
1670
  declare function ContextDialog({
1653
1671
  usage,
1654
1672
  open,
1655
- onOpenChange
1673
+ onOpenChange,
1674
+ className
1656
1675
  }: ContextDialogProps): _$react.JSX.Element;
1657
1676
  //#endregion
1658
1677
  //#region src/components/agent/UsageDialog.d.ts
@@ -1678,6 +1697,7 @@ interface UsageDialogProps {
1678
1697
  updatedAt?: number;
1679
1698
  open: boolean;
1680
1699
  onOpenChange: (open: boolean) => void;
1700
+ className?: string;
1681
1701
  }
1682
1702
  /**
1683
1703
  * The session's view of the plan: every window as a meter (see
@@ -1690,7 +1710,8 @@ declare function UsageDialog({
1690
1710
  totalCostUsd,
1691
1711
  updatedAt,
1692
1712
  open,
1693
- onOpenChange
1713
+ onOpenChange,
1714
+ className
1694
1715
  }: UsageDialogProps): _$react.JSX.Element;
1695
1716
  //#endregion
1696
1717
  //#region src/components/agent/UsageMeters.d.ts
@@ -1768,6 +1789,7 @@ interface McpDialogProps {
1768
1789
  * that 501 are worse than buttons that aren't there.
1769
1790
  */
1770
1791
  canManageServers?: boolean;
1792
+ className?: string;
1771
1793
  }
1772
1794
  /**
1773
1795
  * The session's MCP servers, at the CLI's own `/mcp` depth: servers → one server
@@ -1786,7 +1808,8 @@ declare function McpDialog({
1786
1808
  sessionId,
1787
1809
  open,
1788
1810
  onOpenChange,
1789
- canManageServers
1811
+ canManageServers,
1812
+ className
1790
1813
  }: McpDialogProps): _$react.JSX.Element;
1791
1814
  //#endregion
1792
1815
  //#region src/components/agent/SkillsDialog.d.ts
@@ -1797,6 +1820,7 @@ interface SkillsDialogProps {
1797
1820
  /** Insert a skill's opening message into the composer, if the host offers
1798
1821
  * that. Omit and the dialog is read-only. */
1799
1822
  onUse?: (skill: SkillInfo) => void;
1823
+ className?: string;
1800
1824
  }
1801
1825
  /**
1802
1826
  * What this session's engine can do beyond its own tools: the skills it found,
@@ -1815,7 +1839,8 @@ declare function SkillsDialog({
1815
1839
  skills,
1816
1840
  open,
1817
1841
  onOpenChange,
1818
- onUse
1842
+ onUse,
1843
+ className
1819
1844
  }: SkillsDialogProps): _$react.JSX.Element;
1820
1845
  //#endregion
1821
1846
  //#region src/components/agent/HostFilesDialog.d.ts
@@ -1848,12 +1873,14 @@ interface SessionListItemProps {
1848
1873
  active?: boolean;
1849
1874
  onSelect?: (id: string) => void;
1850
1875
  onDelete?: (id: string) => void;
1876
+ className?: string;
1851
1877
  }
1852
1878
  declare function SessionListItem({
1853
1879
  session,
1854
1880
  active,
1855
1881
  onSelect,
1856
- onDelete
1882
+ onDelete,
1883
+ className
1857
1884
  }: SessionListItemProps): _$react.JSX.Element;
1858
1885
  interface SessionListProps {
1859
1886
  sessions: SessionInfo[];
@@ -2237,10 +2264,16 @@ type Step = {
2237
2264
  label: string; /** What one of these is called, for the disclosure's count. */
2238
2265
  noun: string;
2239
2266
  /**
2240
- * An **agent** has an identity and work of its own, so it is pressable and
2241
- * wears the sub-agent colour. A **task** is something the model described with
2242
- * no agent behind it (`isAgentRecord`), so it is inert: there is no frame to
2243
- * open, and a row that offered one would show an empty screen.
2267
+ * Both kinds press. The kind decides **where the press goes**, which is the
2268
+ * whole of the distinction.
2269
+ *
2270
+ * An **agent** has an identity and work of its own, so it wears the sub-agent
2271
+ * colour and opens that agent's own frame. A **task** is something the model
2272
+ * described with no agent behind it (`isAgentRecord`), so there is no frame:
2273
+ * framing its id selects no items and draws an empty screen. What it has
2274
+ * instead is a *place* — the spawning call's row in the transcript — so it is
2275
+ * muted, never selected, and travels there. See `StepRow` for why an inert
2276
+ * row was the worse answer.
2244
2277
  *
2245
2278
  * Two values and not a boolean because the checklist source this shape was
2246
2279
  * drawn for (see above) produces the second kind natively — a to-do is a task
package/build/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as toolIcon, A as PERMISSION_MODES, At as MenuSeparator, B as skillPrompt, Bt as badgeVariants, C as TerminalQuestionPrompt, Ct as DialogContent, D as parseUserQuestions, Dt as Menu, E as QuestionPrompt, Et as DialogTrigger, F as SkillsDialog, Ft as SelectItemText, G as Band, H as TerminalMarkdown, Ht as buttonVariants, I as McpDialog, It as SelectTrigger, J as Row, K as Blank, L as HostFilesDialog, Lt as SelectValue, M as permissionModeChoices, Mt as Select, N as permissionModeMeta, Nt as SelectContent, O as SubagentStrip, Ot as MenuContent, P as ModelSelect, Pt as SelectItem, Q as isMutatingTool, R as ContextDialog, Rt as Input, S as SessionInfoDialog, St as DialogClose, T as QUESTION_BEHAVIORS, Tt as DialogRow, U as TerminalDiff, Ut as cn, V as TerminalSurface, Vt as Button, W as previewPatch, X as WithActions, Y as CopyAction, Z as useAffordances, _ as Conversation, _t as Tip, a as Transcript, at as hashtagTrigger, b as StatusBar, bt as Dialog, c as ToolCallCard, ct as PromptArea, d as Response, dt as ProgressRing, et as TranscriptDensityProvider, f as PromptTokenText, ft as Splitter, g as FileCard, gt as copyText, h as Loader, ht as CopyButton, i as useMinuteClock, it as commandTrigger, j as PermissionModeSelect, jt as MenuTrigger, k as PermissionPrompt, kt as MenuItem, l as SessionEmptyState, lt as plainTextToSegments, m as MessageContent, mt as Spinner, n as UsageDialog, nt as useTranscriptDensity, o as TerminalItemView, ot as mentionTrigger, p as Message, pt as CodeBlock, q as Ink, r as UsageMeters, rt as useTranscriptVariant, s as TerminalTranscript, st as usePromptAreaState, t as SessionPanel, tt as TranscriptVariantProvider, u as Reasoning, ut as segmentsToPlainText, v as ConversationContent, vt as TooltipContent, w as TerminalPermissionPrompt, wt as DialogHeader, x as STATUS_META, xt as DialogBody, y as ConversationScrollButton, yt as TooltipProvider, z as Composer, zt as Badge } from "./SessionPanel-DNuPKg5c.mjs";
1
+ import { $ as toolIcon, A as PERMISSION_MODES, At as MenuSeparator, B as skillPrompt, Bt as Badge, C as TerminalQuestionPrompt, Ct as DialogContent, D as parseUserQuestions, Dt as Menu, E as QuestionPrompt, Et as DialogTrigger, F as SkillsDialog, Ft as SelectItemText, G as Band, H as TerminalMarkdown, Ht as Button, I as McpDialog, It as SelectTrigger, J as Row, K as Blank, L as HostFilesDialog, Lt as SelectValue, M as permissionModeChoices, Mt as Select, N as permissionModeMeta, Nt as SelectContent, O as SubagentStrip, Ot as MenuContent, P as ModelSelect, Pt as SelectItem, Q as isMutatingTool, R as ContextDialog, Rt as PortalScope, S as SessionInfoDialog, St as DialogClose, T as QUESTION_BEHAVIORS, Tt as DialogRow, U as TerminalDiff, Ut as buttonVariants, V as TerminalSurface, Vt as badgeVariants, W as previewPatch, Wt as cn, X as WithActions, Y as CopyAction, Z as useAffordances, _ as Conversation, _t as Tip, a as Transcript, at as hashtagTrigger, b as StatusBar, bt as Dialog, c as ToolCallCard, ct as PromptArea, d as Response, dt as ProgressRing, et as TranscriptDensityProvider, f as PromptTokenText, ft as Splitter, g as FileCard, gt as copyText, h as Loader, ht as CopyButton, i as useMinuteClock, it as commandTrigger, j as PermissionModeSelect, jt as MenuTrigger, k as PermissionPrompt, kt as MenuItem, l as SessionEmptyState, lt as plainTextToSegments, m as MessageContent, mt as Spinner, n as UsageDialog, nt as useTranscriptDensity, o as TerminalItemView, ot as mentionTrigger, p as Message, pt as CodeBlock, q as Ink, r as UsageMeters, rt as useTranscriptVariant, s as TerminalTranscript, st as usePromptAreaState, t as SessionPanel, tt as TranscriptVariantProvider, u as Reasoning, ut as segmentsToPlainText, v as ConversationContent, vt as TooltipContent, w as TerminalPermissionPrompt, wt as DialogHeader, x as STATUS_META, xt as DialogBody, y as ConversationScrollButton, yt as TooltipProvider, z as Composer, zt as Input } from "./SessionPanel-DgwjH4Ve.mjs";
2
2
  import { _ as formatRelativeTime, a as modelLabel, b as rateLimitWindowSeconds, d as formatBytes, f as formatCost, g as formatRateLimitWindowLong, h as formatRateLimitWindow, i as meterSeverity, l as windowLabel, m as formatDuration, o as statusPresentation, p as formatCountdown, r as meterColorClass, s as tightestWindow, t as contextSeverity, u as formatAgoPrecise, v as formatTokens, x as toolInputPreview, y as friendlyModel } from "./status-BE-zg88x.mjs";
3
3
  import { Fragment, forwardRef, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -46,12 +46,12 @@ Textarea.displayName = "Textarea";
46
46
  const AlertDialog = AlertDialog$1.Root;
47
47
  const AlertDialogTrigger = AlertDialog$1.Trigger;
48
48
  const AlertDialogClose = AlertDialog$1.Close;
49
- const AlertDialogContent = ({ className, children, ...props }) => /* @__PURE__ */ jsxs(AlertDialog$1.Portal, { children: [/* @__PURE__ */ jsx(AlertDialog$1.Backdrop, { className: cn("fixed inset-0 z-70 bg-black/40 backdrop-blur-[1px]", "transition-opacity duration-(--motion-base)", "data-starting-style:opacity-0 data-ending-style:opacity-0") }), /* @__PURE__ */ jsx(AlertDialog$1.Popup, {
49
+ const AlertDialogContent = ({ className, children, ...props }) => /* @__PURE__ */ jsx(AlertDialog$1.Portal, { children: /* @__PURE__ */ jsxs(PortalScope, { children: [/* @__PURE__ */ jsx(AlertDialog$1.Backdrop, { className: cn("fixed inset-0 z-70 bg-black/40 backdrop-blur-[1px]", "transition-opacity duration-(--motion-base)", "data-starting-style:opacity-0 data-ending-style:opacity-0") }), /* @__PURE__ */ jsx(AlertDialog$1.Popup, {
50
50
  "data-slot": "alert-dialog-content",
51
51
  className: cn("fixed top-1/2 left-1/2 z-70 w-[min(28rem,calc(100vw-2rem))] -translate-x-1/2 -translate-y-1/2", "rounded-lg border border-border bg-surface p-5 shadow-(--shadow-lg) outline-none", "transition-[opacity,transform] duration-(--motion-base)", "data-starting-style:scale-95 data-starting-style:opacity-0", "data-ending-style:scale-95 data-ending-style:opacity-0", className),
52
52
  ...props,
53
53
  children
54
- })] });
54
+ })] }) });
55
55
  const AlertDialogTitle = ({ className, ...props }) => /* @__PURE__ */ jsx(AlertDialog$1.Title, {
56
56
  className: cn("text-heading-3 font-semibold text-text", className),
57
57
  ...props
@@ -181,7 +181,7 @@ function Reading({ tone, onPress, label, children }) {
181
181
  })
182
182
  });
183
183
  }
184
- function TerminalStatusLine({ state, rateLimits, connection, onOpenStatus, onOpenContext, onOpenUsage }) {
184
+ function TerminalStatusLine({ className, state, rateLimits, connection, onOpenStatus, onOpenContext, onOpenUsage }) {
185
185
  const presentation = statusPresentation({
186
186
  status: state.status,
187
187
  connection
@@ -234,6 +234,7 @@ function TerminalStatusLine({ state, rateLimits, connection, onOpenStatus, onOpe
234
234
  return /* @__PURE__ */ jsx(Row, {
235
235
  "data-slot": "status-line",
236
236
  tone: "dim",
237
+ className,
237
238
  children: parts.map((part, index) => /* @__PURE__ */ jsxs("span", { children: [index > 0 ? /* @__PURE__ */ jsx(Ink, {
238
239
  tone: "faint",
239
240
  children: " · "
@@ -242,12 +243,12 @@ function TerminalStatusLine({ state, rateLimits, connection, onOpenStatus, onOpe
242
243
  }
243
244
  //#endregion
244
245
  //#region src/components/agent/SessionList.tsx
245
- function SessionListItem({ session, active, onSelect, onDelete }) {
246
+ function SessionListItem({ session, active, onSelect, onDelete, className }) {
246
247
  const meta = STATUS_META[session.status];
247
248
  return /* @__PURE__ */ jsxs("div", {
248
249
  "data-slot": "session-list-item",
249
250
  "data-active": active || void 0,
250
- className: cn("group flex w-full items-center gap-2 rounded-md border border-transparent px-2.5 py-2 text-left transition-colors", active ? "border-border bg-surface" : "hover:bg-surface-hover"),
251
+ className: cn("group flex w-full items-center gap-2 rounded-md border border-transparent px-2.5 py-2 text-left transition-colors", active ? "border-border bg-surface" : "hover:bg-surface-hover", className),
251
252
  children: [/* @__PURE__ */ jsxs("button", {
252
253
  type: "button",
253
254
  onClick: () => onSelect?.(session.id),