@wrongstack/tui 0.308.0 → 0.308.2

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.
@@ -1,8 +1,8 @@
1
1
  import type React from 'react';
2
2
  import type { AppViewProps } from './app-view-contract.js';
3
- import type { PanelId } from './ui-contracts.js';
4
- import type { useSidebarConnections, useSidebarKanban, useSidebarProcessList } from './hooks/use-sidebar-panel-data.js';
5
3
  import type { usePlanPanelData } from './components/plan-panel.js';
4
+ import type { useSidebarConnections, useSidebarKanban, useSidebarProcessList } from './hooks/use-sidebar-panel-data.js';
5
+ import type { PanelId } from './ui-contracts.js';
6
6
  export interface AppViewSidebarProps {
7
7
  host: AppViewProps['host'];
8
8
  runtime: AppViewProps['runtime'];
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import type { HistoryEntry } from './types.js';
3
3
  export declare function ToolEntry({ entry, termWidth, multiDiffSummaryThreshold, showSageMemoryInject, }: {
4
4
  entry: Extract<HistoryEntry, {
@@ -0,0 +1,34 @@
1
+ import type React from 'react';
2
+ export interface CardProps {
3
+ /** Outer content width in cols (already inside the parent frame's
4
+ * border + padding — i.e. the available width the card must fill). */
5
+ innerWidth: number;
6
+ /** Optional bottom margin (defaults to 0). Persistent cards chain with
7
+ * no margin; the F-twin frame usually adds its own spacing. */
8
+ marginBottom?: number | undefined;
9
+ /** Optional accent color for the top + bottom cap hairlines. When set,
10
+ * paints the frame in the panel's state color (green = healthy,
11
+ * red = alerting, etc.). */
12
+ accent?: string | undefined;
13
+ /** Draw the top + bottom hairline around the card body. When false, the
14
+ * Card renders only the body (no corners, no bottom rule) so it can be
15
+ * nested inside an outer frame without double-chroming. The F-twin
16
+ * SidebarPanelFrame uses this for the title row. */
17
+ capped?: boolean | undefined;
18
+ /**
19
+ * Render-prop body. The Card walks the returned tree, flattens Fragments +
20
+ * column Boxes, and wraps every top-level child in a `│ ... │` row so the
21
+ * frame stays intact on every body line. `bodyWidth` is the inner content
22
+ * width (already accounting for side bars + padding) so callers don't
23
+ * have to recompute it.
24
+ */
25
+ children: (bodyWidth: number) => React.ReactNode;
26
+ }
27
+ /**
28
+ * A raised "card" wrapper for the persistent sidebar content. The accent
29
+ * top edge and hairlines stay at the card's full width to visually "frame"
30
+ * it; the body content is inset by 1 column on each side so text never
31
+ * touches the colored surface directly.
32
+ */
33
+ export declare function Card({ innerWidth, marginBottom, accent, capped, children, }: CardProps): React.ReactElement;
34
+ //# sourceMappingURL=sidebar-card.d.ts.map
@@ -5,6 +5,7 @@ import type React from 'react';
5
5
  import type { ResumeSessionEntry } from '../app-state.js';
6
6
  import type { FleetEntry } from '../app-state-fleet.js';
7
7
  import type { HeapSample } from '../heap-watchdog.js';
8
+ import type { PanelId } from '../ui-contracts.js';
8
9
  import type { LiveSessionEntry } from './sessions-panel.js';
9
10
  export interface SidebarContentProps {
10
11
  /** Live context window data from useStatusbarViewModel. */
@@ -72,6 +73,17 @@ export interface SidebarContentProps {
72
73
  heapHistory?: readonly number[] | undefined;
73
74
  /** Total physical RAM in bytes — denominator of the RAM ratio. */
74
75
  totalMem?: number | undefined;
76
+ /**
77
+ * Set of F-key panels that are routed to the sidebar AND win a slot
78
+ * under `SIDEBAR_PANEL_LIMIT` this render. The persistent AGENT SWARM /
79
+ * MISSIONS / SESSIONS cards check this set and skip themselves when the
80
+ * corresponding F twin is already mounted above — otherwise the user
81
+ * would see the same data rendered twice (once as a routed twin, once
82
+ * as a persistent card). The F twin wins because it has its own Card
83
+ * chrome and richer header / status affordances; the persistent card
84
+ * is the fallback when the twin is at the bottom (F-key default).
85
+ */
86
+ effectiveSidebarRoutes?: ReadonlySet<PanelId> | undefined;
75
87
  }
76
88
  /**
77
89
  * Normalized "is this session row the current session?" predicate used by
@@ -89,6 +101,23 @@ export interface SidebarContentProps {
89
101
  * single source of truth.
90
102
  */
91
103
  export declare function isCurrentSession(rowId: string | undefined, currentSessionId: string | undefined, fallbackIsCurrent?: boolean | undefined): boolean;
104
+ /**
105
+ * (Replaced by `SidebarSectionHeader` in `./sidebar-panel-frame.tsx`.)
106
+ * Kept here as a doc-comment so anyone hunting for "the sidebar's section
107
+ * header" lands on the right file. The local `SectionHeader` symbol was
108
+ * promoted to the shared `sidebar-panel-frame.tsx` so routed panels and
109
+ * persistent content cards use the same capsuled-pill component.
110
+ */
111
+ /**
112
+ * The `Card` component now lives in `./sidebar-card.tsx` as the shared
113
+ * raised-surface iskelet used by both the persistent cards (this file) and
114
+ * the routed F-key panel twins (`sidebar-panel-frame.tsx` +
115
+ * `sidebar-panels-{workspace,task}.tsx`). Imported at the top of this file
116
+ * for the `MODEL CORE`, `PROMPT CACHE`, `SYSTEM`, `AGENT SWARM`, `MISSIONS`,
117
+ * `SESSIONS`, and `TOOL TICKER` cards — the migration keeps the persistent
118
+ * call sites identical because the shared component preserves the same
119
+ * `innerWidth` / `marginBottom` / `accent` / `children` contract.
120
+ */
92
121
  interface ContextSegment {
93
122
  label: string;
94
123
  shortLabel: string;
@@ -102,6 +131,6 @@ export declare function contextSpectrum(breakdown: ContextBreakdown | undefined,
102
131
  } | undefined, width: number): Array<ContextSegment & {
103
132
  cells: number;
104
133
  }>;
105
- export declare function SidebarContent({ contextWindow, contextBreakdown, cacheStats, cacheCoverageTokens, entries, fleetCounts, provider, model, width, scrollOffset, focused, todos, showSwarmSection, liveSessions, resumeSessions, currentSessionId, processMemory, cpuPercent, cpuHistory, rssHistory, heapHistory, totalMem, }: SidebarContentProps): React.ReactElement;
134
+ export declare function SidebarContent({ contextWindow, contextBreakdown, cacheStats, cacheCoverageTokens, entries, fleetCounts, provider, model, width, scrollOffset, focused, todos, showSwarmSection, liveSessions, resumeSessions, currentSessionId, processMemory, cpuPercent, cpuHistory, rssHistory, heapHistory, totalMem, effectiveSidebarRoutes, }: SidebarContentProps): React.ReactElement;
106
135
  export {};
107
136
  //# sourceMappingURL=sidebar-content.d.ts.map
@@ -1,4 +1,5 @@
1
- import type React from 'react';
1
+ import React from 'react';
2
+ import { type CardProps } from './sidebar-card.js';
2
3
  export interface SidebarPanelFrameProps {
3
4
  /** Accent color for the rail, title, and separator. */
4
5
  accent: string;
@@ -14,12 +15,28 @@ export interface SidebarPanelFrameProps {
14
15
  width: number;
15
16
  /** Optional quiet subtitle hidden on narrow terminals. */
16
17
  kicker?: string | undefined;
17
- /** Optional right-aligned header content (status badge, counts, etc.). */
18
+ /** Optional right-aligned header content (status badge, counts, etc.).
19
+ * Wrapped automatically in a pill chrome if `pillStatus` is supplied. */
18
20
  right?: React.ReactNode | undefined;
21
+ /**
22
+ * When provided, the right-side header content is rendered through
23
+ * `SidebarStatusPill` with the given color and label. Existing
24
+ * `right={<Text>...</Text>}` callers still work; pass `pillLabel`+`pillColor`
25
+ * for the new look without rewriting every call site.
26
+ */
27
+ pillLabel?: string | undefined;
28
+ pillColor?: string | undefined;
19
29
  /** Footer content (key hints, footer note). Renders under the body. */
20
30
  footer?: React.ReactNode | undefined;
21
- /** Body content. The outer RightSidebar owns viewport clipping. */
22
- children?: React.ReactNode | undefined;
31
+ /**
32
+ * Body content. Pass a function to receive the Card's *body content width*
33
+ * (the inset width after the Card's optional `│` sides and body padding,
34
+ * not the outer card width). This mirrors the `Card` render prop and lets
35
+ * `SidebarSectionHeader` / `SidebarStatRow` / `SidebarWorklistRow` size
36
+ * their dotted leaders and metric columns to the actual available width
37
+ * instead of over-shooting into the Card's side bars.
38
+ */
39
+ children?: React.ReactNode | ((bodyWidth: number) => React.ReactNode) | undefined;
23
40
  }
24
41
  /**
25
42
  * Truncate a string to fit within `max` display columns, adding an ellipsis.
@@ -27,36 +44,103 @@ export interface SidebarPanelFrameProps {
27
44
  * helper without pulling in sidebar-content.tsx's full implementation.
28
45
  */
29
46
  export declare function trunc(s: string, max: number): string;
47
+ /**
48
+ * A "capsuled" status pill, e.g. `⟦ live 12 ⟧`. Used in panel headers
49
+ * (right side) and stat rows. Renders inline — no Box, no flex — so it can
50
+ * sit next to a label without burning a row of its own.
51
+ */
52
+ export declare function SidebarStatusPill({ label, color, outlined, }: {
53
+ label: string;
54
+ color: string;
55
+ /** When true, render the brackets in muted color so the inner label
56
+ * reads as the main signal — useful in dense stat rows. */
57
+ outlined?: boolean | undefined;
58
+ }): React.ReactElement;
59
+ /**
60
+ * A label : value row, sized for narrow rails. Reserves the first column
61
+ * for an optional accent rail so a stat block reads as a single column of
62
+ * cohesive data rather than a stack of loose Text nodes. The separator is
63
+ * a flexible dot-leader so the value always lands at the right edge.
64
+ */
65
+ export declare function SidebarStatRow({ label, value, color, accent, innerWidth, valueMuted, }: {
66
+ label: string;
67
+ value: string;
68
+ color?: string | undefined;
69
+ /** Optional accent rail. When set, a 1-col rail glyph is drawn at the
70
+ * start of the row in this color so a block of rows reads as a "tag". */
71
+ accent?: string | undefined;
72
+ innerWidth: number;
73
+ valueMuted?: boolean | undefined;
74
+ }): React.ReactElement;
75
+ /**
76
+ * A subtle horizontal divider with an optional centered diamond ornament.
77
+ * Width-aware: on very narrow rails the diamond is dropped so the rule
78
+ * never overflows the column.
79
+ */
80
+ export declare function SidebarDivider({ innerWidth, ornament, color, }: {
81
+ innerWidth: number;
82
+ /** When set, draws `ornament` centered on the rule. */
83
+ ornament?: string | undefined;
84
+ color?: string | undefined;
85
+ }): React.ReactElement;
30
86
  /**
31
87
  * A section header: colored glyph + bold uppercase label, a dotted leader
32
88
  * filling the remaining width, and an optional right-aligned badge. Always
33
89
  * renders exactly one row of exactly `innerWidth` columns — the badge is
34
90
  * dropped gracefully when there is no room (narrow terminals).
91
+ *
92
+ * Modernized (v2):
93
+ * * The glyph sits inside a 1-col "node" rail (▎) so it reads as a
94
+ * visual anchor and never collides with the leading bold label.
95
+ * * The badge is rendered through `SidebarStatusPill` (when `pill` is
96
+ * true) so it picks up the capsuled ⟦ ⟧ treatment.
97
+ * * The leader uses a real dotted leader (·) instead of a thin rule
98
+ * (╌) which renders inconsistently across terminal emulators.
35
99
  */
36
- export declare function SidebarSectionHeader({ glyph, label, color, badge, badgeColor, innerWidth, }: {
100
+ export declare function SidebarSectionHeader({ glyph, label, color, badge, badgeColor, innerWidth, pill, badgeMuted, }: {
37
101
  glyph: string;
38
102
  label: string;
39
103
  color: string;
40
104
  badge?: string | undefined;
41
105
  badgeColor?: string | undefined;
42
106
  innerWidth: number;
107
+ /** Render the badge as a capsuled pill instead of a bare token. */
108
+ pill?: boolean | undefined;
109
+ /** When true, color the badge in muted text instead of accent. Useful
110
+ * for "no data yet" empty-state badges. */
111
+ badgeMuted?: boolean | undefined;
43
112
  }): React.ReactElement;
44
- /** A raised content band sized for a narrow rail. Section headers provide the
45
- * accent, while the lifted surface groups related data without spending any
46
- * horizontal columns on nested chrome. */
47
- export declare function SidebarPanelCard({ innerWidth, marginBottom, children, }: {
48
- innerWidth: number;
49
- marginBottom?: number | undefined;
50
- children: React.ReactNode;
51
- }): React.ReactElement;
113
+ /**
114
+ * A thin wrapper around the shared `Card` iskelet from
115
+ * `./sidebar-card.tsx`. Preserved as a public export so existing test
116
+ * fixtures and direct callers (e.g. `card-frame-integrity.test.tsx`) keep
117
+ * working without changes. The new shared `Card` carries an extra `capped`
118
+ * flag (defaulting to `true` for the legacy semantic of always drawing
119
+ * the top + bottom cap); routed F-twin callers that want a hairline
120
+ * divider instead of a corner frame should use the shared `Card` directly
121
+ * with `capped={false}`.
122
+ */
123
+ export declare function SidebarPanelCard(props: CardProps): React.ReactElement;
52
124
  /**
53
125
  * SidebarPanelFrame — the standard chrome wrapper used by every sidebar
54
- * panel variant. It renders an accent-led title and telemetry strip inside the
55
- * existing RightSidebar shell, followed by a natural-height body and optional
56
- * footer. Avoiding a second border preserves scarce horizontal space; the
57
- * outer shell clips the combined routed-panel and persistent-content stack.
126
+ * panel variant. It composes a title row + optional status row + optional
127
+ * kicker + body on top of the shared `Card` iskelet from
128
+ * `./sidebar-card.tsx` (the same family the persistent MODEL CORE /
129
+ * PROMPT CACHE / SYSTEM / AGENT SWARM / MISSIONS / SESSIONS cards use),
130
+ * followed by an optional footer rendered below the card. The outer
131
+ * RightSidebar still owns the border + padding + viewport clipping so
132
+ * the routed frame's corners sit flush with the persistent cards down
133
+ * the rail.
134
+ *
135
+ * v3: the chrome is delegated to the shared `Card` so the routed F twins
136
+ * and the persistent cards read as one family at a glance. The previous
137
+ * hand-rolled "borderless" title chrome is gone — the Card corners are
138
+ * the only top/bottom rule. The `▎` rail at the title row's left edge is
139
+ * preserved as the panel's accent signal (matching the persistent cards'
140
+ * stage banner style), and the `│` sides from the Card body supply the
141
+ * "framed" look on rails wide enough to afford them.
58
142
  */
59
- export declare function SidebarPanelFrame({ accent, icon, title, width, kicker, right, footer, children, }: SidebarPanelFrameProps): React.ReactElement;
143
+ export declare function SidebarPanelFrame({ accent, icon, title, width, kicker, right, pillLabel, pillColor, footer, children, }: SidebarPanelFrameProps): React.ReactElement;
60
144
  /**
61
145
  * useSidebarPanelSize — returns a sensible default width / height for a
62
146
  * sidebar panel given the terminal dimensions. Width mirrors
@@ -8,6 +8,28 @@ export declare function liveSessionGlyph(status: string): string;
8
8
  export declare function liveSessionColor(status: string): string;
9
9
  export declare function fmtRelative(iso: string | undefined, now?: number): string;
10
10
  export declare function fmtShortDuration(ms: number): string;
11
+ /**
12
+ * Shared "empty state" row used by every routed F-twin sidebar panel and the
13
+ * persistent cards. Replaces the patchwork of `◇ scanning for links…`,
14
+ * `{glyphs.dividerDot} no X`, etc. with one consistent look:
15
+ *
16
+ * · no sessions
17
+ *
18
+ * The leading `·` (dividerDot) is the muted accent, the message is in
19
+ * `theme.textMuted`, and the row honors the rail's body width. Callers
20
+ * only supply the noun (and an optional active-verb form for "scanning"
21
+ * style progress states). Keep the language lower-case to read as a
22
+ * quiet signal rather than a banner.
23
+ */
24
+ export declare function EmptyState({ message, innerWidth, variant, }: {
25
+ message: string;
26
+ innerWidth: number;
27
+ /** `idle` is the standard "no X" / "no data yet" hint. `scanning` is
28
+ * for live-discovery states (e.g. probing connections) where the dot
29
+ * pulses in the accent color so a glance down the rail reads as
30
+ * "actively working". */
31
+ variant?: 'idle' | 'scanning' | undefined;
32
+ }): React.ReactElement;
11
33
  export declare function SidebarWorklistRow({ icon, iconColor, label, labelColor, innerWidth, dim, strikethrough, }: {
12
34
  icon: string;
13
35
  iconColor: string;
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
  import type { FleetEntry } from '../app-state.js';
3
- import type { WorktreeRow } from '../ui-contracts.js';
3
+ import { type WorktreeRow } from '../ui-contracts.js';
4
4
  import type { ProjectPickerItem } from './project-picker.js';
5
5
  export interface ProjectPickerSidebarProps {
6
6
  items: readonly ProjectPickerItem[];
@@ -1,4 +1,4 @@
1
- export { fleetStatusVisual, fmtRelative, fmtShortDuration, liveSessionColor, liveSessionGlyph, SidebarWorklistRow, } from './sidebar-panels-shared.js';
2
- export { type AgentsPanelSidebarProps, AgentsPanelSidebar, type ConnectionsPanelSidebarProps, ConnectionsPanelSidebar, type CoordinatorPanelSidebarProps, CoordinatorPanelSidebar, type FleetPanelSidebarProps, FleetPanelSidebar, type ProjectPickerSidebarProps, ProjectPickerSidebar, type WorktreePanelSidebarProps, WorktreePanelSidebar, } from './sidebar-panels-workspace.js';
3
- export { type GoalPanelSidebarProps, GoalPanelSidebar, type KanbanPanelSidebarProps, KanbanPanelSidebar, type PlanPanelSidebarProps, PlanPanelSidebar, type ProcessListPanelSidebarProps, ProcessListPanelSidebar, type QueuePanelSidebarProps, QueuePanelSidebar, type SessionsPanelSidebarProps, SessionsPanelSidebar, type TodosPanelSidebarProps, TodosPanelSidebar, } from './sidebar-panels-task.js';
1
+ export { EmptyState, fleetStatusVisual, fmtRelative, fmtShortDuration, liveSessionColor, liveSessionGlyph, SidebarWorklistRow, } from './sidebar-panels-shared.js';
2
+ export { GoalPanelSidebar, type GoalPanelSidebarProps, KanbanPanelSidebar, type KanbanPanelSidebarProps, PlanPanelSidebar, type PlanPanelSidebarProps, ProcessListPanelSidebar, type ProcessListPanelSidebarProps, QueuePanelSidebar, type QueuePanelSidebarProps, SessionsPanelSidebar, type SessionsPanelSidebarProps, TodosPanelSidebar, type TodosPanelSidebarProps, } from './sidebar-panels-task.js';
3
+ export { AgentsPanelSidebar, type AgentsPanelSidebarProps, ConnectionsPanelSidebar, type ConnectionsPanelSidebarProps, CoordinatorPanelSidebar, type CoordinatorPanelSidebarProps, FleetPanelSidebar, type FleetPanelSidebarProps, ProjectPickerSidebar, type ProjectPickerSidebarProps, WorktreePanelSidebar, type WorktreePanelSidebarProps, } from './sidebar-panels-workspace.js';
4
4
  //# sourceMappingURL=sidebar-panels.d.ts.map
@@ -45,5 +45,5 @@ export interface RightSidebarProps {
45
45
  */
46
46
  children?: React.ReactNode | undefined;
47
47
  }
48
- export declare function RightSidebar({ width, maxHeight, focused, children }: RightSidebarProps): React.ReactElement | null;
48
+ export declare function RightSidebar({ width, maxHeight, focused, children, }: RightSidebarProps): React.ReactElement | null;
49
49
  //# sourceMappingURL=sidebar.d.ts.map