gloomberb 0.9.3 → 0.9.5

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 (176) hide show
  1. package/README.md +1 -0
  2. package/package.json +3 -2
  3. package/patches/@opentui%2Fcore@0.3.2.patch +231 -29
  4. package/patches/react-reconciler@0.33.0.patch +10 -0
  5. package/src/app/runtime/desktop-menu.ts +5 -1
  6. package/src/app/runtime/ticker-refresh.ts +4 -1
  7. package/src/app.tsx +10 -1
  8. package/src/brokers/account-cache.ts +1 -1
  9. package/src/brokers/sync-broker-instance.test.ts +107 -0
  10. package/src/brokers/sync-broker-instance.ts +22 -10
  11. package/src/cli/desktop-pane-shot.ts +2 -1
  12. package/src/cli/entry.ts +8 -1
  13. package/src/cli/native-smoke.ts +5 -0
  14. package/src/cli/pane-functions/screenshot.ts +13 -1
  15. package/src/components/chart/bar-chart-renderer.test.ts +108 -3
  16. package/src/components/chart/bar-chart-renderer.ts +226 -27
  17. package/src/components/chart/core/pointer.ts +32 -6
  18. package/src/components/chart/native/bitmap-support.test.ts +27 -0
  19. package/src/components/chart/native/bitmap-support.ts +55 -0
  20. package/src/components/chart/native/kitty/index.test.ts +47 -0
  21. package/src/components/chart/native/surface/visibility.ts +8 -1
  22. package/src/components/chart/price-axis-labels.tsx +3 -1
  23. package/src/components/chart/static/bar-chart-surface.test.tsx +97 -0
  24. package/src/components/chart/static/bar-chart-surface.tsx +151 -28
  25. package/src/components/chart/static/chart/axis-overlays.tsx +243 -0
  26. package/src/components/chart/static/chart/bitmap.ts +16 -9
  27. package/src/components/chart/static/chart/surface.test.tsx +92 -0
  28. package/src/components/chart/static/chart/surface.tsx +167 -24
  29. package/src/components/chart/stock-chart/index.test.ts +25 -0
  30. package/src/components/command-bar/layout-items/current-layout.ts +5 -1
  31. package/src/components/command-bar/list/view.tsx +1 -1
  32. package/src/components/command-bar/theme-picker.tsx +1 -1
  33. package/src/components/data-table/view.tsx +0 -12
  34. package/src/components/layout/detached-pane-shell.tsx +6 -3
  35. package/src/components/layout/floating-pane.tsx +6 -5
  36. package/src/components/layout/pane/content.tsx +20 -8
  37. package/src/components/layout/pane/footer/registration.tsx +6 -2
  38. package/src/components/layout/pane/frame.tsx +4 -4
  39. package/src/components/layout/pane/header.tsx +45 -4
  40. package/src/components/layout/pane/index.tsx +6 -4
  41. package/src/components/layout/pane/sizing.test.ts +43 -0
  42. package/src/components/layout/pane/sizing.ts +13 -4
  43. package/src/components/layout/shell/action-menu-overlay.tsx +1 -1
  44. package/src/components/layout/shell/cursor-occlusion.ts +204 -0
  45. package/src/components/layout/shell/drag/runtime.ts +9 -2
  46. package/src/components/layout/shell/index.test.tsx +92 -2
  47. package/src/components/layout/shell/index.tsx +45 -3
  48. package/src/components/layout/shell/layout-state.test.ts +33 -0
  49. package/src/components/layout/shell/layout-state.ts +4 -9
  50. package/src/components/layout/shell/pane/layers.tsx +10 -4
  51. package/src/components/layout/shell/visible-layout.ts +17 -0
  52. package/src/components/layout/status-bar.test.tsx +6 -1
  53. package/src/components/layout/status-bar.tsx +10 -6
  54. package/src/components/onboarding/onboarding-steps.tsx +8 -28
  55. package/src/components/onboarding/onboarding-wizard.test.tsx +13 -12
  56. package/src/components/onboarding/onboarding-wizard.tsx +2 -4
  57. package/src/components/onboarding/portfolio-step/index.tsx +0 -12
  58. package/src/components/onboarding/portfolio-step/types.ts +1 -3
  59. package/src/components/onboarding/wizard-keyboard.ts +2 -5
  60. package/src/components/pane-settings-dialog/desktop.tsx +1 -1
  61. package/src/components/price-performance.tsx +1 -1
  62. package/src/components/price-sparkline/view.tsx +15 -14
  63. package/src/components/speedometer-gauge/terminal.tsx +18 -15
  64. package/src/components/table-view-shared.tsx +12 -14
  65. package/src/components/ticker/list-table-view.tsx +1 -7
  66. package/src/components/ticker/list-table.test.tsx +0 -4
  67. package/src/components/ui/data-table/opentui/index.tsx +29 -22
  68. package/src/components/ui/data-table/types.ts +10 -4
  69. package/src/components/ui/fields.tsx +10 -3
  70. package/src/components/ui/list-view.tsx +1 -1
  71. package/src/components/ui/page-stack-view.tsx +6 -2
  72. package/src/components/ui/table-layout.test.ts +25 -0
  73. package/src/components/ui/table-layout.ts +22 -6
  74. package/src/components/ui/tabs.tsx +27 -12
  75. package/src/components/ui/ui.test.tsx +87 -9
  76. package/src/core/state/app/layout-reducer.ts +2 -2
  77. package/src/plugins/builtin/account-management/form-components.tsx +2 -2
  78. package/src/plugins/builtin/alerts/pane.tsx +1 -1
  79. package/src/plugins/builtin/analytics/index.test.tsx +6 -2
  80. package/src/plugins/builtin/analytics/pane-model.ts +43 -8
  81. package/src/plugins/builtin/buildout/cells.tsx +1 -1
  82. package/src/plugins/builtin/buildout/pane/index.tsx +1 -1
  83. package/src/plugins/builtin/chat/message/desktop.tsx +1 -1
  84. package/src/plugins/builtin/chat/message/inline-tokens.tsx +1 -1
  85. package/src/plugins/builtin/chat/message/terminal.tsx +2 -2
  86. package/src/plugins/builtin/chat/sidebar.tsx +1 -1
  87. package/src/plugins/builtin/chat/status-widget.tsx +1 -1
  88. package/src/plugins/builtin/cloud/auth-actions.tsx +2 -2
  89. package/src/plugins/builtin/correlation/matrix/symbol-cell.tsx +1 -1
  90. package/src/plugins/builtin/debug/index.tsx +3 -4
  91. package/src/plugins/builtin/help/components.tsx +1 -1
  92. package/src/plugins/builtin/holders/treemap.tsx +1 -1
  93. package/src/plugins/builtin/kelly-sizer/constants.ts +3 -0
  94. package/src/plugins/builtin/kelly-sizer/fields.ts +214 -0
  95. package/src/plugins/builtin/kelly-sizer/index.test.tsx +197 -0
  96. package/src/plugins/builtin/kelly-sizer/index.tsx +47 -0
  97. package/src/plugins/builtin/kelly-sizer/model.test.ts +152 -0
  98. package/src/plugins/builtin/kelly-sizer/model.ts +580 -0
  99. package/src/plugins/builtin/kelly-sizer/pane.tsx +558 -0
  100. package/src/plugins/builtin/kelly-sizer/portfolio.ts +71 -0
  101. package/src/plugins/builtin/kelly-sizer/sections.tsx +142 -0
  102. package/src/plugins/builtin/kelly-sizer/state.ts +67 -0
  103. package/src/plugins/builtin/kelly-sizer/test-support.tsx +174 -0
  104. package/src/plugins/builtin/kelly-sizer/types.ts +156 -0
  105. package/src/plugins/builtin/kelly-sizer/view.test.tsx +77 -0
  106. package/src/plugins/builtin/kelly-sizer/view.tsx +375 -0
  107. package/src/plugins/builtin/layout-manager/index.tsx +5 -1
  108. package/src/plugins/builtin/options/table.ts +5 -5
  109. package/src/plugins/builtin/options/view.test.tsx +141 -4
  110. package/src/plugins/builtin/options/view.tsx +76 -15
  111. package/src/plugins/builtin/portfolio-list/account-metrics.test.ts +26 -1
  112. package/src/plugins/builtin/portfolio-list/account-metrics.ts +14 -0
  113. package/src/plugins/builtin/portfolio-list/index.test.ts +23 -0
  114. package/src/plugins/builtin/portfolio-list/pane/index.tsx +2 -0
  115. package/src/plugins/builtin/portfolio-list/summary/index.test.ts +59 -1
  116. package/src/plugins/builtin/portfolio-list/summary/index.tsx +36 -5
  117. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/content.tsx +149 -48
  118. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/model.ts +25 -2
  119. package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph.tsx +5 -4
  120. package/src/plugins/builtin/ticker-detail/data-panes.test.ts +16 -0
  121. package/src/plugins/builtin/ticker-detail/index.test.tsx +143 -0
  122. package/src/plugins/catalog-ui.ts +2 -0
  123. package/src/plugins/ibkr/broker-adapter.ts +19 -0
  124. package/src/plugins/ibkr/config.test.ts +31 -2
  125. package/src/plugins/ibkr/config.ts +9 -2
  126. package/src/plugins/ibkr/flex/index.test.ts +18 -9
  127. package/src/plugins/ibkr/flex/index.ts +30 -0
  128. package/src/plugins/ibkr/flex/statement-client.ts +68 -14
  129. package/src/plugins/ibkr/gateway/account-loaders.ts +1 -1
  130. package/src/plugins/ibkr/gateway/account-summary.ts +1 -0
  131. package/src/plugins/ibkr/gateway/service/index.test.ts +8 -0
  132. package/src/plugins/ibkr/trade/ticket-panel.tsx +1 -1
  133. package/src/plugins/pane-manager/gridlock.ts +13 -5
  134. package/src/plugins/pane-manager/layout-state.ts +25 -0
  135. package/src/plugins/pane-manager.test.ts +33 -0
  136. package/src/plugins/pane-manager.ts +6 -1
  137. package/src/plugins/prediction-markets/chart.tsx +10 -4
  138. package/src/plugins/prediction-markets/detail/book.tsx +141 -96
  139. package/src/plugins/prediction-markets/detail/overview.tsx +3 -0
  140. package/src/plugins/prediction-markets/detail/pane.tsx +71 -64
  141. package/src/plugins/prediction-markets/detail/shared.tsx +19 -0
  142. package/src/plugins/prediction-markets/detail/trades.tsx +64 -19
  143. package/src/plugins/prediction-markets/detail.test.tsx +50 -0
  144. package/src/plugins/prediction-markets/pane.test.tsx +43 -0
  145. package/src/plugins/prediction-markets/pane.tsx +50 -22
  146. package/src/plugins/prediction-markets/test-helpers.tsx +41 -23
  147. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +13 -2
  148. package/src/renderers/electrobun/view/data-table/index.tsx +19 -12
  149. package/src/renderers/electrobun/view/data-table/row.tsx +32 -18
  150. package/src/renderers/electrobun/view/desktop/controls.tsx +11 -5
  151. package/src/renderers/electrobun/view/host/box.tsx +6 -1
  152. package/src/renderers/electrobun/view/host/input.tsx +115 -18
  153. package/src/renderers/electrobun/view/host/style.ts +1 -0
  154. package/src/renderers/electrobun/view/host/tabs.tsx +7 -2
  155. package/src/renderers/electrobun/view/styles.css +18 -0
  156. package/src/renderers/opentui/host.tsx +17 -1
  157. package/src/renderers/opentui/native-smoke.ts +1 -0
  158. package/src/renderers/opentui/ui-host.tsx +57 -25
  159. package/src/sources/provider-router/batches.ts +16 -2
  160. package/src/sources/provider-router/financial-routes.ts +5 -0
  161. package/src/sources/provider-router/financials.ts +11 -23
  162. package/src/sources/provider-router/index.test.ts +189 -0
  163. package/src/sources/provider-router/primary.ts +3 -2
  164. package/src/sources/sec-edgar.test.ts +83 -0
  165. package/src/sources/sec-edgar.ts +231 -0
  166. package/src/sources/yahoo-finance.test.ts +51 -0
  167. package/src/sources/yahoo-finance.ts +49 -1
  168. package/src/state/app/context/index.test.tsx +5 -8
  169. package/src/types/broker.ts +1 -0
  170. package/src/types/config.ts +10 -0
  171. package/src/types/trading.ts +2 -0
  172. package/src/ui/host.tsx +16 -0
  173. package/src/ui/index.tsx +2 -0
  174. package/src/utils/financial-statements.ts +23 -0
  175. package/src/version.ts +1 -1
  176. package/src/components/onboarding/portfolio-step/manual-name-panel.tsx +0 -62
@@ -17,6 +17,7 @@ describe("YahooFinanceClient exchange aliases", () => {
17
17
  provider.fetchAssetProfile = async () => undefined;
18
18
  provider.fetchQuoteSupplement = async () => ({});
19
19
  provider.fetchExtendedHoursData = async () => ({});
20
+ provider.secClient.getFinancialStatements = async () => null;
20
21
  provider.fetchTimeseries = async () => [
21
22
  point("annualAccountsReceivable", 7_450_000_000),
22
23
  point("annualInventory", 4_880_000_000),
@@ -52,6 +53,56 @@ describe("YahooFinanceClient exchange aliases", () => {
52
53
  });
53
54
  });
54
55
 
56
+ test("supplements US Yahoo financials with deeper SEC statement history", async () => {
57
+ const provider = new YahooFinanceClient() as any;
58
+ const point = (type: string, date: string, value: number) => ({
59
+ meta: { type: [type] },
60
+ [type]: [{ asOfDate: date, reportedValue: { raw: value } }],
61
+ });
62
+
63
+ provider.fetchChart = async () => ({
64
+ meta: { currency: "USD", regularMarketPrice: 100, shortName: "AMD" },
65
+ history: [{ date: new Date("2025-12-31T00:00:00Z"), close: 100 }],
66
+ });
67
+ provider.fetchAssetProfile = async () => undefined;
68
+ provider.fetchQuoteSupplement = async () => ({});
69
+ provider.fetchExtendedHoursData = async () => ({});
70
+ provider.fetchTimeseries = async () => [
71
+ point("annualTotalRevenue", "2025-12-31", 200),
72
+ point("quarterlyTotalRevenue", "2025-12-31", 60),
73
+ ];
74
+ provider.secClient.getFinancialStatements = async (ticker: string) => {
75
+ expect(ticker).toBe("AMD");
76
+ return {
77
+ annualStatements: [
78
+ { date: "2023-12-31", totalRevenue: 100 },
79
+ { date: "2024-12-31", totalRevenue: 150 },
80
+ { date: "2025-12-31", totalRevenue: 190, netIncome: 40 },
81
+ ],
82
+ quarterlyStatements: [
83
+ { date: "2025-03-31", totalRevenue: 45 },
84
+ { date: "2025-06-30", totalRevenue: 50 },
85
+ { date: "2025-09-30", totalRevenue: 55 },
86
+ { date: "2025-12-31", totalRevenue: 58, netIncome: 12 },
87
+ ],
88
+ };
89
+ };
90
+
91
+ const financials = await provider.getTickerFinancials("AMD", "NASDAQ");
92
+
93
+ expect(financials.annualStatements.map((row: any) => [row.date, row.totalRevenue, row.netIncome])).toEqual([
94
+ ["2023-12-31", 100, undefined],
95
+ ["2024-12-31", 150, undefined],
96
+ ["2025-12-31", 200, 40],
97
+ ]);
98
+ expect(financials.quarterlyStatements.map((row: any) => [row.date, row.totalRevenue, row.netIncome])).toEqual([
99
+ ["2025-03-31", 45, undefined],
100
+ ["2025-06-30", 50, undefined],
101
+ ["2025-09-30", 55, undefined],
102
+ ["2025-12-31", 60, 12],
103
+ ]);
104
+ });
105
+
55
106
  test("tries the Taipei Exchange suffix for TPEX tickers", () => {
56
107
  expect(getYahooSymbolsToTry("3105", "TPEX")).toEqual(["3105.TWO", "3105.TW"]);
57
108
  });
@@ -8,6 +8,7 @@ import {
8
8
  import type { InstrumentSearchResult } from "../types/instrument";
9
9
  import { parseOptionSymbol } from "../utils/options";
10
10
  import { SecEdgarClient } from "./sec-edgar";
11
+ import { mergeFinancialStatementRows } from "../utils/financial-statements";
11
12
  import { YahooHttpClient } from "./yahoo-finance/http";
12
13
  import {
13
14
  normalizeSubUnitCurrency,
@@ -42,6 +43,21 @@ import {
42
43
  loadYahooTickerFinancials,
43
44
  } from "./yahoo-finance/snapshots";
44
45
 
46
+ const SEC_STATEMENT_SUPPLEMENT_EXCHANGES = new Set([
47
+ "",
48
+ "AMEX",
49
+ "ARCA",
50
+ "BATS",
51
+ "BYX",
52
+ "IEX",
53
+ "NASDAQ",
54
+ "NMS",
55
+ "NYSE",
56
+ "NYSEARCA",
57
+ "OTC",
58
+ "PINK",
59
+ ]);
60
+
45
61
  export class YahooFinanceClient implements DataProvider {
46
62
  readonly id = "yahoo";
47
63
  readonly name = "Yahoo Finance";
@@ -50,6 +66,38 @@ export class YahooFinanceClient implements DataProvider {
50
66
 
51
67
  constructor(private readonly http = new YahooHttpClient()) {}
52
68
 
69
+ private shouldSupplementSecStatements(ticker: string, exchange: string, financials: TickerFinancials): boolean {
70
+ if (!/^[A-Z0-9.-]+$/i.test(ticker.trim())) return false;
71
+ if (ticker.includes(".")) return false;
72
+ const normalizedExchange = exchange.trim().toUpperCase();
73
+ return SEC_STATEMENT_SUPPLEMENT_EXCHANGES.has(normalizedExchange)
74
+ && (financials.quote?.currency ?? "USD").toUpperCase() === "USD";
75
+ }
76
+
77
+ private async supplementSecStatements(
78
+ ticker: string,
79
+ exchange: string,
80
+ financials: TickerFinancials,
81
+ ): Promise<TickerFinancials> {
82
+ if (!this.shouldSupplementSecStatements(ticker, exchange, financials)) return financials;
83
+ try {
84
+ const secStatements = await this.secClient.getFinancialStatements(ticker);
85
+ if (
86
+ !secStatements
87
+ || (secStatements.annualStatements.length === 0 && secStatements.quarterlyStatements.length === 0)
88
+ ) {
89
+ return financials;
90
+ }
91
+ return {
92
+ ...financials,
93
+ annualStatements: mergeFinancialStatementRows(financials.annualStatements, secStatements.annualStatements),
94
+ quarterlyStatements: mergeFinancialStatementRows(financials.quarterlyStatements, secStatements.quarterlyStatements),
95
+ };
96
+ } catch {
97
+ return financials;
98
+ }
99
+ }
100
+
53
101
  private async fetchChart(symbol: string, range: string, interval = "1d", includePrePost = false) {
54
102
  return fetchYahooChart(this.http, symbol, range, interval, includePrePost);
55
103
  }
@@ -90,7 +138,7 @@ export class YahooFinanceClient implements DataProvider {
90
138
  fetchTimeseries: (targetSymbol, types, period1) => this.fetchTimeseries(targetSymbol, types, period1),
91
139
  providerId: this.id,
92
140
  });
93
- return result;
141
+ return await this.supplementSecStatements(ticker, exchange, result);
94
142
  } catch (err) {
95
143
  lastError = err;
96
144
  }
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { cloneLayout, createDefaultConfig } from "../../../types/config";
2
+ import { cloneLayout, createBlankLayout, createDefaultConfig } from "../../../types/config";
3
3
  import { appReducer, createInitialState } from "./index";
4
4
 
5
5
  describe("appReducer command bar state", () => {
@@ -150,11 +150,10 @@ describe("appReducer command bar state", () => {
150
150
 
151
151
  const noUndoOnFreshLayout = appReducer(state, { type: "UNDO_LAYOUT" });
152
152
  expect(noUndoOnFreshLayout.config.activeLayoutIndex).toBe(newLayoutIndex);
153
- expect(noUndoOnFreshLayout.config.layout.dockRoot && noUndoOnFreshLayout.config.layout.dockRoot.kind === "split"
154
- ? noUndoOnFreshLayout.config.layout.dockRoot.ratio
155
- : null).toBe(defaultRatio);
153
+ expect(noUndoOnFreshLayout.config.layout).toEqual(createBlankLayout());
154
+ expect(noUndoOnFreshLayout.focusedPaneId).toBeNull();
156
155
 
157
- const secondLayout = cloneLayout(noUndoOnFreshLayout.config.layout);
156
+ const secondLayout = cloneLayout(initial.config.layout);
158
157
  if (!secondLayout.dockRoot || secondLayout.dockRoot.kind !== "split") {
159
158
  throw new Error("expected split dock root");
160
159
  }
@@ -172,9 +171,7 @@ describe("appReducer command bar state", () => {
172
171
  const backToSecond = appReducer(firstUndone, { type: "SWITCH_LAYOUT", index: newLayoutIndex });
173
172
  const secondUndone = appReducer(backToSecond, { type: "UNDO_LAYOUT" });
174
173
  expect(secondUndone.config.activeLayoutIndex).toBe(newLayoutIndex);
175
- expect(secondUndone.config.layout.dockRoot && secondUndone.config.layout.dockRoot.kind === "split"
176
- ? secondUndone.config.layout.dockRoot.ratio
177
- : null).toBe(defaultRatio);
174
+ expect(secondUndone.config.layout).toEqual(createBlankLayout());
178
175
  });
179
176
 
180
177
  test("tracks manual update-check feedback", () => {
@@ -85,6 +85,7 @@ export interface BrokerAdapter {
85
85
  readonly cachePolicy?: CachePolicyMap;
86
86
  validate(instance: BrokerInstanceConfig): Promise<boolean>;
87
87
  importPositions(instance: BrokerInstanceConfig): Promise<BrokerPosition[]>;
88
+ importPortfolioSnapshot?(instance: BrokerInstanceConfig): Promise<{ accounts: BrokerAccount[]; positions: BrokerPosition[] }>;
88
89
  configSchema: BrokerConfigField[];
89
90
  connect?(instance: BrokerInstanceConfig): Promise<void>;
90
91
  disconnect?(instance: BrokerInstanceConfig): Promise<void>;
@@ -309,6 +309,12 @@ const DEFAULT_MONITOR_LAYOUT: LayoutConfig = {
309
309
  };
310
310
 
311
311
  export const DEFAULT_LAYOUT = DEFAULT_HOME_LAYOUT;
312
+ const BLANK_LAYOUT: LayoutConfig = {
313
+ dockRoot: null,
314
+ instances: [],
315
+ floating: [],
316
+ detached: [],
317
+ };
312
318
 
313
319
  let nextPaneInstanceSeq = 0;
314
320
 
@@ -594,6 +600,10 @@ export function cloneLayout(layout: LayoutConfig): LayoutConfig {
594
600
  };
595
601
  }
596
602
 
603
+ export function createBlankLayout(): LayoutConfig {
604
+ return cloneLayout(BLANK_LAYOUT);
605
+ }
606
+
597
607
  export function findPaneInstance(layout: LayoutConfig, instanceId: string): PaneInstanceConfig | undefined {
598
608
  return layout.instances.find((instance) => instance.instanceId === instanceId);
599
609
  }
@@ -16,7 +16,9 @@ export interface BrokerAccount {
16
16
  currency?: string;
17
17
  source?: "gateway" | "flex";
18
18
  updatedAt?: number;
19
+ asOfDate?: string;
19
20
  netLiquidation?: number;
21
+ grossPositionValue?: number;
20
22
  totalCashValue?: number;
21
23
  settledCash?: number;
22
24
  buyingPower?: number;
package/src/ui/host.tsx CHANGED
@@ -143,12 +143,22 @@ export interface TextareaRenderable extends InputRenderable {
143
143
  clearLineHighlights?(lineIdx: number): void;
144
144
  }
145
145
 
146
+ export interface NativeCursorState {
147
+ x: number;
148
+ y: number;
149
+ visible: boolean;
150
+ }
151
+
152
+ export type NativePostProcessFn = (buffer: unknown, deltaTime: number) => void;
153
+
146
154
  export interface NativeRendererHost {
147
155
  terminalWidth: number;
148
156
  terminalHeight: number;
149
157
  resolution: PixelResolution | null;
150
158
  capabilities?: unknown;
151
159
  isDestroyed?: boolean;
160
+ currentFocusedRenderable?: unknown;
161
+ currentFocusedEditor?: unknown;
152
162
  keyInput?: {
153
163
  on(event: string, handler: (...args: any[]) => void): void;
154
164
  off(event: string, handler: (...args: any[]) => void): void;
@@ -160,8 +170,13 @@ export interface NativeRendererHost {
160
170
  registerLifecyclePass(renderable: unknown): void;
161
171
  unregisterLifecyclePass(renderable: unknown): void;
162
172
  getSelection?(): { getSelectedText(): string } | null;
173
+ getCursorState?(): NativeCursorState;
174
+ setCursorPosition?(x: number, y: number, visible?: boolean): void;
175
+ addPostProcessFn?(processFn: NativePostProcessFn): void;
176
+ removePostProcessFn?(processFn: NativePostProcessFn): void;
163
177
  copyToClipboardOSC52?(text: string): boolean;
164
178
  write?(data: string | Uint8Array): boolean;
179
+ captureMouseRenderable?(renderable: unknown): void;
165
180
  }
166
181
 
167
182
  interface BoxProps {
@@ -244,6 +259,7 @@ export interface HostTabsProps {
244
259
  closeMode?: "active" | "always";
245
260
  addLabel?: string;
246
261
  onAdd?: () => void;
262
+ focused?: boolean;
247
263
  palette: HostTabsPalette;
248
264
  }
249
265
 
package/src/ui/index.tsx CHANGED
@@ -28,7 +28,9 @@ export type {
28
28
  Highlight,
29
29
  ImageSurfaceProps,
30
30
  InputRenderable,
31
+ NativeCursorState,
31
32
  NativeRendererHost,
33
+ NativePostProcessFn,
32
34
  PixelResolution,
33
35
  RendererHost,
34
36
  ScrollBoxRenderable,
@@ -0,0 +1,23 @@
1
+ import type { FinancialStatement } from "../types/financials";
2
+
3
+ export function mergeFinancialStatementRows(
4
+ primaryRows: FinancialStatement[],
5
+ fallbackRows: FinancialStatement[],
6
+ ): FinancialStatement[] {
7
+ if (primaryRows.length === 0) return fallbackRows;
8
+ if (fallbackRows.length === 0) return primaryRows;
9
+
10
+ const fallbackByDate = new Map(fallbackRows.map((row) => [row.date, row]));
11
+ const primaryDates = new Set(primaryRows.map((row) => row.date));
12
+ const mergedRows = primaryRows.map((row) => ({
13
+ ...fallbackByDate.get(row.date),
14
+ ...row,
15
+ date: row.date,
16
+ }));
17
+
18
+ for (const row of fallbackRows) {
19
+ if (!primaryDates.has(row.date)) mergedRows.push(row);
20
+ }
21
+
22
+ return mergedRows.sort((left, right) => left.date.localeCompare(right.date));
23
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.9.3";
1
+ export const VERSION = "0.9.5";
@@ -1,62 +0,0 @@
1
- import type { RefObject } from "react";
2
- import { Box, Text, TextAttributes, type InputRenderable } from "../../../ui";
3
- import { colors } from "../../../theme/colors";
4
- import { TextField } from "../../ui";
5
-
6
- export function ManualPortfolioNamePanel({
7
- portfolioName,
8
- onNameChange,
9
- editing,
10
- inputRef,
11
- }: {
12
- portfolioName: string;
13
- onNameChange: (name: string) => void;
14
- editing: boolean;
15
- inputRef: RefObject<InputRenderable | null>;
16
- }) {
17
- return (
18
- <Box flexDirection="column" paddingX={2}>
19
- <Box height={1}>
20
- <Text fg={colors.textBright} attributes={TextAttributes.BOLD}>{"Name your portfolio"}</Text>
21
- </Box>
22
- <Box height={1} />
23
- <Box height={1}>
24
- <Text fg={colors.textDim}>{"Create watchlists later."}</Text>
25
- </Box>
26
- <Box height={2} />
27
- <Box height={1}>
28
- <Text fg={colors.text}>{"Portfolio name:"}</Text>
29
- </Box>
30
- <Box height={1}>
31
- {editing ? (
32
- <TextField
33
- inputRef={inputRef}
34
- value={portfolioName}
35
- placeholder="Main Portfolio"
36
- focused
37
- backgroundColor={colors.panel}
38
- textColor={colors.text}
39
- placeholderColor={colors.textDim}
40
- onChange={onNameChange}
41
- onSubmit={() => {}}
42
- />
43
- ) : (
44
- <Text fg={colors.textBright} attributes={TextAttributes.BOLD}>
45
- {`> ${portfolioName}`}
46
- </Text>
47
- )}
48
- </Box>
49
- <Box height={2} />
50
- <Box height={1} flexDirection="row">
51
- <Text fg={colors.textDim}>{"After setup, use the command bar ("}</Text>
52
- <Text fg={colors.text}>{"Ctrl+P"}</Text>
53
- <Text fg={colors.textDim}>{") and"}</Text>
54
- </Box>
55
- <Box height={1} flexDirection="row">
56
- <Text fg={colors.textDim}>{"type "}</Text>
57
- <Text fg={colors.text} attributes={TextAttributes.BOLD}>{"DES AAPL"}</Text>
58
- <Text fg={colors.textDim}>{" to open security details for a stock or ETF."}</Text>
59
- </Box>
60
- </Box>
61
- );
62
- }