@workerdeck/ui 0.13.0 → 0.15.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.
@@ -2,7 +2,7 @@ import * as _$react from "react";
2
2
  import { ReactNode } from "react";
3
3
  import { LucideIcon } from "lucide-react";
4
4
  import { ModelOption, PermissionMode } from "@workerdeck/protocol";
5
- import { ConnectionState, TranscriptState } from "@workerdeck/react";
5
+ import { ConnectionState, TranscriptState, UseToolCallHostOptions } from "@workerdeck/react";
6
6
  import { WorkerDeckClient } from "@workerdeck/client";
7
7
 
8
8
  //#region src/components/agent/PermissionModeSelect.d.ts
@@ -127,6 +127,19 @@ declare function TranscriptDensityProvider({
127
127
  children: ReactNode;
128
128
  }): _$react.JSX.Element;
129
129
  declare function useTranscriptDensity(): TranscriptDensity;
130
+ /**
131
+ * The typeface the panel runs in.
132
+ *
133
+ * `sans` is the host's UI font; `mono` repoints the sans token at the mono stack
134
+ * for the panel's subtree (see the `[data-agent-font='mono']` rule in
135
+ * `theme.css`), so the transcript reads as part of a terminal rather than as a
136
+ * web app beside one.
137
+ *
138
+ * No context and no hook, unlike variant and density: nothing branches on it in
139
+ * JS. It is one attribute on the panel root and the cascade does the rest, which
140
+ * is also what keeps it from leaking past the panel.
141
+ */
142
+ type TranscriptFont = 'sans' | 'mono';
130
143
  //#endregion
131
144
  //#region src/components/agent/SessionPanel.d.ts
132
145
  interface SessionPanelProps {
@@ -205,18 +218,36 @@ interface SessionPanelProps {
205
218
  * dock is allowed to be roomy.
206
219
  */
207
220
  transcriptDensity?: TranscriptDensity;
221
+ /**
222
+ * The panel's typeface — `'sans'` (default, the host's UI font) or `'mono'`,
223
+ * which repoints the sans token at the mono stack **for this subtree only**.
224
+ *
225
+ * The third reader preference beside variant and density, and the same kind of
226
+ * thing: how a transcript should read is a property of the person reading it.
227
+ * Scoped to the panel because that is the whole claim — a monospace agent view
228
+ * next to an ordinary app, not a monospace app.
229
+ */
230
+ transcriptFont?: TranscriptFont;
208
231
  /**
209
232
  * Where the session's own controls — model and permission mode — live.
210
233
  * `'internal'` (default) draws them in the composer's toolbar row.
211
- * `'external'` draws neither, and the composer collapses to a single line
212
- * with its attach/send buttons beside the field: the embedder renders the
213
- * pickers in its own chrome (VS Code's status bar, where a click opens a
214
- * QuickPick) and drives them through {@link onControls}.
234
+ * `'status'` draws them in the panel's OWN status bar, beside the readings
235
+ * they act on; the composer collapses to a single line either way. That is
236
+ * VS Code's arrangement without VS Code a host whose panel carries a status
237
+ * bar of its own (`statusPlacement: 'bottom'`) gets the same streamlined
238
+ * shape without having to host the pickers itself.
239
+ * `'external'` draws neither: the embedder renders the pickers in its own
240
+ * chrome (VS Code's window status bar, where a click opens a QuickPick) and
241
+ * drives them through {@link onControls}.
242
+ *
243
+ * `'status'` needs a status bar to put them in — with
244
+ * `statusSurface: 'external'` there is none, and the two together would hide
245
+ * the controls entirely, so that combination falls back to the composer.
215
246
  *
216
247
  * The options themselves ride {@link SessionVitals} — an embedder must not
217
248
  * attach a second time to learn what the models are.
218
249
  */
219
- controlsSurface?: 'internal' | 'external';
250
+ controlsSurface?: 'internal' | 'external' | 'status';
220
251
  /**
221
252
  * Handed the session's setters once the panel is live, and `undefined` on
222
253
  * unmount. The counterpart to `controlsSurface: 'external'`: vitals carry the
@@ -265,6 +296,22 @@ interface SessionPanelProps {
265
296
  * enforcement lives on the gateway.
266
297
  */
267
298
  readOnly?: boolean;
299
+ /**
300
+ * Options for the browser tool host this panel runs on its own attach — or
301
+ * `false` to run none at all.
302
+ *
303
+ * The panel hosts server-bridged tool calls itself, because the bridge asks
304
+ * the *first attached client* and the panel owns the session's one attach: an
305
+ * embedder subscribing to the same handle separately would find this host
306
+ * already answering, and refusing, anything outside its allow-list. So the
307
+ * options come through here.
308
+ *
309
+ * Merged over the defaults, which host `eval_script` alone. Widening `tools`
310
+ * is a real grant — this tab will execute what the gateway asks it to for
311
+ * every name in the list — so it names them explicitly rather than accepting
312
+ * a wildcard.
313
+ */
314
+ toolHost?: UseToolCallHostOptions | false;
268
315
  className?: string;
269
316
  }
270
317
  /** What an embedder needs to *change* a session it doesn't own the attach for. */
@@ -336,13 +383,15 @@ declare function SessionPanel({
336
383
  onVitals,
337
384
  transcriptVariant,
338
385
  transcriptDensity,
386
+ transcriptFont,
339
387
  controlsSurface,
340
388
  onControls,
341
389
  focusComposerOnClick,
342
390
  unseen,
343
391
  readOnly,
392
+ toolHost,
344
393
  className
345
394
  }: SessionPanelProps): _$react.JSX.Element;
346
395
  //#endregion
347
- export { permissionModeChoices as _, SessionVitals as a, TranscriptVariant as c, useTranscriptVariant as d, PERMISSION_MODES as f, PermissionModeSelectProps as g, PermissionModeSelect as h, SessionSurfacePanel as i, TranscriptVariantProvider as l, PermissionModeMeta as m, SessionPanel as n, TranscriptDensity as o, PermissionModeChoice as p, SessionPanelProps as r, TranscriptDensityProvider as s, SessionControls as t, useTranscriptDensity as u, permissionModeMeta as v };
348
- //# sourceMappingURL=SessionPanel-CZMA44NM.d.mts.map
396
+ export { PermissionModeSelectProps as _, SessionVitals as a, TranscriptFont as c, useTranscriptDensity as d, useTranscriptVariant as f, PermissionModeSelect as g, PermissionModeMeta as h, SessionSurfacePanel as i, TranscriptVariant as l, PermissionModeChoice as m, SessionPanel as n, TranscriptDensity as o, PERMISSION_MODES as p, SessionPanelProps as r, TranscriptDensityProvider as s, SessionControls as t, TranscriptVariantProvider as u, permissionModeChoices as v, permissionModeMeta as y };
397
+ //# sourceMappingURL=SessionPanel-J2U8v88q.d.mts.map
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 { _ as permissionModeChoices, a as SessionVitals, c as TranscriptVariant, d as useTranscriptVariant, f as PERMISSION_MODES, g as PermissionModeSelectProps, h as PermissionModeSelect, i as SessionSurfacePanel, l as TranscriptVariantProvider, m as PermissionModeMeta, n as SessionPanel, o as TranscriptDensity, p as PermissionModeChoice, r as SessionPanelProps, s as TranscriptDensityProvider, t as SessionControls, u as useTranscriptDensity, v as permissionModeMeta } from "./SessionPanel-CZMA44NM.mjs";
2
+ import { _ as PermissionModeSelectProps, a as SessionVitals, c as TranscriptFont, d as useTranscriptDensity, f as useTranscriptVariant, g as PermissionModeSelect, h as PermissionModeMeta, i as SessionSurfacePanel, l as TranscriptVariant, m as PermissionModeChoice, n as SessionPanel, o as TranscriptDensity, p as PERMISSION_MODES, r as SessionPanelProps, s as TranscriptDensityProvider, t as SessionControls, u as TranscriptVariantProvider, v as permissionModeChoices, y as permissionModeMeta } from "./SessionPanel-J2U8v88q.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";
@@ -218,6 +218,12 @@ interface SplitterProps {
218
218
  max: number;
219
219
  /** Keyboard step. */
220
220
  step?: number;
221
+ /**
222
+ * Size to snap back to on a double-click — the convention every pane divider
223
+ * that can be dragged is expected to honour. Omit and a double-click does
224
+ * nothing, which is the honest behaviour when there is no default to mean.
225
+ */
226
+ defaultValue?: number;
221
227
  /** Set when dragging the splitter *away* from the origin should shrink the
222
228
  * controlled pane — i.e. the pane is on the right or the bottom. */
223
229
  inverted?: boolean;
@@ -249,11 +255,49 @@ declare function Splitter({
249
255
  min,
250
256
  max,
251
257
  step,
258
+ defaultValue,
252
259
  inverted,
253
260
  'aria-label': label,
254
261
  className
255
262
  }: SplitterProps): _$react.JSX.Element;
256
263
  //#endregion
264
+ //#region src/components/ui/Empty.d.ts
265
+ /**
266
+ * A view with nothing in it: icon, title, description, and at most one action.
267
+ *
268
+ * Centered and given room, because an empty view is the first thing a new
269
+ * install shows and a flush-left sentence in the top corner reads like a bug
270
+ * report. It lives here rather than in one client because every panel that can
271
+ * be empty should be empty the same way — the extension's views and the
272
+ * dashboard's four sidebars are the same shape of thing.
273
+ *
274
+ * **At most one action, and never one the view header already offers.** Creating
275
+ * a session and adding a gateway are the `+` in the native title bar, exclusively
276
+ * — so those empty states point at it in words rather than growing a second
277
+ * button that does the same thing two inches lower. A button here is for the way
278
+ * out of a state the header has no answer to: clearing a filter, widening a
279
+ * scope.
280
+ */
281
+ declare function Empty({
282
+ icon,
283
+ title,
284
+ description,
285
+ action,
286
+ onAction
287
+ }: {
288
+ icon: ReactNode;
289
+ title: string;
290
+ description?: ReactNode;
291
+ action?: string;
292
+ onAction?: () => void;
293
+ }): _$react.JSX.Element;
294
+ /** A key or icon named inline in an empty state's description — "use the + above". */
295
+ declare function EmptyKey({
296
+ children
297
+ }: {
298
+ children: ReactNode;
299
+ }): _$react.JSX.Element;
300
+ //#endregion
257
301
  //#region src/components/ui/ProgressRing.d.ts
258
302
  interface ProgressRingProps {
259
303
  /** Filled share, 0–100 (clamped). */
@@ -1147,6 +1191,13 @@ interface StatusBarProps {
1147
1191
  onOpenStatus?: () => void;
1148
1192
  onOpenContext?: () => void;
1149
1193
  onOpenUsage?: () => void;
1194
+ /**
1195
+ * The session's own controls (model, permission mode), for
1196
+ * `controlsSurface: 'status'`. They sit at the end of the readings cluster —
1197
+ * status, context, usage, then what you can *change* — rather than out by the
1198
+ * actions menu, because they belong with the session facts they act on.
1199
+ */
1200
+ controls?: ReactNode;
1150
1201
  /** Trailing slot — the session-actions menu, at the bar's trailing edge. */
1151
1202
  actions?: ReactNode;
1152
1203
  /** Which edge the bar sits on, so its separating rule goes on the other side.
@@ -1161,6 +1212,7 @@ declare function StatusBar({
1161
1212
  onOpenStatus,
1162
1213
  onOpenContext,
1163
1214
  onOpenUsage,
1215
+ controls,
1164
1216
  actions,
1165
1217
  placement,
1166
1218
  className
@@ -1570,5 +1622,5 @@ declare function toolIcon(toolName: string): LucideIcon;
1570
1622
  */
1571
1623
  declare function isMutatingTool(toolName: string): boolean;
1572
1624
  //#endregion
1573
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, Composer, type ComposerFileMatch, type ComposerHandle, type ComposerProps, ContextDialog, type ContextDialogProps, Conversation, ConversationContent, type ConversationProps, ConversationScrollButton, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, EngineIcon, FileCard, type FileCardProps, type FileDeliveredItem, HostFilesDialog, type HostFilesDialogProps, Input, Loader, McpDialog, type McpDialogProps, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, type MessageProps, ModelSelect, type ModelSelectProps, PERMISSION_MODES, type PermissionModeChoice, type PermissionModeMeta, PermissionModeSelect, type PermissionModeSelectProps, PermissionPrompt, type PermissionPromptProps, ProgressRing, type ProgressRingProps, PromptArea, type PromptAreaHandle, type PromptAreaProps, PromptTokenText, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, type SessionBrowserProps, type SessionControls, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, SessionStatusIcon, type SessionSurfacePanel, type SessionVitals, SkillsDialog, type SkillsDialogProps, Spinner, Splitter, type SplitterProps, StatusBar, type StatusBarProps, type TextSegment, Textarea, Tip, Toaster, ToolCallCard, type ToolCallCardProps, type ToolCallItem, TooltipContent, TooltipProvider, Transcript, type TranscriptDensity, TranscriptDensityProvider, type TranscriptProps, type TranscriptVariant, TranscriptVariantProvider, type TriggerConfig, type TriggerSuggestion, UsageDialog, type UsageDialogProps, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
1625
+ export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type ChipSegment, CodeBlock, type CodeBlockProps, Composer, type ComposerFileMatch, type ComposerHandle, type ComposerProps, ContextDialog, type ContextDialogProps, Conversation, ConversationContent, type ConversationProps, ConversationScrollButton, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, type FileCardProps, type FileDeliveredItem, HostFilesDialog, type HostFilesDialogProps, Input, Loader, McpDialog, type McpDialogProps, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, type MessageProps, ModelSelect, type ModelSelectProps, PERMISSION_MODES, type PermissionModeChoice, type PermissionModeMeta, PermissionModeSelect, type PermissionModeSelectProps, PermissionPrompt, type PermissionPromptProps, ProgressRing, type ProgressRingProps, PromptArea, type PromptAreaHandle, type PromptAreaProps, PromptTokenText, QUESTION_BEHAVIORS, type QuestionBehaviorMeta, QuestionPrompt, type QuestionPromptProps, Reasoning, type ReasoningProps, Response, type ResponseProps, STATUS_META, type Segment, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, type SessionBrowserProps, type SessionControls, SessionEmptyState, type SessionEmptyStateProps, SessionInfoDialog, type SessionInfoDialogProps, SessionList, SessionListItem, type SessionListItemProps, type SessionListProps, SessionPanel, type SessionPanelProps, SessionStatusIcon, type SessionSurfacePanel, type SessionVitals, SkillsDialog, type SkillsDialogProps, Spinner, Splitter, type SplitterProps, StatusBar, type StatusBarProps, type TextSegment, Textarea, Tip, Toaster, ToolCallCard, type ToolCallCardProps, type ToolCallItem, TooltipContent, TooltipProvider, Transcript, type TranscriptDensity, TranscriptDensityProvider, type TranscriptFont, type TranscriptProps, type TranscriptVariant, TranscriptVariantProvider, type TriggerConfig, type TriggerSuggestion, UsageDialog, type UsageDialogProps, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
1574
1626
  //# sourceMappingURL=index.d.mts.map
package/build/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as Tip, A as SkillsDialog, B as commandTrigger, C as isMutatingTool, Ct as Button, D as permissionModeChoices, E as PermissionModeSelect, F as skillPrompt, G as plainTextToSegments, H as mentionTrigger, I as TranscriptDensityProvider, J as Splitter, K as segmentsToPlainText, L as TranscriptVariantProvider, M as HostFilesDialog, N as ContextDialog, O as permissionModeMeta, P as Composer, Q as copyText, R as useTranscriptDensity, S as Response, St as badgeVariants, T as PERMISSION_MODES, Tt as cn, U as usePromptAreaState, V as hashtagTrigger, W as PromptArea, X as Spinner, Y as CodeBlock, Z as CopyButton, _ as SessionInfoDialog, _t as SelectItemText, a as SessionEmptyState, at as DialogContent, b as parseUserQuestions, bt as Input, c as Message, ct as DialogTrigger, d as FileCard, dt as MenuItem, et as TooltipContent, f as Conversation, ft as MenuSeparator, g as STATUS_META, gt as SelectItem, h as StatusBar, ht as SelectContent, i as ToolCallCard, it as DialogClose, j as McpDialog, k as ModelSelect, l as MessageContent, lt as Menu, m as ConversationScrollButton, mt as Select, n as UsageDialog, nt as Dialog, o as Reasoning, ot as DialogHeader, p as ConversationContent, pt as MenuTrigger, q as ProgressRing, r as Transcript, rt as DialogBody, s as PromptTokenText, st as DialogRow, t as SessionPanel, tt as TooltipProvider, u as Loader, ut as MenuContent, v as QUESTION_BEHAVIORS, vt as SelectTrigger, w as toolIcon, wt as buttonVariants, x as PermissionPrompt, xt as Badge, y as QuestionPrompt, yt as SelectValue, z as useTranscriptVariant } from "./SessionPanel-CKQa4i0Y.mjs";
1
+ import { $ as Tip, A as SkillsDialog, B as commandTrigger, C as isMutatingTool, Ct as Button, D as permissionModeChoices, E as PermissionModeSelect, F as skillPrompt, G as plainTextToSegments, H as mentionTrigger, I as TranscriptDensityProvider, J as Splitter, K as segmentsToPlainText, L as TranscriptVariantProvider, M as HostFilesDialog, N as ContextDialog, O as permissionModeMeta, P as Composer, Q as copyText, R as useTranscriptDensity, S as Response, St as badgeVariants, T as PERMISSION_MODES, Tt as cn, U as usePromptAreaState, V as hashtagTrigger, W as PromptArea, X as Spinner, Y as CodeBlock, Z as CopyButton, _ as SessionInfoDialog, _t as SelectItemText, a as SessionEmptyState, at as DialogContent, b as parseUserQuestions, bt as Input, c as Message, ct as DialogTrigger, d as FileCard, dt as MenuItem, et as TooltipContent, f as Conversation, ft as MenuSeparator, g as STATUS_META, gt as SelectItem, h as StatusBar, ht as SelectContent, i as ToolCallCard, it as DialogClose, j as McpDialog, k as ModelSelect, l as MessageContent, lt as Menu, m as ConversationScrollButton, mt as Select, n as UsageDialog, nt as Dialog, o as Reasoning, ot as DialogHeader, p as ConversationContent, pt as MenuTrigger, q as ProgressRing, r as Transcript, rt as DialogBody, s as PromptTokenText, st as DialogRow, t as SessionPanel, tt as TooltipProvider, u as Loader, ut as MenuContent, v as QUESTION_BEHAVIORS, vt as SelectTrigger, w as toolIcon, wt as buttonVariants, x as PermissionPrompt, xt as Badge, y as QuestionPrompt, yt as SelectValue, z as useTranscriptVariant } from "./SessionPanel-DI1NO4l8.mjs";
2
2
  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-DqR56Y8l.mjs";
3
3
  import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
4
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
- import { BellRing, CircleAlert, CircleSlash, Moon, PauseCircle, Pencil, Search, Trash2, X } from "lucide-react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { BellRing, CircleAlert, CircleSlash, Layers, Moon, PauseCircle, Pencil, Search, SearchX, Trash2, X } from "lucide-react";
6
6
  import { AlertDialog as AlertDialog$1 } from "@base-ui/react/alert-dialog";
7
7
  import { Toaster as Toaster$1, toast } from "sonner";
8
8
  import { STATE_LABELS, STATE_ORDER, adaptersOf, clearFilters, filterRows, groupRows, hasFacetFilter, sessionLabel, subsetSummary } from "@workerdeck/protocol";
@@ -77,6 +77,57 @@ function Toaster() {
77
77
  });
78
78
  }
79
79
  //#endregion
80
+ //#region src/components/ui/Empty.tsx
81
+ /**
82
+ * A view with nothing in it: icon, title, description, and at most one action.
83
+ *
84
+ * Centered and given room, because an empty view is the first thing a new
85
+ * install shows and a flush-left sentence in the top corner reads like a bug
86
+ * report. It lives here rather than in one client because every panel that can
87
+ * be empty should be empty the same way — the extension's views and the
88
+ * dashboard's four sidebars are the same shape of thing.
89
+ *
90
+ * **At most one action, and never one the view header already offers.** Creating
91
+ * a session and adding a gateway are the `+` in the native title bar, exclusively
92
+ * — so those empty states point at it in words rather than growing a second
93
+ * button that does the same thing two inches lower. A button here is for the way
94
+ * out of a state the header has no answer to: clearing a filter, widening a
95
+ * scope.
96
+ */
97
+ function Empty({ icon, title, description, action, onAction }) {
98
+ return /* @__PURE__ */ jsxs("div", {
99
+ className: "flex flex-col items-center gap-2 px-5 py-8 text-center",
100
+ children: [
101
+ /* @__PURE__ */ jsx("div", {
102
+ className: "text-fg-4 opacity-60 [&_svg]:size-7",
103
+ children: icon
104
+ }),
105
+ /* @__PURE__ */ jsx("p", {
106
+ className: "text-body-sm font-medium text-fg-2",
107
+ children: title
108
+ }),
109
+ description ? /* @__PURE__ */ jsx("p", {
110
+ className: "max-w-[26ch] text-balance text-label leading-relaxed text-fg-4",
111
+ children: description
112
+ }) : null,
113
+ action && onAction ? /* @__PURE__ */ jsx(Button, {
114
+ variant: "outline",
115
+ size: "sm",
116
+ className: "mt-1",
117
+ onClick: onAction,
118
+ children: action
119
+ }) : null
120
+ ]
121
+ });
122
+ }
123
+ /** A key or icon named inline in an empty state's description — "use the + above". */
124
+ function EmptyKey({ children }) {
125
+ return /* @__PURE__ */ jsx("span", {
126
+ className: "rounded border border-border px-1 font-mono text-fg-3",
127
+ children
128
+ });
129
+ }
130
+ //#endregion
80
131
  //#region src/components/prompt-area/segment-helpers.ts
81
132
  /** Returns `true` when the segment array is empty or contains only whitespace text. */
82
133
  function isSegmentsEmpty(segments) {
@@ -319,16 +370,20 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
319
370
  children: "Show all"
320
371
  })]
321
372
  }) : null,
322
- rows.length === 0 ? emptyState ?? /* @__PURE__ */ jsx(Empty, { children: "No sessions yet." }) : visible.length === 0 ? /* @__PURE__ */ jsx(Empty, { children: hasFacetFilter(config) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
323
- "No sessions match.",
324
- " ",
325
- /* @__PURE__ */ jsx("button", {
326
- type: "button",
327
- className: "underline underline-offset-2 hover:text-fg-1",
328
- onClick: () => onConfigChange(clearFilters(config)),
329
- children: "Clear filters"
330
- })
331
- ] }) : "No sessions here." }) : /* @__PURE__ */ jsx("div", {
373
+ rows.length === 0 ? emptyState ?? /* @__PURE__ */ jsx(Empty, {
374
+ icon: /* @__PURE__ */ jsx(Layers, {}),
375
+ title: "No sessions yet"
376
+ }) : visible.length === 0 ? hasFacetFilter(config) ? /* @__PURE__ */ jsx(Empty, {
377
+ icon: /* @__PURE__ */ jsx(SearchX, {}),
378
+ title: "No matches",
379
+ description: "No session matches the current search and filters.",
380
+ action: "Clear filters",
381
+ onAction: () => onConfigChange(clearFilters(config))
382
+ }) : /* @__PURE__ */ jsx(Empty, {
383
+ icon: /* @__PURE__ */ jsx(Layers, {}),
384
+ title: "Nothing here",
385
+ description: "No session to show."
386
+ }) : /* @__PURE__ */ jsx("div", {
332
387
  className: "flex flex-col gap-4",
333
388
  children: groups.map((group) => /* @__PURE__ */ jsxs("div", {
334
389
  className: "flex flex-col gap-1",
@@ -354,12 +409,6 @@ function SessionBrowser({ rows, config, onConfigChange, scope, activeId, onSelec
354
409
  ]
355
410
  });
356
411
  }
357
- function Empty({ children }) {
358
- return /* @__PURE__ */ jsx("div", {
359
- className: "px-3 py-6 text-center text-body-sm text-fg-4",
360
- children
361
- });
362
- }
363
412
  function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename }) {
364
413
  const { info } = row;
365
414
  const [editing, setEditing] = useState(false);
@@ -374,6 +423,7 @@ function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename
374
423
  return /* @__PURE__ */ jsxs("div", {
375
424
  "data-slot": "session-row",
376
425
  "data-active": active || void 0,
426
+ onClick: () => !editing && onSelect?.(row),
377
427
  className: cn("group flex cursor-pointer flex-col gap-0.5 text-left transition-colors", rowShapeClass(active === true)),
378
428
  children: [/* @__PURE__ */ jsxs("div", {
379
429
  className: "flex items-center gap-1.5",
@@ -387,7 +437,6 @@ function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename
387
437
  onCancel: () => setEditing(false)
388
438
  }) : /* @__PURE__ */ jsx("button", {
389
439
  type: "button",
390
- onClick: () => onSelect?.(row),
391
440
  className: cn("min-w-0 flex-1 truncate text-left text-body-sm outline-none", active ? "font-medium text-fg-1" : "text-fg-2"),
392
441
  children: sessionLabel(info)
393
442
  }),
@@ -407,7 +456,7 @@ function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename
407
456
  children: [
408
457
  /* @__PURE__ */ jsx("button", {
409
458
  type: "button",
410
- onClick: () => !editing && onSelect?.(row),
459
+ tabIndex: -1,
411
460
  className: "min-w-0 flex-1 truncate text-left font-mono outline-none",
412
461
  children: details.join(" · ")
413
462
  }),
@@ -416,7 +465,10 @@ function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename
416
465
  size: "icon-sm",
417
466
  "aria-label": "Rename session",
418
467
  className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
419
- onClick: () => setEditing(true),
468
+ onClick: (e) => {
469
+ e.stopPropagation();
470
+ setEditing(true);
471
+ },
420
472
  children: /* @__PURE__ */ jsx(Pencil, { className: "size-3 text-fg-3" })
421
473
  }) : null,
422
474
  onDelete ? /* @__PURE__ */ jsx(Button, {
@@ -424,7 +476,10 @@ function SessionRowItem({ row, active, showGateway, onSelect, onDelete, onRename
424
476
  size: "icon-sm",
425
477
  "aria-label": "Close session",
426
478
  className: "size-5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100",
427
- onClick: () => onDelete(row),
479
+ onClick: (e) => {
480
+ e.stopPropagation();
481
+ onDelete(row);
482
+ },
428
483
  children: /* @__PURE__ */ jsx(Trash2, { className: "size-3 text-fg-3" })
429
484
  }) : null
430
485
  ]
@@ -612,6 +667,6 @@ function EngineIcon({ engine, model, className }) {
612
667
  });
613
668
  }
614
669
  //#endregion
615
- export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, Conversation, ConversationContent, ConversationScrollButton, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, EngineIcon, FileCard, HostFilesDialog, Input, Loader, McpDialog, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, ProgressRing, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, STATUS_META, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionInfoDialog, SessionList, SessionListItem, SessionPanel, SessionStatusIcon, SkillsDialog, Spinner, Splitter, StatusBar, Textarea, Tip, Toaster, ToolCallCard, TooltipContent, TooltipProvider, Transcript, TranscriptDensityProvider, TranscriptVariantProvider, UsageDialog, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
670
+ export { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogTitle, AlertDialogTrigger, Badge, Button, Card, CardContent, CardHeader, CardTitle, CodeBlock, Composer, ContextDialog, Conversation, ConversationContent, ConversationScrollButton, CopyButton, Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger, Empty, EmptyKey, EngineIcon, FileCard, HostFilesDialog, Input, Loader, McpDialog, Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Message, MessageContent, ModelSelect, PERMISSION_MODES, PermissionModeSelect, PermissionPrompt, ProgressRing, PromptArea, PromptTokenText, QUESTION_BEHAVIORS, QuestionPrompt, Reasoning, Response, STATUS_META, Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue, SessionBrowser, SessionEmptyState, SessionInfoDialog, SessionList, SessionListItem, SessionPanel, SessionStatusIcon, SkillsDialog, Spinner, Splitter, StatusBar, Textarea, Tip, Toaster, ToolCallCard, TooltipContent, TooltipProvider, Transcript, TranscriptDensityProvider, TranscriptVariantProvider, UsageDialog, badgeVariants, buttonVariants, cn, commandTrigger, copyText, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, getChipsByTrigger, hashtagTrigger, isMutatingTool, isSegmentsEmpty, mentionTrigger, parseUserQuestions, permissionModeChoices, permissionModeMeta, plainTextToSegments, rateLimitWindowSeconds, rowShapeClass, segmentsToPlainText, skillPrompt, toast, toolIcon, toolInputPreview, usePromptAreaState, useTranscriptDensity, useTranscriptVariant };
616
671
 
617
672
  //# sourceMappingURL=index.mjs.map