gloomberb 0.4.1 β†’ 0.5.1

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 (212) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/app.tsx +168 -65
  4. package/src/cli/commands/ticker.ts +45 -15
  5. package/src/cli/helpers.ts +4 -2
  6. package/src/cli/registry.test.ts +42 -35
  7. package/src/cli.test.ts +4 -2
  8. package/src/components/chart/chart-control-hint.tsx +39 -0
  9. package/src/components/chart/chart-controller.test.ts +110 -0
  10. package/src/components/chart/chart-controller.ts +364 -2
  11. package/src/components/chart/chart-data.ts +177 -29
  12. package/src/components/chart/chart-indicator-selector.tsx +53 -0
  13. package/src/components/chart/chart-pane-settings.ts +20 -0
  14. package/src/components/chart/chart-renderer.ts +220 -30
  15. package/src/components/chart/chart-resolution.test.ts +67 -0
  16. package/src/components/chart/chart-resolution.ts +74 -4
  17. package/src/components/chart/chart-scroll.test.ts +69 -0
  18. package/src/components/chart/chart-scroll.ts +104 -0
  19. package/src/components/chart/chart-types.ts +12 -0
  20. package/src/components/chart/chart-viewport.test.ts +5 -1
  21. package/src/components/chart/chart-viewport.ts +1 -1
  22. package/src/components/chart/chart.test.ts +249 -10
  23. package/src/components/chart/comparison-chart-renderer.test.ts +71 -1
  24. package/src/components/chart/comparison-chart-renderer.ts +40 -3
  25. package/src/components/chart/comparison-stock-chart.tsx +218 -123
  26. package/src/components/chart/indicators/bands.test.ts +50 -0
  27. package/src/components/chart/indicators/bands.ts +29 -0
  28. package/src/components/chart/indicators/moving-averages.test.ts +54 -0
  29. package/src/components/chart/indicators/moving-averages.ts +42 -0
  30. package/src/components/chart/indicators/options.test.ts +32 -0
  31. package/src/components/chart/indicators/options.ts +107 -0
  32. package/src/components/chart/indicators/oscillators.test.ts +79 -0
  33. package/src/components/chart/indicators/oscillators.ts +92 -0
  34. package/src/components/chart/indicators/types.ts +36 -0
  35. package/src/components/chart/native/chart-rasterizer.ts +51 -0
  36. package/src/components/chart/native/kitty.test.ts +68 -0
  37. package/src/components/chart/stock-chart-renderer-switch.test.tsx +740 -9
  38. package/src/components/chart/stock-chart.test.ts +239 -0
  39. package/src/components/chart/stock-chart.tsx +2257 -372
  40. package/src/components/command-bar/command-bar.test.tsx +337 -5
  41. package/src/components/command-bar/command-bar.tsx +292 -120
  42. package/src/components/command-bar/helpers.ts +1 -1
  43. package/src/components/command-bar/root-shortcuts.ts +33 -4
  44. package/src/components/command-bar/view-model.test.ts +3 -3
  45. package/src/components/command-bar/view-model.ts +4 -4
  46. package/src/components/command-bar/workflow-ops.ts +10 -0
  47. package/src/components/layout/floating-pane.tsx +3 -2
  48. package/src/components/layout/header.tsx +2 -1
  49. package/src/components/layout/pane-sizing.ts +10 -0
  50. package/src/components/layout/pane.tsx +9 -2
  51. package/src/components/layout/shell.test.tsx +282 -28
  52. package/src/components/layout/shell.tsx +10 -7
  53. package/src/components/layout/status-bar.test.tsx +16 -7
  54. package/src/components/layout/status-bar.tsx +4 -1
  55. package/src/components/markdown-editor.tsx +1 -0
  56. package/src/components/pane-settings-dialog.tsx +13 -152
  57. package/src/components/pane-template-wizard.tsx +1 -0
  58. package/src/components/price-selector-dialog.tsx +12 -7
  59. package/src/components/ticker-badge-text.test.tsx +50 -0
  60. package/src/components/ticker-badge-text.tsx +17 -2
  61. package/src/components/ticker-badge.tsx +2 -2
  62. package/src/components/ticker-list-table.tsx +54 -1
  63. package/src/components/toggle-list.tsx +15 -2
  64. package/src/components/ui/data-table.tsx +60 -3
  65. package/src/components/ui/external-link.tsx +48 -11
  66. package/src/components/ui/fields.tsx +2 -1
  67. package/src/components/ui/index.ts +8 -1
  68. package/src/components/ui/multi-select-chips.tsx +69 -0
  69. package/src/components/ui/multi-select-dialog.tsx +267 -0
  70. package/src/components/ui/multi-select.ts +78 -0
  71. package/src/components/ui/ui.test.tsx +343 -1
  72. package/src/data/plugin-state-store.ts +30 -19
  73. package/src/data/resource-store.ts +133 -103
  74. package/src/data/session-store.ts +19 -12
  75. package/src/data/sqlite-cache.test.ts +37 -2
  76. package/src/data/sqlite-database.ts +8 -2
  77. package/src/data/sqlite-retry.test.ts +63 -0
  78. package/src/data/sqlite-retry.ts +66 -0
  79. package/src/data/ticker-store.ts +29 -18
  80. package/src/index.tsx +6 -1
  81. package/src/market-data/coordinator.test.ts +114 -5
  82. package/src/market-data/coordinator.ts +70 -1
  83. package/src/market-data/hooks.test.tsx +73 -2
  84. package/src/market-data/hooks.tsx +16 -4
  85. package/src/notifications/app-notifier.test.ts +177 -0
  86. package/src/notifications/app-notifier.ts +241 -0
  87. package/src/pane-settings.test.ts +2 -0
  88. package/src/plugins/builtin/ai/index.test.tsx +1 -1
  89. package/src/plugins/builtin/ai/screener-pane.test.tsx +2 -0
  90. package/src/plugins/builtin/ai/screener-pane.tsx +1 -0
  91. package/src/plugins/builtin/ai/ticker-context.ts +3 -2
  92. package/src/plugins/builtin/alerts/alert-engine.test.ts +90 -0
  93. package/src/plugins/builtin/alerts/alert-engine.ts +55 -0
  94. package/src/plugins/builtin/alerts/index.test.tsx +357 -0
  95. package/src/plugins/builtin/alerts/index.tsx +519 -0
  96. package/src/plugins/builtin/alerts/types.ts +14 -0
  97. package/src/plugins/builtin/analytics/index.test.tsx +300 -0
  98. package/src/plugins/builtin/analytics/index.tsx +775 -0
  99. package/src/plugins/builtin/analytics/metrics.test.ts +125 -0
  100. package/src/plugins/builtin/analytics/metrics.ts +155 -0
  101. package/src/plugins/builtin/ask-ai.test.tsx +2 -0
  102. package/src/plugins/builtin/chat-controller.test.ts +83 -18
  103. package/src/plugins/builtin/chat-controller.ts +26 -14
  104. package/src/plugins/builtin/chat.test.tsx +715 -4
  105. package/src/plugins/builtin/chat.tsx +424 -120
  106. package/src/plugins/builtin/comparison-chart.test.tsx +97 -57
  107. package/src/plugins/builtin/comparison-chart.tsx +1 -2
  108. package/src/plugins/builtin/correlation/compute.test.ts +147 -0
  109. package/src/plugins/builtin/correlation/compute.ts +115 -0
  110. package/src/plugins/builtin/correlation/index.tsx +385 -0
  111. package/src/plugins/builtin/correlation/plugin.test.ts +44 -0
  112. package/src/plugins/builtin/correlation/settings.test.ts +34 -0
  113. package/src/plugins/builtin/correlation/settings.ts +95 -0
  114. package/src/plugins/builtin/debug.tsx +36 -50
  115. package/src/plugins/builtin/earnings/earnings-cache.test.ts +181 -0
  116. package/src/plugins/builtin/earnings/earnings-cache.ts +136 -0
  117. package/src/plugins/builtin/earnings/earnings-data.test.ts +59 -0
  118. package/src/plugins/builtin/earnings/earnings-data.ts +50 -0
  119. package/src/plugins/builtin/earnings/index.tsx +337 -0
  120. package/src/plugins/builtin/econ/calendar-source.test.ts +219 -0
  121. package/src/plugins/builtin/econ/calendar-source.ts +121 -0
  122. package/src/plugins/builtin/econ/fred-client.test.ts +63 -0
  123. package/src/plugins/builtin/econ/fred-client.ts +79 -0
  124. package/src/plugins/builtin/econ/fred-series-map.ts +88 -0
  125. package/src/plugins/builtin/econ/index.tsx +999 -0
  126. package/src/plugins/builtin/econ/types.ts +13 -0
  127. package/src/plugins/builtin/fred-settings.ts +10 -0
  128. package/src/plugins/builtin/fx-matrix/index.tsx +178 -0
  129. package/src/plugins/builtin/fx-matrix/pairs.ts +30 -0
  130. package/src/plugins/builtin/help.test.tsx +1 -5
  131. package/src/plugins/builtin/help.tsx +1 -16
  132. package/src/plugins/builtin/insider/index.tsx +417 -0
  133. package/src/plugins/builtin/insider/insider-data.test.ts +55 -0
  134. package/src/plugins/builtin/insider/insider-data.ts +49 -0
  135. package/src/plugins/builtin/layout-manager.tsx +24 -16
  136. package/src/plugins/builtin/market-movers/index.tsx +573 -0
  137. package/src/plugins/builtin/market-movers/screener.test.ts +143 -0
  138. package/src/plugins/builtin/market-movers/screener.ts +105 -0
  139. package/src/plugins/builtin/options.tsx +4 -3
  140. package/src/plugins/builtin/portfolio-list/cli/commands.ts +11 -6
  141. package/src/plugins/builtin/portfolio-list/command-bar.ts +6 -3
  142. package/src/plugins/builtin/portfolio-list/header.tsx +3 -2
  143. package/src/plugins/builtin/portfolio-list/metrics.ts +22 -11
  144. package/src/plugins/builtin/portfolio-list/pane.tsx +3 -9
  145. package/src/plugins/builtin/portfolio-list/settings.ts +9 -0
  146. package/src/plugins/builtin/portfolio-list/table.tsx +3 -0
  147. package/src/plugins/builtin/portfolio-list.test.tsx +3 -1
  148. package/src/plugins/builtin/portfolio-metrics.test.ts +13 -1
  149. package/src/plugins/builtin/sec.tsx +114 -7
  150. package/src/plugins/builtin/sectors/index.tsx +359 -0
  151. package/src/plugins/builtin/sectors/sector-data.ts +18 -0
  152. package/src/plugins/builtin/ticker-detail/chart-tab.tsx +75 -13
  153. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +316 -80
  154. package/src/plugins/builtin/ticker-detail/quote-monitor.tsx +4 -6
  155. package/src/plugins/builtin/ticker-detail-chart-tab-switch.test.tsx +17 -12
  156. package/src/plugins/builtin/ticker-detail.test.tsx +3 -3
  157. package/src/plugins/builtin/world-indices/index.tsx +410 -0
  158. package/src/plugins/builtin/world-indices/indices.ts +52 -0
  159. package/src/plugins/builtin/yield-curve/index.tsx +242 -0
  160. package/src/plugins/builtin/yield-curve/treasury-data.test.ts +212 -0
  161. package/src/plugins/builtin/yield-curve/treasury-data.ts +107 -0
  162. package/src/plugins/catalog.ts +22 -0
  163. package/src/plugins/gridlock-notification.ts +15 -0
  164. package/src/plugins/ibkr/__snapshots__/trade-tab.test.tsx.snap +5 -5
  165. package/src/plugins/ibkr/index.test.tsx +1 -1
  166. package/src/plugins/ibkr/index.tsx +1 -1
  167. package/src/plugins/ibkr/trade-tab.tsx +23 -5
  168. package/src/plugins/ibkr/trade-utils.test.ts +1 -1
  169. package/src/plugins/ibkr/trade-utils.ts +7 -6
  170. package/src/plugins/ibkr/trading-pane.tsx +8 -7
  171. package/src/plugins/plugin-runtime.test.tsx +2 -0
  172. package/src/plugins/plugin-runtime.tsx +10 -0
  173. package/src/plugins/prediction-markets/controller-data.ts +8 -0
  174. package/src/plugins/prediction-markets/detail/shared.tsx +7 -6
  175. package/src/plugins/prediction-markets/plugin.test.tsx +48 -1
  176. package/src/plugins/prediction-markets/services/fetch.ts +13 -7
  177. package/src/plugins/prediction-markets/services/polymarket-adapter.ts +29 -11
  178. package/src/plugins/prediction-markets/services/polymarket-ws.ts +20 -0
  179. package/src/plugins/prediction-markets/test-helpers.tsx +2 -0
  180. package/src/plugins/registry.ts +22 -13
  181. package/src/sources/provider-router.test.ts +3 -2
  182. package/src/sources/sec-edgar.ts +13 -1
  183. package/src/sources/yahoo-finance.ts +75 -1
  184. package/src/state/app-context-selector.test.tsx +17 -1
  185. package/src/state/app-context.test.tsx +24 -0
  186. package/src/state/app-context.tsx +29 -6
  187. package/src/theme/colors.ts +5 -0
  188. package/src/theme/themes.ts +25 -0
  189. package/src/types/config.test.ts +107 -0
  190. package/src/types/config.ts +30 -1
  191. package/src/types/data-provider.ts +13 -0
  192. package/src/types/plugin.ts +35 -1
  193. package/src/utils/api-client.test.ts +90 -0
  194. package/src/utils/api-client.ts +56 -16
  195. package/src/utils/format.test.ts +11 -1
  196. package/src/utils/format.ts +86 -8
  197. package/src/utils/inline-content-tokenizer.test.ts +22 -0
  198. package/src/utils/inline-content-tokenizer.ts +76 -0
  199. package/src/utils/link-tokenizer.test.ts +27 -0
  200. package/src/utils/link-tokenizer.ts +93 -0
  201. package/src/utils/market-format.test.ts +109 -0
  202. package/src/utils/market-format.ts +299 -0
  203. package/src/utils/market-status.ts +3 -2
  204. package/src/utils/selection-clipboard.test.ts +43 -0
  205. package/src/utils/selection-clipboard.ts +88 -0
  206. package/src/utils/terminal-input-reset.test.ts +50 -0
  207. package/src/utils/terminal-input-reset.ts +24 -0
  208. package/src/utils/throttled-fetch.test.ts +145 -0
  209. package/src/utils/throttled-fetch.ts +212 -0
  210. package/src/utils/ticker-tokenizer.test.ts +31 -0
  211. package/src/utils/ticker-tokenizer.ts +7 -42
  212. package/src/version.ts +1 -1
@@ -0,0 +1,13 @@
1
+ export type EconImpact = "high" | "medium" | "low";
2
+
3
+ export interface EconEvent {
4
+ id: string;
5
+ date: Date;
6
+ time: string; // "08:30" or "All Day"
7
+ country: string; // "US", "GB", etc.
8
+ event: string;
9
+ actual: string | null;
10
+ forecast: string | null;
11
+ prior: string | null;
12
+ impact: EconImpact;
13
+ }
@@ -0,0 +1,10 @@
1
+ import type { AppConfig } from "../../types/config";
2
+
3
+ export const FRED_API_KEY_CONFIG_PLUGIN_ID = "econ-calendar";
4
+ export const FRED_API_KEY_CONFIG_KEY = "fredApiKey";
5
+ export const FRED_API_KEY_COMMAND_LABEL = "Set FRED API Key";
6
+
7
+ export function getSharedFredApiKey(config: Pick<AppConfig, "pluginConfig">): string {
8
+ const value = config.pluginConfig?.[FRED_API_KEY_CONFIG_PLUGIN_ID]?.[FRED_API_KEY_CONFIG_KEY];
9
+ return typeof value === "string" ? value.trim() : "";
10
+ }
@@ -0,0 +1,178 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { TextAttributes } from "@opentui/core";
3
+ import { useKeyboard } from "@opentui/react";
4
+ import type { GloomPlugin, PaneProps } from "../../../types/plugin";
5
+ import { colors, blendHex } from "../../../theme/colors";
6
+ import { getSharedDataProvider } from "../../registry";
7
+ import { MAJOR_CURRENCIES, CURRENCY_FLAGS, formatRate, type MajorCurrency } from "./pairs";
8
+
9
+ const REFRESH_INTERVAL_MS = 60_000;
10
+
11
+ function formatAge(ms: number): string {
12
+ const secs = Math.floor(ms / 1000);
13
+ if (secs < 60) return `${secs}s ago`;
14
+ const mins = Math.floor(secs / 60);
15
+ if (mins < 60) return `${mins}m ago`;
16
+ return `${Math.floor(mins / 60)}h ago`;
17
+ }
18
+
19
+ export function FxMatrixPane({ focused, width, height }: PaneProps) {
20
+ const [rates, setRates] = useState<Map<MajorCurrency, number>>(new Map());
21
+ const [loading, setLoading] = useState(true);
22
+ const [lastRefreshed, setLastRefreshed] = useState<number | null>(null);
23
+ const [now, setNow] = useState(Date.now());
24
+ const fetchGenRef = useRef(0);
25
+
26
+ const fetchRates = async () => {
27
+ const provider = getSharedDataProvider();
28
+ if (!provider) return;
29
+
30
+ fetchGenRef.current += 1;
31
+ const gen = fetchGenRef.current;
32
+
33
+ try {
34
+ const results = await Promise.allSettled(
35
+ MAJOR_CURRENCIES.map(async (currency) => {
36
+ if (currency === "USD") return { currency, rate: 1 };
37
+ const rate = await provider.getExchangeRate(currency);
38
+ return { currency, rate };
39
+ }),
40
+ );
41
+
42
+ if (fetchGenRef.current !== gen) return;
43
+
44
+ const newRates = new Map<MajorCurrency, number>();
45
+ for (const result of results) {
46
+ if (result.status === "fulfilled") {
47
+ newRates.set(result.value.currency as MajorCurrency, result.value.rate);
48
+ }
49
+ }
50
+
51
+ setRates(newRates);
52
+ setLastRefreshed(Date.now());
53
+ } finally {
54
+ if (fetchGenRef.current === gen) setLoading(false);
55
+ }
56
+ };
57
+
58
+ useEffect(() => {
59
+ fetchRates();
60
+ const interval = setInterval(fetchRates, REFRESH_INTERVAL_MS);
61
+ return () => clearInterval(interval);
62
+ }, []);
63
+
64
+ useEffect(() => {
65
+ const interval = setInterval(() => setNow(Date.now()), 5_000);
66
+ return () => clearInterval(interval);
67
+ }, []);
68
+
69
+ useKeyboard((event) => {
70
+ if (!focused) return;
71
+ if (event.name === "r") {
72
+ fetchRates();
73
+ }
74
+ });
75
+
76
+ const headerBg = blendHex(colors.bg, colors.border, 0.3);
77
+
78
+ function crossRate(row: MajorCurrency, col: MajorCurrency): number | null {
79
+ if (row === col) return 1;
80
+ const rowUsd = rates.get(row);
81
+ const colUsd = rates.get(col);
82
+ if (rowUsd == null || colUsd == null) return null;
83
+ return rowUsd / colUsd;
84
+ }
85
+
86
+ const ageText = lastRefreshed ? `updated ${formatAge(now - lastRefreshed)}` : loading ? "loading…" : "";
87
+
88
+ // Row header: just the 3-letter code, no emoji (keeps width predictable)
89
+ // Rates use flexGrow so they fill available space dynamically
90
+
91
+ return (
92
+ <box flexDirection="column" width={width} height={height}>
93
+ {/* Header */}
94
+ <box flexDirection="row" height={1} paddingX={1}>
95
+ <text fg={colors.textMuted}>{ageText}</text>
96
+ </box>
97
+
98
+ {/* Column header row */}
99
+ <box flexDirection="row" paddingX={1} height={1} backgroundColor={headerBg}>
100
+ <box width={5} flexShrink={0} />
101
+ {MAJOR_CURRENCIES.map((col) => (
102
+ <box key={col} flexGrow={1} justifyContent="flex-end" paddingRight={1}>
103
+ <text fg={colors.textDim} attributes={TextAttributes.BOLD}>{col}</text>
104
+ </box>
105
+ ))}
106
+ </box>
107
+
108
+ {/* Matrix rows */}
109
+ <scrollbox flexGrow={1} scrollY focusable={false}>
110
+ <box flexDirection="column">
111
+ {loading && rates.size === 0 ? (
112
+ <box paddingX={1} paddingY={1}>
113
+ <text fg={colors.textMuted}>Fetching rates…</text>
114
+ </box>
115
+ ) : (
116
+ MAJOR_CURRENCIES.map((row) => (
117
+ <box key={row} flexDirection="row" paddingX={1}>
118
+ <box width={5} flexShrink={0}>
119
+ <text fg={colors.textBright} attributes={TextAttributes.BOLD}>{row}</text>
120
+ </box>
121
+ {MAJOR_CURRENCIES.map((col) => {
122
+ const rate = crossRate(row, col);
123
+ const isDiag = row === col;
124
+ return (
125
+ <box key={col} flexGrow={1} justifyContent="flex-end" paddingRight={1}>
126
+ {rate == null ? (
127
+ <text fg={colors.textDim}>β€”</text>
128
+ ) : (
129
+ <text fg={isDiag ? colors.textDim : colors.text}>
130
+ {formatRate(rate, col)}
131
+ </text>
132
+ )}
133
+ </box>
134
+ );
135
+ })}
136
+ </box>
137
+ ))
138
+ )}
139
+ </box>
140
+ </scrollbox>
141
+
142
+ <box height={1} paddingX={1}>
143
+ <text fg={colors.textMuted}>[r]efresh</text>
144
+ </box>
145
+ </box>
146
+ );
147
+ }
148
+
149
+ export const fxMatrixPlugin: GloomPlugin = {
150
+ id: "fx-matrix",
151
+ name: "FX Cross Rates",
152
+ version: "1.0.0",
153
+ description: "Currency cross-rate matrix for major FX pairs",
154
+ toggleable: true,
155
+
156
+ panes: [
157
+ {
158
+ id: "fx-matrix",
159
+ name: "FX Cross Rates",
160
+ icon: "F",
161
+ component: FxMatrixPane,
162
+ defaultPosition: "right",
163
+ defaultMode: "floating",
164
+ defaultFloatingSize: { width: 105, height: 14 },
165
+ },
166
+ ],
167
+
168
+ paneTemplates: [
169
+ {
170
+ id: "fx-matrix-pane",
171
+ paneId: "fx-matrix",
172
+ label: "FX Cross Rates",
173
+ description: "Currency cross-rate matrix for major FX pairs.",
174
+ keywords: ["fx", "forex", "currency", "exchange", "rates", "cross", "matrix"],
175
+ shortcut: { prefix: "FXC" },
176
+ },
177
+ ],
178
+ };
@@ -0,0 +1,30 @@
1
+ export const MAJOR_CURRENCIES = ["USD", "EUR", "GBP", "JPY", "CHF", "CAD", "AUD", "NZD"] as const;
2
+ export type MajorCurrency = typeof MAJOR_CURRENCIES[number];
3
+
4
+ export const CURRENCY_LABELS: Record<MajorCurrency, string> = {
5
+ USD: "US Dollar",
6
+ EUR: "Euro",
7
+ GBP: "British Pound",
8
+ JPY: "Japanese Yen",
9
+ CHF: "Swiss Franc",
10
+ CAD: "Canadian Dollar",
11
+ AUD: "Australian Dollar",
12
+ NZD: "New Zealand Dollar",
13
+ };
14
+
15
+ export const CURRENCY_FLAGS: Record<MajorCurrency, string> = {
16
+ USD: "πŸ‡ΊπŸ‡Έ",
17
+ EUR: "πŸ‡ͺπŸ‡Ί",
18
+ GBP: "πŸ‡¬πŸ‡§",
19
+ JPY: "πŸ‡―πŸ‡΅",
20
+ CHF: "πŸ‡¨πŸ‡­",
21
+ CAD: "πŸ‡¨πŸ‡¦",
22
+ AUD: "πŸ‡¦πŸ‡Ί",
23
+ NZD: "πŸ‡³πŸ‡Ώ",
24
+ };
25
+
26
+ /** Format rate with appropriate precision β€” JPY pairs get 2 decimals, others get 4 */
27
+ export function formatRate(rate: number, toCurrency: MajorCurrency): string {
28
+ const decimals = toCurrency === "JPY" ? 2 : 4;
29
+ return rate.toFixed(decimals);
30
+ }
@@ -69,7 +69,6 @@ describe("HelpPane", () => {
69
69
 
70
70
  test("opens the debug log from the mouse action", async () => {
71
71
  const calls: string[] = [];
72
- let closed = 0;
73
72
 
74
73
  setSharedRegistryForTests({
75
74
  showWidget: (paneId: string) => calls.push(`widget:${paneId}`),
@@ -83,9 +82,7 @@ describe("HelpPane", () => {
83
82
  focused
84
83
  width={88}
85
84
  height={36}
86
- close={() => {
87
- closed += 1;
88
- }}
85
+ close={() => {}}
89
86
  />,
90
87
  { width: 88, height: 36 },
91
88
  );
@@ -104,7 +101,6 @@ describe("HelpPane", () => {
104
101
  await testSetup!.renderOnce();
105
102
  });
106
103
 
107
- expect(closed).toBe(1);
108
104
  expect(calls).toEqual(["widget:debug"]);
109
105
  });
110
106
  });
@@ -1,5 +1,4 @@
1
1
  import { TextAttributes } from "@opentui/core";
2
- import { useKeyboard } from "@opentui/react";
3
2
  import { useState } from "react";
4
3
  import type { ReactNode } from "react";
5
4
  import type { GloomPlugin, PaneProps } from "../../types/plugin";
@@ -107,31 +106,21 @@ function resolveWindowTemplates(registry: ReturnType<typeof getSharedRegistry>)
107
106
  ));
108
107
  }
109
108
 
110
- export function HelpPane({ focused, width, height, close }: PaneProps) {
109
+ export function HelpPane({ width, height }: PaneProps) {
111
110
  const registry = getSharedRegistry();
112
111
  const compact = width < 78;
113
112
  const [hoveredAction, setHoveredAction] = useState<string | null>(null);
114
113
  const windowTemplates = resolveWindowTemplates(registry);
115
114
 
116
- useKeyboard((event) => {
117
- if (!focused) return;
118
- if (event.name === "escape") {
119
- close?.();
120
- }
121
- });
122
-
123
115
  const openDebugLog = () => {
124
- close?.();
125
116
  registry?.showWidget("debug");
126
117
  };
127
118
 
128
119
  const openLayoutActions = () => {
129
- close?.();
130
120
  registry?.openCommandBarFn("LAY ");
131
121
  };
132
122
 
133
123
  const openPluginManager = () => {
134
- close?.();
135
124
  registry?.openCommandBarFn("PL ");
136
125
  };
137
126
 
@@ -253,10 +242,6 @@ export function HelpPane({ focused, width, height, close }: PaneProps) {
253
242
  </HelpSection>
254
243
  </box>
255
244
  </scrollbox>
256
-
257
- <box height={1} paddingX={1}>
258
- <text fg={colors.textMuted}>Esc closes this window. Ctrl+W closes the focused pane.</text>
259
- </box>
260
245
  </box>
261
246
  );
262
247
  }