gloomberb 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (500) hide show
  1. package/README.md +91 -11
  2. package/package.json +12 -5
  3. package/src/app.tsx +414 -191
  4. package/src/architecture/import-boundaries.test.ts +118 -0
  5. package/src/assets/gloomberb-logo.png +0 -0
  6. package/src/assets/gloomberb-logo.svg +73 -0
  7. package/src/brokers/account-cache.ts +157 -0
  8. package/src/brokers/profile-form.test.ts +73 -0
  9. package/src/brokers/profile-form.ts +109 -0
  10. package/src/brokers/remote-broker-adapter.ts +91 -0
  11. package/src/brokers/sync-broker-instance.test.ts +124 -1
  12. package/src/brokers/sync-broker-instance.ts +113 -17
  13. package/src/capabilities/factories.ts +100 -0
  14. package/src/capabilities/index.ts +4 -0
  15. package/src/capabilities/registry.test.ts +137 -0
  16. package/src/capabilities/registry.ts +131 -0
  17. package/src/capabilities/service-capabilities.ts +27 -0
  18. package/src/capabilities/types.ts +84 -0
  19. package/src/cli/commands/ticker.ts +11 -3
  20. package/src/cli/context.ts +19 -13
  21. package/src/cli/helpers.ts +1 -0
  22. package/src/cli/types.ts +2 -2
  23. package/src/components/chart/chart-controller.ts +4 -24
  24. package/src/components/chart/chart-data.ts +3 -14
  25. package/src/components/chart/chart-indicator-selector.tsx +28 -6
  26. package/src/components/chart/chart-pane-settings.ts +15 -28
  27. package/src/components/chart/chart-renderer.ts +74 -99
  28. package/src/components/chart/chart-resolution.ts +10 -10
  29. package/src/components/chart/chart-scroll.test.ts +6 -5
  30. package/src/components/chart/chart-scroll.ts +2 -2
  31. package/src/components/chart/chart-types.ts +0 -1
  32. package/src/components/chart/chart-viewport.ts +2 -1
  33. package/src/components/chart/chart.test.ts +37 -0
  34. package/src/components/chart/comparison-chart-data.ts +3 -17
  35. package/src/components/chart/comparison-chart-renderer.test.ts +27 -4
  36. package/src/components/chart/comparison-chart-renderer.ts +1 -1
  37. package/src/components/chart/comparison-stock-chart.tsx +304 -108
  38. package/src/components/chart/cursor-motion.ts +3 -2
  39. package/src/components/chart/indicators/bands.test.ts +0 -14
  40. package/src/components/chart/indicators/moving-averages.test.ts +0 -15
  41. package/src/components/chart/indicators/options.ts +3 -3
  42. package/src/components/chart/indicators/oscillators.test.ts +0 -21
  43. package/src/components/chart/indicators/types.ts +1 -2
  44. package/src/components/chart/native/chart-rasterizer.ts +37 -44
  45. package/src/components/chart/native/kitty-adapter.ts +2 -5
  46. package/src/components/chart/native/kitty-manager.ts +1 -1
  47. package/src/components/chart/native/kitty-protocol.ts +0 -1
  48. package/src/components/chart/native/kitty-support.ts +1 -1
  49. package/src/components/chart/native/kitty.test.ts +30 -13
  50. package/src/components/chart/native/renderer-selection.ts +1 -1
  51. package/src/components/chart/native/surface-manager.ts +1 -1
  52. package/src/components/chart/static-chart-surface.test.tsx +51 -0
  53. package/src/components/chart/static-chart-surface.tsx +191 -0
  54. package/src/components/chart/stock-chart-renderer-switch.test.tsx +242 -35
  55. package/src/components/chart/stock-chart.tsx +438 -141
  56. package/src/components/command-bar/__snapshots__/command-bar.test.tsx.snap +4 -4
  57. package/src/components/command-bar/command-bar.test.tsx +269 -20
  58. package/src/components/command-bar/command-bar.tsx +830 -353
  59. package/src/components/command-bar/command-registry.ts +10 -20
  60. package/src/components/command-bar/helpers.test.ts +1 -1
  61. package/src/components/command-bar/helpers.ts +9 -11
  62. package/src/components/command-bar/pane-template-display.ts +4 -8
  63. package/src/components/command-bar/root-shortcuts.ts +12 -11
  64. package/src/components/command-bar/view-model.test.ts +8 -42
  65. package/src/components/command-bar/view-model.ts +8 -36
  66. package/src/components/command-bar/workflow-ops.test.ts +76 -2
  67. package/src/components/command-bar/workflow-ops.ts +40 -9
  68. package/src/components/command-bar/workflow-types.ts +2 -1
  69. package/src/components/data-table-stack-view.test.tsx +206 -0
  70. package/src/components/data-table-stack-view.tsx +152 -0
  71. package/src/components/data-table-view.test.tsx +188 -0
  72. package/src/components/data-table-view.tsx +279 -0
  73. package/src/components/feed-data-table-stack-view.test.tsx +225 -0
  74. package/src/components/feed-data-table-stack-view.tsx +365 -0
  75. package/src/components/index.ts +26 -31
  76. package/src/components/layout/detached-pane-shell.tsx +185 -0
  77. package/src/components/layout/floating-pane.tsx +87 -13
  78. package/src/components/layout/header.tsx +139 -49
  79. package/src/components/layout/pane-content.tsx +40 -0
  80. package/src/components/layout/pane-footer.test.tsx +195 -0
  81. package/src/components/layout/pane-footer.tsx +410 -0
  82. package/src/components/layout/pane-header.test.tsx +39 -0
  83. package/src/components/layout/pane-header.tsx +192 -14
  84. package/src/components/layout/pane-sizing.ts +13 -4
  85. package/src/components/layout/pane-title.ts +35 -0
  86. package/src/components/layout/pane.tsx +56 -8
  87. package/src/components/layout/shell.test.tsx +322 -19
  88. package/src/components/layout/shell.tsx +1010 -366
  89. package/src/components/layout/status-bar.test.tsx +17 -10
  90. package/src/components/layout/status-bar.tsx +367 -100
  91. package/src/components/layout/titlebar-overlay.ts +2 -0
  92. package/src/components/markdown-editor.tsx +29 -14
  93. package/src/components/markdown-text.tsx +25 -24
  94. package/src/components/onboarding/onboarding-wizard.test.tsx +8 -3
  95. package/src/components/onboarding/onboarding-wizard.tsx +347 -473
  96. package/src/components/pane-settings-dialog.tsx +521 -89
  97. package/src/components/pane-template-wizard.test.tsx +1 -1
  98. package/src/components/pane-template-wizard.tsx +38 -37
  99. package/src/components/price-selector-dialog.tsx +22 -21
  100. package/src/components/ticker-badge-list.tsx +53 -0
  101. package/src/components/ticker-badge-text.test.tsx +44 -1
  102. package/src/components/ticker-badge-text.tsx +78 -38
  103. package/src/components/ticker-badge.tsx +28 -7
  104. package/src/components/ticker-list-table-view.tsx +248 -0
  105. package/src/components/ticker-list-table.test.tsx +47 -1
  106. package/src/components/ticker-list-table.tsx +212 -41
  107. package/src/components/toggle-list.tsx +114 -8
  108. package/src/components/ui/button.tsx +24 -16
  109. package/src/components/ui/choice-dialog.tsx +89 -0
  110. package/src/components/ui/data-table.tsx +313 -114
  111. package/src/components/ui/external-link.tsx +52 -13
  112. package/src/components/ui/fields.tsx +44 -30
  113. package/src/components/ui/frame.tsx +24 -57
  114. package/src/components/ui/index.ts +15 -50
  115. package/src/components/ui/list-view.tsx +65 -25
  116. package/src/components/ui/loading.tsx +5 -60
  117. package/src/components/ui/message-composer.test.tsx +81 -0
  118. package/src/components/ui/message-composer.tsx +139 -0
  119. package/src/components/ui/multi-select-dialog.tsx +100 -32
  120. package/src/components/ui/multi-select.ts +112 -0
  121. package/src/components/ui/native-select.tsx +120 -0
  122. package/src/components/ui/page-stack-view.tsx +49 -19
  123. package/src/components/ui/remote-image.tsx +75 -0
  124. package/src/components/ui/row-value-cache.test.ts +17 -0
  125. package/src/components/ui/row-value-cache.ts +41 -0
  126. package/src/components/ui/shortcut-hint.tsx +55 -0
  127. package/src/components/ui/status.tsx +12 -67
  128. package/src/components/ui/table-layout.ts +59 -0
  129. package/src/components/ui/tabs.tsx +249 -27
  130. package/src/components/ui/toggle.tsx +19 -127
  131. package/src/components/ui/ui.test.tsx +266 -53
  132. package/src/components/use-double-click-activation.ts +7 -2
  133. package/src/components/use-external-link-footer.ts +79 -0
  134. package/src/core/app-services.ts +95 -0
  135. package/src/core/state/app-state.ts +886 -0
  136. package/src/{state → core/state}/session-persistence.ts +7 -6
  137. package/src/data/config-layout.ts +225 -0
  138. package/src/data/config-store-node.ts +390 -0
  139. package/src/data/config-store.test.ts +72 -0
  140. package/src/data/config-store.ts +35 -478
  141. package/src/data/sqlite-json.ts +2 -5
  142. package/src/data/sqlite-retry.ts +1 -0
  143. package/src/index.tsx +2 -68
  144. package/src/market-data/coordinator-subscriptions.test.ts +125 -0
  145. package/src/market-data/coordinator.test.ts +73 -4
  146. package/src/market-data/coordinator.ts +190 -24
  147. package/src/market-data/hooks.test.tsx +1 -1
  148. package/src/market-data/hooks.tsx +109 -87
  149. package/src/market-data/query-store.ts +3 -3
  150. package/src/market-data/request-types.test.ts +0 -14
  151. package/src/market-data/result-types.ts +1 -0
  152. package/src/news/aggregator.test.ts +267 -0
  153. package/src/news/aggregator.ts +452 -0
  154. package/src/news/hooks.ts +39 -0
  155. package/src/news/ticker-symbols.ts +21 -0
  156. package/src/news/types.ts +77 -0
  157. package/src/notifications/app-notifier.ts +21 -10
  158. package/src/pane-settings.test.ts +0 -2
  159. package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +124 -134
  160. package/src/plugins/builtin/ai/gloomberb-cli.ts +14 -13
  161. package/src/plugins/builtin/ai/providers.ts +1 -9
  162. package/src/plugins/builtin/ai/runner.ts +41 -5
  163. package/src/plugins/builtin/ai/screener-pane.test.tsx +37 -55
  164. package/src/plugins/builtin/ai/screener-pane.tsx +231 -276
  165. package/src/plugins/builtin/ai/settings.ts +0 -1
  166. package/src/plugins/builtin/ai/utils.ts +1 -71
  167. package/src/plugins/builtin/alerts/alert-engine.test.ts +1 -38
  168. package/src/plugins/builtin/alerts/index.test.tsx +61 -82
  169. package/src/plugins/builtin/alerts/index.tsx +263 -155
  170. package/src/plugins/builtin/alerts/types.ts +7 -0
  171. package/src/plugins/builtin/analytics/index.test.tsx +13 -8
  172. package/src/plugins/builtin/analytics/index.tsx +78 -120
  173. package/src/plugins/builtin/analytics/metrics.test.ts +0 -4
  174. package/src/plugins/builtin/ask-ai.test.tsx +55 -54
  175. package/src/plugins/builtin/broker-manager/index.test.tsx +168 -0
  176. package/src/plugins/builtin/broker-manager/index.tsx +759 -0
  177. package/src/plugins/builtin/broker-manager/model.test.ts +107 -0
  178. package/src/plugins/builtin/broker-manager/model.ts +142 -0
  179. package/src/plugins/builtin/chat-controller.test.ts +150 -0
  180. package/src/plugins/builtin/chat-controller.ts +88 -16
  181. package/src/plugins/builtin/chat.test.tsx +283 -36
  182. package/src/plugins/builtin/chat.tsx +373 -172
  183. package/src/plugins/builtin/cloud-auth-actions.tsx +72 -0
  184. package/src/plugins/builtin/cloud-tweets.tsx +896 -0
  185. package/src/plugins/builtin/comparison-chart.test.tsx +46 -57
  186. package/src/plugins/builtin/comparison-chart.tsx +11 -11
  187. package/src/plugins/builtin/correlation/compute.test.ts +0 -17
  188. package/src/plugins/builtin/correlation/index.tsx +51 -46
  189. package/src/plugins/builtin/correlation/settings.ts +1 -2
  190. package/src/plugins/builtin/debug.tsx +99 -70
  191. package/src/plugins/builtin/earnings/earnings-cache.test.ts +2 -2
  192. package/src/plugins/builtin/earnings/earnings-cache.ts +12 -3
  193. package/src/plugins/builtin/earnings/earnings-data.test.ts +42 -11
  194. package/src/plugins/builtin/earnings/earnings-data.ts +70 -5
  195. package/src/plugins/builtin/earnings/index.tsx +187 -94
  196. package/src/plugins/builtin/econ/calendar-source.ts +9 -116
  197. package/src/plugins/builtin/econ/fred-client.test.ts +1 -14
  198. package/src/plugins/builtin/econ/fred-series-map.ts +1 -0
  199. package/src/plugins/builtin/econ/index.tsx +236 -421
  200. package/src/plugins/builtin/econ/types.ts +1 -0
  201. package/src/plugins/builtin/fx-matrix/index.tsx +43 -45
  202. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -0
  203. package/src/plugins/builtin/help.test.tsx +120 -60
  204. package/src/plugins/builtin/help.tsx +266 -82
  205. package/src/plugins/builtin/holders/index.test.ts +45 -0
  206. package/src/plugins/builtin/holders/index.tsx +949 -0
  207. package/src/plugins/builtin/insider/index.tsx +207 -253
  208. package/src/plugins/builtin/insider/insider-data.test.ts +1 -11
  209. package/src/plugins/builtin/insider/insider-data.ts +1 -0
  210. package/src/plugins/builtin/layout-manager.tsx +12 -40
  211. package/src/plugins/builtin/market-movers/index.tsx +70 -144
  212. package/src/plugins/builtin/market-movers/screener.test.ts +0 -18
  213. package/src/plugins/builtin/news-wire/breaking-notifications.test.ts +98 -0
  214. package/src/plugins/builtin/news-wire/breaking-notifications.ts +110 -0
  215. package/src/plugins/builtin/news-wire/breaking-pane.tsx +157 -0
  216. package/src/plugins/builtin/news-wire/categories.ts +114 -0
  217. package/src/plugins/builtin/news-wire/default-feeds.ts +3 -0
  218. package/src/plugins/builtin/news-wire/digest-store.ts +44 -0
  219. package/src/plugins/builtin/news-wire/feed-config.test.ts +90 -0
  220. package/src/plugins/builtin/news-wire/feed-config.ts +216 -0
  221. package/src/plugins/builtin/news-wire/feed-pane.tsx +21 -0
  222. package/src/plugins/builtin/news-wire/hash.ts +9 -0
  223. package/src/plugins/builtin/news-wire/index.tsx +92 -0
  224. package/src/plugins/builtin/news-wire/industry-pane.tsx +140 -0
  225. package/src/plugins/builtin/news-wire/news-detail-view.tsx +256 -0
  226. package/src/plugins/builtin/news-wire/news-footer.ts +28 -0
  227. package/src/plugins/builtin/news-wire/news-preset-pane.tsx +94 -0
  228. package/src/plugins/builtin/news-wire/news-query-presets.ts +40 -0
  229. package/src/plugins/builtin/news-wire/news-table.test.tsx +206 -0
  230. package/src/plugins/builtin/news-wire/news-table.tsx +296 -0
  231. package/src/plugins/builtin/news-wire/persisted-articles.ts +92 -0
  232. package/src/plugins/builtin/news-wire/read-state.test.ts +30 -0
  233. package/src/plugins/builtin/news-wire/read-state.ts +76 -0
  234. package/src/plugins/builtin/news-wire/rss-parser.test.ts +184 -0
  235. package/src/plugins/builtin/news-wire/rss-parser.ts +213 -0
  236. package/src/plugins/builtin/news-wire/rss-source.test.ts +159 -0
  237. package/src/plugins/builtin/news-wire/rss-source.ts +181 -0
  238. package/src/plugins/builtin/news-wire/top-pane.tsx +21 -0
  239. package/src/plugins/builtin/news.tsx +98 -25
  240. package/src/plugins/builtin/notes-files.ts +51 -10
  241. package/src/plugins/builtin/notes.tsx +332 -131
  242. package/src/plugins/builtin/options.test.tsx +185 -0
  243. package/src/plugins/builtin/options.tsx +346 -206
  244. package/src/plugins/builtin/plugin-groups.ts +92 -0
  245. package/src/plugins/builtin/portfolio-list/header.tsx +72 -37
  246. package/src/plugins/builtin/portfolio-list/index.tsx +25 -42
  247. package/src/plugins/builtin/portfolio-list/metrics.ts +1 -1
  248. package/src/plugins/builtin/portfolio-list/pane.tsx +246 -164
  249. package/src/plugins/builtin/portfolio-list/settings.ts +19 -51
  250. package/src/plugins/builtin/portfolio-list/summary.tsx +21 -16
  251. package/src/plugins/builtin/portfolio-list/table.tsx +66 -25
  252. package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.test.tsx +1 -1
  253. package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +1 -1
  254. package/src/plugins/builtin/portfolio-list.test.ts +60 -1
  255. package/src/plugins/builtin/portfolio-list.test.tsx +122 -55
  256. package/src/plugins/builtin/quote-monitor.test.tsx +2 -27
  257. package/src/plugins/builtin/research/index.tsx +724 -0
  258. package/src/plugins/builtin/sec.tsx +67 -19
  259. package/src/plugins/builtin/sectors/index.tsx +42 -80
  260. package/src/plugins/builtin/sectors/sector-data.ts +1 -0
  261. package/src/plugins/builtin/ticker-detail/chart-tab.tsx +25 -39
  262. package/src/plugins/builtin/ticker-detail/financials-tab.tsx +108 -58
  263. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +383 -271
  264. package/src/plugins/builtin/ticker-detail/pane.tsx +135 -49
  265. package/src/plugins/builtin/ticker-detail/quote-monitor.tsx +43 -27
  266. package/src/plugins/builtin/ticker-detail/settings.ts +3 -6
  267. package/src/plugins/builtin/ticker-detail-chart-tab-switch.test.tsx +16 -10
  268. package/src/plugins/builtin/ticker-detail.test.tsx +156 -33
  269. package/src/plugins/builtin/ticker-surface.ts +68 -0
  270. package/src/plugins/builtin/world-indices/index.tsx +44 -82
  271. package/src/plugins/builtin/world-indices/indices.ts +1 -0
  272. package/src/plugins/builtin/yahoo.ts +55 -1
  273. package/src/plugins/builtin/yield-curve/index.tsx +87 -145
  274. package/src/plugins/builtin/yield-curve/treasury-data.ts +6 -77
  275. package/src/plugins/catalog-ui.test.ts +24 -0
  276. package/src/plugins/catalog-ui.ts +44 -0
  277. package/src/plugins/catalog.ts +2 -50
  278. package/src/plugins/ibkr/__snapshots__/trade-tab.test.tsx.snap +5 -5
  279. package/src/plugins/ibkr/account-cache.test.ts +15 -14
  280. package/src/plugins/ibkr/account-cache.ts +15 -120
  281. package/src/plugins/ibkr/broker-adapter.ts +67 -0
  282. package/src/plugins/ibkr/config.test.ts +0 -18
  283. package/src/plugins/ibkr/dialogs.tsx +14 -56
  284. package/src/plugins/ibkr/flex.test.ts +57 -2
  285. package/src/plugins/ibkr/flex.ts +116 -12
  286. package/src/plugins/ibkr/gateway-helpers.ts +8 -3
  287. package/src/plugins/ibkr/gateway-service-native.ts +2381 -0
  288. package/src/plugins/ibkr/gateway-service.test.ts +47 -9
  289. package/src/plugins/ibkr/gateway-service.ts +264 -2235
  290. package/src/plugins/ibkr/gateway-types.ts +27 -0
  291. package/src/plugins/ibkr/index.test.tsx +3 -11
  292. package/src/plugins/ibkr/index.tsx +1 -0
  293. package/src/plugins/ibkr/price-normalization.test.ts +1 -6
  294. package/src/plugins/ibkr/price-normalization.ts +1 -0
  295. package/src/plugins/ibkr/trade-badge.tsx +6 -5
  296. package/src/plugins/ibkr/trade-tab.test.tsx +2 -2
  297. package/src/plugins/ibkr/trade-tab.tsx +164 -117
  298. package/src/plugins/ibkr/trading-pane.tsx +117 -83
  299. package/src/plugins/pane-manager.test.ts +3 -1
  300. package/src/plugins/pane-manager.ts +93 -19
  301. package/src/plugins/plugin-runtime.test.tsx +176 -74
  302. package/src/plugins/plugin-runtime.tsx +228 -10
  303. package/src/plugins/prediction-markets/cache.ts +49 -0
  304. package/src/plugins/prediction-markets/categories.ts +0 -10
  305. package/src/plugins/prediction-markets/chart.test.tsx +1 -1
  306. package/src/plugins/prediction-markets/chart.tsx +21 -20
  307. package/src/plugins/prediction-markets/cli.ts +1 -0
  308. package/src/plugins/prediction-markets/controller-data.ts +135 -89
  309. package/src/plugins/prediction-markets/controller.ts +37 -108
  310. package/src/plugins/prediction-markets/detail/book.tsx +23 -22
  311. package/src/plugins/prediction-markets/detail/outcomes.tsx +33 -32
  312. package/src/plugins/prediction-markets/detail/overview.tsx +17 -12
  313. package/src/plugins/prediction-markets/detail/pane.tsx +59 -45
  314. package/src/plugins/prediction-markets/detail/rules.tsx +22 -7
  315. package/src/plugins/prediction-markets/detail/shared.tsx +3 -2
  316. package/src/plugins/prediction-markets/detail/trades.tsx +12 -11
  317. package/src/plugins/prediction-markets/detail.test.tsx +1 -1
  318. package/src/plugins/prediction-markets/keyboard.ts +1 -0
  319. package/src/plugins/prediction-markets/launch.test.ts +1 -1
  320. package/src/plugins/prediction-markets/launch.ts +1 -1
  321. package/src/plugins/prediction-markets/metrics.ts +25 -12
  322. package/src/plugins/prediction-markets/pane.test.tsx +16 -7
  323. package/src/plugins/prediction-markets/pane.tsx +180 -82
  324. package/src/plugins/prediction-markets/plugin.test.tsx +37 -45
  325. package/src/plugins/prediction-markets/services/fetch.ts +27 -10
  326. package/src/plugins/prediction-markets/services/kalshi-adapter.ts +20 -3
  327. package/src/plugins/prediction-markets/services/polymarket-adapter.ts +29 -11
  328. package/src/plugins/prediction-markets/settings.ts +0 -5
  329. package/src/plugins/prediction-markets/test-helpers.tsx +19 -44
  330. package/src/plugins/registry.test.ts +307 -0
  331. package/src/plugins/registry.ts +293 -82
  332. package/src/react/input.ts +53 -0
  333. package/src/react/plugins/plugin-slot.tsx +21 -0
  334. package/src/react/use-raf-callback.ts +44 -0
  335. package/src/renderers/electrobun/bun/application-menu-click.test.ts +41 -0
  336. package/src/renderers/electrobun/bun/application-menu-click.ts +55 -0
  337. package/src/renderers/electrobun/bun/application-menu.ts +118 -0
  338. package/src/renderers/electrobun/bun/context-menu-click.test.ts +67 -0
  339. package/src/renderers/electrobun/bun/context-menu-click.ts +61 -0
  340. package/src/renderers/electrobun/bun/context-menu-normalize.test.ts +52 -0
  341. package/src/renderers/electrobun/bun/context-menu-normalize.ts +67 -0
  342. package/src/renderers/electrobun/bun/core-capabilities.ts +328 -0
  343. package/src/renderers/electrobun/bun/desktop-workspace.test.ts +63 -0
  344. package/src/renderers/electrobun/bun/desktop-workspace.ts +162 -0
  345. package/src/renderers/electrobun/bun/index.ts +1149 -0
  346. package/src/renderers/electrobun/bun/window-frame.test.ts +40 -0
  347. package/src/renderers/electrobun/bun/window-frame.ts +46 -0
  348. package/src/renderers/electrobun/shared/protocol.ts +72 -0
  349. package/src/renderers/electrobun/view/ai-host.ts +93 -0
  350. package/src/renderers/electrobun/view/app-services.ts +348 -0
  351. package/src/renderers/electrobun/view/application-menu-bridge.ts +12 -0
  352. package/src/renderers/electrobun/view/backend-rpc.ts +173 -0
  353. package/src/renderers/electrobun/view/broker-remote-client.ts +154 -0
  354. package/src/renderers/electrobun/view/config-host.ts +35 -0
  355. package/src/renderers/electrobun/view/context-menu.test.ts +140 -0
  356. package/src/renderers/electrobun/view/context-menu.ts +164 -0
  357. package/src/renderers/electrobun/view/data-table.tsx +773 -0
  358. package/src/renderers/electrobun/view/desktop-controls.tsx +651 -0
  359. package/src/renderers/electrobun/view/desktop-window-bridge.ts +59 -0
  360. package/src/renderers/electrobun/view/desktop-window-snapshot.test.ts +57 -0
  361. package/src/renderers/electrobun/view/desktop-window-snapshot.ts +41 -0
  362. package/src/renderers/electrobun/view/dialog-host.tsx +62 -0
  363. package/src/renderers/electrobun/view/http-fetch.ts +113 -0
  364. package/src/renderers/electrobun/view/input-host.tsx +65 -0
  365. package/src/renderers/electrobun/view/key-event.test.ts +34 -0
  366. package/src/renderers/electrobun/view/key-event.ts +134 -0
  367. package/src/renderers/electrobun/view/main.tsx +104 -0
  368. package/src/renderers/electrobun/view/native-renderer.ts +110 -0
  369. package/src/renderers/electrobun/view/native-stubs/chart-kitty-support.ts +9 -0
  370. package/src/renderers/electrobun/view/native-stubs/chart-surface-manager.ts +25 -0
  371. package/src/renderers/electrobun/view/native-stubs/chart-surface-sync.ts +1 -0
  372. package/src/renderers/electrobun/view/notes-files.ts +56 -0
  373. package/src/renderers/electrobun/view/resource-store.test.ts +44 -0
  374. package/src/renderers/electrobun/view/resource-store.ts +106 -0
  375. package/src/renderers/electrobun/view/rpc-codec.ts +42 -0
  376. package/src/renderers/electrobun/view/scrollbar-activity.ts +23 -0
  377. package/src/renderers/electrobun/view/toast-host.tsx +65 -0
  378. package/src/renderers/electrobun/view/ui-host.tsx +1490 -0
  379. package/src/renderers/electrobun/view/update-host.ts +38 -0
  380. package/src/renderers/opentui/dialog-host.test.tsx +44 -0
  381. package/src/renderers/opentui/dialog-host.tsx +56 -0
  382. package/src/renderers/opentui/host.tsx +134 -0
  383. package/src/renderers/opentui/input-host.tsx +24 -0
  384. package/src/renderers/opentui/start.tsx +71 -0
  385. package/src/renderers/opentui/test-utils.tsx +76 -0
  386. package/src/renderers/opentui/toast-host.tsx +10 -0
  387. package/src/renderers/opentui/ui-host.tsx +97 -0
  388. package/src/sources/gloomberb-cloud.test.ts +288 -17
  389. package/src/sources/gloomberb-cloud.ts +176 -9
  390. package/src/sources/provider-errors.ts +1 -0
  391. package/src/sources/provider-router.test.ts +220 -81
  392. package/src/sources/provider-router.ts +294 -111
  393. package/src/sources/sec-edgar.ts +19 -6
  394. package/src/sources/yahoo-finance.test.ts +0 -5
  395. package/src/sources/yahoo-finance.ts +420 -11
  396. package/src/state/app-activity.ts +7 -7
  397. package/src/state/app-bootstrap.ts +114 -40
  398. package/src/state/app-context-selector.test.tsx +70 -1
  399. package/src/state/app-context.test.ts +71 -3
  400. package/src/state/app-context.test.tsx +14 -7
  401. package/src/state/app-context.tsx +205 -869
  402. package/src/state/config-save-scheduler.ts +35 -0
  403. package/src/state/persist-scheduler.test.ts +67 -0
  404. package/src/state/persist-scheduler.ts +69 -0
  405. package/src/state/selectors-ui.ts +55 -0
  406. package/src/state/selectors.ts +15 -71
  407. package/src/state/session-persistence.test.ts +1 -1
  408. package/src/state/ticker-refresh-queue.ts +52 -3
  409. package/src/state/use-inline-tickers.ts +18 -16
  410. package/src/state/use-quote-streaming.test.ts +0 -6
  411. package/src/state/use-quote-streaming.test.tsx +1 -1
  412. package/src/state/use-quote-streaming.ts +3 -2
  413. package/src/state/use-session-snapshot.ts +32 -17
  414. package/src/test-support/plugin-runtime.ts +149 -0
  415. package/src/theme/color-utils.ts +1 -0
  416. package/src/theme/colors.ts +16 -0
  417. package/src/types/broker.ts +16 -1
  418. package/src/types/capability-route-source.ts +23 -0
  419. package/src/types/config.test.ts +23 -0
  420. package/src/types/config.ts +145 -10
  421. package/src/types/context-menu.ts +95 -0
  422. package/src/types/data-provider.ts +34 -3
  423. package/src/types/desktop-menu.ts +13 -0
  424. package/src/types/desktop-window.ts +29 -0
  425. package/src/types/financials.ts +123 -2
  426. package/src/types/instrument.ts +1 -0
  427. package/src/types/news-source.ts +9 -0
  428. package/src/types/persistence.ts +1 -0
  429. package/src/types/plugin.ts +32 -8
  430. package/src/ui/ascii-font.ts +85 -0
  431. package/src/ui/context-menu.test.ts +94 -0
  432. package/src/ui/context-menu.tsx +433 -0
  433. package/src/ui/dialog.tsx +55 -0
  434. package/src/ui/host.tsx +361 -0
  435. package/src/ui/index.tsx +126 -0
  436. package/src/ui/toast.tsx +40 -0
  437. package/src/updater.test.ts +69 -0
  438. package/src/updater.ts +61 -18
  439. package/src/utils/api-client.test.ts +186 -6
  440. package/src/utils/api-client.ts +433 -33
  441. package/src/utils/back-navigation.ts +6 -0
  442. package/src/utils/cli-output.ts +1 -0
  443. package/src/utils/currency-units.test.ts +1 -6
  444. package/src/utils/currency-units.ts +1 -0
  445. package/src/utils/debug-log.ts +68 -0
  446. package/src/utils/dom-screenshot.ts +326 -0
  447. package/src/utils/exchange-rate-map.ts +1 -0
  448. package/src/utils/exchanges.ts +214 -0
  449. package/src/utils/format.test.ts +7 -0
  450. package/src/utils/format.ts +1 -0
  451. package/src/utils/fuzzy-search.ts +1 -0
  452. package/src/utils/html-entities.test.ts +8 -0
  453. package/src/utils/html-entities.ts +32 -0
  454. package/src/utils/http-transport.ts +11 -0
  455. package/src/utils/main-thread-monitor.ts +127 -0
  456. package/src/utils/perf-marks.ts +54 -0
  457. package/src/utils/quote-freshness.ts +27 -50
  458. package/src/utils/quote-resolution.test.ts +5 -5
  459. package/src/utils/quote-resolution.ts +0 -1
  460. package/src/utils/quote-time.ts +1 -5
  461. package/src/utils/sec.test.ts +0 -12
  462. package/src/utils/selection-clipboard.ts +14 -6
  463. package/src/utils/shortcut-labels.test.ts +20 -0
  464. package/src/utils/shortcut-labels.ts +67 -0
  465. package/src/utils/slugify.ts +1 -0
  466. package/src/utils/terminal-input-reset.ts +1 -0
  467. package/src/utils/text-wrap.ts +82 -0
  468. package/src/utils/throttled-fetch.test.ts +19 -0
  469. package/src/utils/throttled-fetch.ts +11 -9
  470. package/src/utils/ticker-list.test.ts +1 -7
  471. package/src/utils/ticker-list.ts +1 -0
  472. package/src/utils/timestamp.ts +29 -0
  473. package/src/utils/tweet-text.test.ts +13 -0
  474. package/src/utils/tweet-text.ts +18 -0
  475. package/src/utils/url.ts +11 -0
  476. package/src/version.ts +1 -1
  477. package/src/components/chart/chart-control-hint.tsx +0 -39
  478. package/src/components/detail-feed-view.test.tsx +0 -180
  479. package/src/components/detail-feed-view.tsx +0 -531
  480. package/src/components/layout/pixel-mouse-mode.test.ts +0 -122
  481. package/src/components/layout/pixel-mouse.test.ts +0 -40
  482. package/src/components/spinner.tsx +0 -2
  483. package/src/components/tab-bar.tsx +0 -17
  484. package/src/components/ui/multi-select-chips.tsx +0 -69
  485. package/src/plugins/builtin/ai/index.test.tsx +0 -139
  486. package/src/plugins/builtin/ask-ai.tsx +0 -9
  487. package/src/plugins/builtin/correlation/plugin.test.ts +0 -44
  488. package/src/plugins/builtin/correlation/settings.test.ts +0 -34
  489. package/src/plugins/builtin/econ/calendar-source.test.ts +0 -219
  490. package/src/plugins/builtin/econ/fred-client.ts +0 -79
  491. package/src/plugins/builtin/fred-settings.ts +0 -10
  492. package/src/plugins/builtin/options-availability.test.tsx +0 -179
  493. package/src/plugins/builtin/options-availability.ts +0 -158
  494. package/src/plugins/builtin/portfolio-list/metrics.test.ts +0 -61
  495. package/src/plugins/builtin/yield-curve/treasury-data.test.ts +0 -212
  496. package/src/plugins/prediction-markets/status.ts +0 -24
  497. package/src/plugins/prediction-markets/table.tsx +0 -87
  498. package/src/utils/quote-time.test.ts +0 -22
  499. package/src/utils/selection-clipboard.test.ts +0 -43
  500. package/src/utils/terminal-input-reset.test.ts +0 -50
@@ -1,7 +1,8 @@
1
1
  import { afterEach, describe, expect, test } from "bun:test";
2
2
  import { createTestRenderer } from "@opentui/core/testing";
3
- import { createRoot } from "@opentui/react";
4
- import { act, useReducer } from "react";
3
+ import { createOpenTuiTestRoot as createRoot } from "../../renderers/opentui/test-utils";
4
+ import { act, useReducer, useState } from "react";
5
+ import { PaneFooterBar, PaneFooterProvider } from "../layout/pane-footer";
5
6
  import {
6
7
  AppContext,
7
8
  PaneInstanceProvider,
@@ -10,12 +11,14 @@ import {
10
11
  type AppAction,
11
12
  } from "../../state/app-context";
12
13
  import { MarketDataCoordinator, setSharedMarketDataCoordinator } from "../../market-data/coordinator";
13
- import { setSharedDataProviderForTests } from "../../plugins/registry";
14
+ import { setSharedMarketDataForTests } from "../../plugins/registry";
14
15
  import { cloneLayout, createDefaultConfig, type AppConfig } from "../../types/config";
15
16
  import type { DataProvider } from "../../types/data-provider";
16
17
  import type { PricePoint, TickerFinancials } from "../../types/financials";
17
18
  import type { TickerRecord } from "../../types/ticker";
19
+ import { Box } from "../../ui";
18
20
  import { StockChart } from "./stock-chart";
21
+ import { getNativeSurfaceManager } from "./native/surface-manager";
19
22
 
20
23
  const TEST_PANE_ID = "ticker-detail:test";
21
24
  const CHART_DETAIL_REQUEST_DEBOUNCE_WAIT_MS = 220;
@@ -121,10 +124,16 @@ function ChartHarness({
121
124
  config,
122
125
  ticker,
123
126
  financials,
127
+ interactive = false,
128
+ activateOnMouse = false,
129
+ width = 84,
124
130
  }: {
125
131
  config: AppConfig;
126
132
  ticker: TickerRecord;
127
133
  financials: TickerFinancials;
134
+ interactive?: boolean;
135
+ activateOnMouse?: boolean;
136
+ width?: number;
128
137
  }) {
129
138
  const initialState = createInitialState(config);
130
139
  initialState.focusedPaneId = TEST_PANE_ID;
@@ -132,12 +141,27 @@ function ChartHarness({
132
141
  initialState.financials = new Map([[ticker.metadata.ticker, financials]]);
133
142
 
134
143
  const [state, dispatch] = useReducer(appReducer, initialState);
144
+ const [mouseInteractive, setMouseInteractive] = useState(interactive);
135
145
  harnessDispatch = dispatch;
146
+ const effectiveInteractive = activateOnMouse ? mouseInteractive : interactive;
136
147
 
137
148
  return (
138
149
  <AppContext value={{ state, dispatch }}>
139
150
  <PaneInstanceProvider paneId={TEST_PANE_ID}>
140
- <StockChart width={84} height={16} focused />
151
+ <PaneFooterProvider>
152
+ {(footer) => (
153
+ <Box flexDirection="column" width={width} height={16}>
154
+ <StockChart
155
+ width={width}
156
+ height={15}
157
+ focused
158
+ interactive={effectiveInteractive}
159
+ onActivate={activateOnMouse ? () => setMouseInteractive(true) : undefined}
160
+ />
161
+ <PaneFooterBar footer={footer} focused width={width} />
162
+ </Box>
163
+ )}
164
+ </PaneFooterProvider>
141
165
  </PaneInstanceProvider>
142
166
  </AppContext>
143
167
  );
@@ -228,7 +252,7 @@ afterEach(async () => {
228
252
  harnessDispatch = null;
229
253
  sharedCoordinator = null;
230
254
  setSharedMarketDataCoordinator(null);
231
- setSharedDataProviderForTests(undefined);
255
+ setSharedMarketDataForTests(undefined);
232
256
  if (root) {
233
257
  await act(async () => {
234
258
  root!.unmount();
@@ -250,7 +274,7 @@ describe("StockChart renderer switching", () => {
250
274
  const provider = makeProvider({ [symbol]: [] });
251
275
  sharedCoordinator = new MarketDataCoordinator(provider);
252
276
  setSharedMarketDataCoordinator(sharedCoordinator);
253
- setSharedDataProviderForTests(provider);
277
+ setSharedMarketDataForTests(provider);
254
278
  const financials: TickerFinancials = {
255
279
  annualStatements: [],
256
280
  quarterlyStatements: [],
@@ -278,6 +302,192 @@ describe("StockChart renderer switching", () => {
278
302
  expect(frame).toContain("AUTO");
279
303
  });
280
304
 
305
+ test("keeps the time axis above the pane footer", async () => {
306
+ const symbol = "AAPL";
307
+ const config = makeChartConfig(symbol);
308
+ const ticker = makeTicker(symbol);
309
+ const history = makeMonthlyHistory(72, new Date(Date.UTC(2019, 0, 1)));
310
+ const provider = makeProvider({ [symbol]: history });
311
+ sharedCoordinator = new MarketDataCoordinator(provider);
312
+ setSharedMarketDataCoordinator(sharedCoordinator);
313
+ setSharedMarketDataForTests(provider);
314
+ const financials: TickerFinancials = {
315
+ annualStatements: [],
316
+ quarterlyStatements: [],
317
+ priceHistory: history,
318
+ };
319
+
320
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
321
+ testSetup = await createTestRenderer({ width: 120, height: 32 });
322
+ root = createRoot(testSetup.renderer);
323
+ act(() => {
324
+ root!.render(
325
+ <ChartHarness
326
+ config={config}
327
+ ticker={ticker}
328
+ financials={financials}
329
+ />,
330
+ );
331
+ });
332
+
333
+ await flushFrames(4);
334
+ const lines = testSetup.captureCharFrame().split("\n");
335
+ const chartAndFooterLines = lines.slice(0, 16);
336
+ const footerLine = chartAndFooterLines.at(-1) ?? "";
337
+
338
+ expect(chartAndFooterLines.join("\n")).toContain("Dec 2019");
339
+ expect(footerLine).toContain("[m]ode");
340
+ expect(footerLine).not.toContain("Dec 2019");
341
+ expect(footerLine).not.toContain("Dec 2024");
342
+ });
343
+
344
+ test("keeps the native chart surface clear of the time axis row", async () => {
345
+ const symbol = "AAPL";
346
+ const config = makeChartConfig(symbol);
347
+ config.chartPreferences.renderer = "kitty";
348
+ const ticker = makeTicker(symbol);
349
+ const history = makeMonthlyHistory(72, new Date(Date.UTC(2019, 0, 1)));
350
+ const provider = makeProvider({ [symbol]: history });
351
+ sharedCoordinator = new MarketDataCoordinator(provider);
352
+ setSharedMarketDataCoordinator(sharedCoordinator);
353
+ setSharedMarketDataForTests(provider);
354
+ const financials: TickerFinancials = {
355
+ annualStatements: [],
356
+ quarterlyStatements: [],
357
+ priceHistory: history,
358
+ };
359
+
360
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
361
+ testSetup = await createTestRenderer({ width: 120, height: 32 });
362
+ ((testSetup.renderer as unknown) as { _capabilities: unknown })._capabilities = { kitty_graphics: true };
363
+ ((testSetup.renderer as unknown) as { _resolution: unknown })._resolution = { width: 1200, height: 960 };
364
+ root = createRoot(testSetup.renderer);
365
+ act(() => {
366
+ root!.render(
367
+ <ChartHarness
368
+ config={config}
369
+ ticker={ticker}
370
+ financials={financials}
371
+ />,
372
+ );
373
+ });
374
+
375
+ await flushFrames(4);
376
+ const lines = testSetup.captureCharFrame().split("\n");
377
+ const axisLineIndex = lines.findIndex((line) => line.includes("Dec 2019"));
378
+ const footerLineIndex = lines.findIndex((line) => line.includes("[m]ode"));
379
+ expect(axisLineIndex).toBeGreaterThanOrEqual(0);
380
+ expect(footerLineIndex).toBeGreaterThan(axisLineIndex);
381
+
382
+ const manager = getNativeSurfaceManager(testSetup.renderer as never) as unknown as {
383
+ surfaces: Map<string, { snapshot: { rect: { height: number } } }>;
384
+ };
385
+ expect(manager.surfaces.get("chart-surface:ticker-detail:test:full:base")?.snapshot.rect.height).toBe(11);
386
+ });
387
+
388
+ test("moves candle OHLC summary into the pane footer", async () => {
389
+ const symbol = "AAPL";
390
+ const config = makeChartConfig(symbol);
391
+ config.chartPreferences.defaultRenderMode = "candles";
392
+ const ticker = makeTicker(symbol);
393
+ const history = makeHistory(96);
394
+ const provider = makeProvider({ [symbol]: history });
395
+ sharedCoordinator = new MarketDataCoordinator(provider);
396
+ setSharedMarketDataCoordinator(sharedCoordinator);
397
+ setSharedMarketDataForTests(provider);
398
+ const financials: TickerFinancials = {
399
+ annualStatements: [],
400
+ quarterlyStatements: [],
401
+ priceHistory: history,
402
+ };
403
+
404
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
405
+ testSetup = await createTestRenderer({ width: 140, height: 32 });
406
+ root = createRoot(testSetup.renderer);
407
+ act(() => {
408
+ root!.render(
409
+ <ChartHarness
410
+ config={config}
411
+ ticker={ticker}
412
+ financials={financials}
413
+ width={120}
414
+ />,
415
+ );
416
+ });
417
+
418
+ await flushFrames(4);
419
+ const lines = testSetup.captureCharFrame().split("\n");
420
+ const chartAndFooterLines = lines.slice(0, 16);
421
+ const footerLine = chartAndFooterLines.at(-1) ?? "";
422
+
423
+ expect(chartAndFooterLines.join("\n")).not.toContain("AAPL -");
424
+ expect(footerLine).toContain("O $");
425
+ expect(footerLine).toContain("H $");
426
+ expect(footerLine).toContain("L $");
427
+ expect(footerLine).toContain("C $");
428
+ expect(footerLine).toContain("V ");
429
+ expect(footerLine).toContain("[m]ode");
430
+ });
431
+
432
+ test("pans the visible window with mouse drag", async () => {
433
+ const symbol = "AAPL";
434
+ const config = makeChartConfig(symbol);
435
+ config.layout.instances = config.layout.instances.map((instance) => (
436
+ instance.instanceId === TEST_PANE_ID
437
+ ? {
438
+ ...instance,
439
+ settings: {
440
+ chartRangePreset: "1Y",
441
+ chartResolution: "1d",
442
+ },
443
+ }
444
+ : instance
445
+ ));
446
+ config.layouts = [{ name: "Default", layout: cloneLayout(config.layout) }];
447
+ const ticker = makeTicker(symbol);
448
+ const history = makeHistory(240);
449
+ const provider = makeProvider({ [symbol]: history });
450
+ sharedCoordinator = new MarketDataCoordinator(provider);
451
+ setSharedMarketDataCoordinator(sharedCoordinator);
452
+ setSharedMarketDataForTests(provider);
453
+ const financials: TickerFinancials = {
454
+ annualStatements: [],
455
+ quarterlyStatements: [],
456
+ priceHistory: history,
457
+ };
458
+
459
+ actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
460
+ testSetup = await createTestRenderer({ width: 120, height: 32 });
461
+ root = createRoot(testSetup.renderer);
462
+ act(() => {
463
+ root!.render(
464
+ <ChartHarness
465
+ config={config}
466
+ ticker={ticker}
467
+ financials={financials}
468
+ activateOnMouse
469
+ />,
470
+ );
471
+ });
472
+
473
+ await flushFrames(3);
474
+ await emitKeypress({ name: "=", sequence: "=" });
475
+ await flushFrames(3);
476
+
477
+ const beforeLines = testSetup.captureCharFrame().split("\n");
478
+ const beforeAxis = beforeLines[14] ?? "";
479
+
480
+ await act(async () => {
481
+ await testSetup!.mockMouse.drag(20, 8, 68, 8);
482
+ await testSetup!.renderOnce();
483
+ });
484
+ await flushFrames(2);
485
+
486
+ const afterLines = testSetup.captureCharFrame().split("\n");
487
+ const afterAxis = afterLines[14] ?? "";
488
+ expect(afterAxis).not.toBe(beforeAxis);
489
+ });
490
+
281
491
  test("switches from braille to kitty without crashing text updates", async () => {
282
492
  const symbol = "AAPL";
283
493
  const config = makeChartConfig(symbol);
@@ -307,7 +517,7 @@ describe("StockChart renderer switching", () => {
307
517
  });
308
518
 
309
519
  await flushFrames();
310
- expect(testSetup.captureCharFrame()).toContain("AAPL");
520
+ expect(testSetup.captureCharFrame()).toContain("AUTO 1M");
311
521
 
312
522
  const nextConfig: AppConfig = {
313
523
  ...config,
@@ -322,7 +532,7 @@ describe("StockChart renderer switching", () => {
322
532
  });
323
533
 
324
534
  await flushFrames();
325
- expect(testSetup.captureCharFrame()).toContain("AAPL");
535
+ expect(testSetup.captureCharFrame()).toContain("AUTO 1M");
326
536
  });
327
537
 
328
538
  test("applies preset hotkeys without reverting to the previous stored range", async () => {
@@ -332,7 +542,7 @@ describe("StockChart renderer switching", () => {
332
542
  const provider = makeProvider({ [symbol]: makeHistory(180) });
333
543
  sharedCoordinator = new MarketDataCoordinator(provider);
334
544
  setSharedMarketDataCoordinator(sharedCoordinator);
335
- setSharedDataProviderForTests(provider);
545
+ setSharedMarketDataForTests(provider);
336
546
  const financials: TickerFinancials = {
337
547
  annualStatements: [],
338
548
  quarterlyStatements: [],
@@ -353,15 +563,14 @@ describe("StockChart renderer switching", () => {
353
563
  });
354
564
 
355
565
  await flushFrames(3);
356
- expect(testSetup.captureCharFrame()).toContain("AAPL - AUTO");
566
+ expect(testSetup.captureCharFrame()).toContain("AUTO 1M");
357
567
 
358
568
  await emitKeypress({ name: "3", sequence: "3" });
359
569
  await flushFrames(3);
360
570
  await flushDebouncedChartRequests();
361
571
 
362
572
  const frame = testSetup.captureCharFrame();
363
- expect(frame).not.toContain("AAPL - AUTO");
364
- expect(frame).toContain("AAPL - 15M");
573
+ expect(frame).not.toContain("AAPL -");
365
574
  expect(frame).toContain("May 28");
366
575
  expect(frame).not.toContain("view:");
367
576
  });
@@ -402,7 +611,7 @@ describe("StockChart renderer switching", () => {
402
611
  } satisfies DataProvider;
403
612
  sharedCoordinator = new MarketDataCoordinator(provider);
404
613
  setSharedMarketDataCoordinator(sharedCoordinator);
405
- setSharedDataProviderForTests(provider);
614
+ setSharedMarketDataForTests(provider);
406
615
  const financials: TickerFinancials = {
407
616
  annualStatements: [],
408
617
  quarterlyStatements: [],
@@ -424,7 +633,7 @@ describe("StockChart renderer switching", () => {
424
633
 
425
634
  await flushFrames(6);
426
635
  await flushDebouncedChartRequests();
427
- expect(testSetup.captureCharFrame()).toContain("AAPL - AUTO");
636
+ expect(testSetup.captureCharFrame()).toContain("AUTO 1M");
428
637
  expect(detailBarSizes).toContain("15m");
429
638
 
430
639
  for (let index = 0; index < 6; index += 1) {
@@ -474,7 +683,7 @@ describe("StockChart renderer switching", () => {
474
683
  } satisfies DataProvider;
475
684
  sharedCoordinator = new MarketDataCoordinator(provider);
476
685
  setSharedMarketDataCoordinator(sharedCoordinator);
477
- setSharedDataProviderForTests(provider);
686
+ setSharedMarketDataForTests(provider);
478
687
  const financials: TickerFinancials = {
479
688
  annualStatements: [],
480
689
  quarterlyStatements: [],
@@ -543,7 +752,7 @@ describe("StockChart renderer switching", () => {
543
752
  } satisfies DataProvider;
544
753
  sharedCoordinator = new MarketDataCoordinator(provider);
545
754
  setSharedMarketDataCoordinator(sharedCoordinator);
546
- setSharedDataProviderForTests(provider);
755
+ setSharedMarketDataForTests(provider);
547
756
  const financials: TickerFinancials = {
548
757
  annualStatements: [],
549
758
  quarterlyStatements: [],
@@ -574,7 +783,7 @@ describe("StockChart renderer switching", () => {
574
783
  expect(resolutionRequests.some((request) => request.resolution === "1d")).toBe(true);
575
784
  expect(detailRequests).toHaveLength(0);
576
785
  expect(frame).not.toContain("No price history available.");
577
- expect(frame).toContain("Apr");
786
+ expect(frame).toMatch(/\b[A-Z][a-z]{2} \d{1,2}/);
578
787
  });
579
788
 
580
789
  test("mouse scroll at the auto edge does not zoom into narrower detail windows", async () => {
@@ -603,7 +812,7 @@ describe("StockChart renderer switching", () => {
603
812
  } satisfies DataProvider;
604
813
  sharedCoordinator = new MarketDataCoordinator(provider);
605
814
  setSharedMarketDataCoordinator(sharedCoordinator);
606
- setSharedDataProviderForTests(provider);
815
+ setSharedMarketDataForTests(provider);
607
816
  const financials: TickerFinancials = {
608
817
  annualStatements: [],
609
818
  quarterlyStatements: [],
@@ -625,18 +834,18 @@ describe("StockChart renderer switching", () => {
625
834
 
626
835
  await flushFrames(6);
627
836
  const initialFrame = testSetup.captureCharFrame();
628
- const titleRow = getFrameRowContaining(initialFrame, "AAPL - AUTO");
629
- expect(titleRow).toBeGreaterThanOrEqual(0);
837
+ const controlsRow = getFrameRowContaining(initialFrame, "AUTO 1M");
838
+ expect(controlsRow).toBeGreaterThanOrEqual(0);
630
839
 
631
840
  await act(async () => {
632
- await testSetup!.mockMouse.scroll(1, titleRow, "up");
841
+ await testSetup!.mockMouse.scroll(1, controlsRow, "up");
633
842
  await testSetup!.renderOnce();
634
843
  });
635
844
  await flushFrames(2);
636
845
 
637
846
  for (let index = 0; index < 4; index += 1) {
638
847
  await act(async () => {
639
- await testSetup!.mockMouse.scroll(68, titleRow + 3, "up");
848
+ await testSetup!.mockMouse.scroll(68, controlsRow + 3, "up");
640
849
  await testSetup!.renderOnce();
641
850
  });
642
851
  await flushFrames(2);
@@ -644,8 +853,8 @@ describe("StockChart renderer switching", () => {
644
853
  await flushDebouncedChartRequests();
645
854
 
646
855
  const pannedFrame = testSetup.captureCharFrame();
647
- const pannedHeader = getFrameLineContaining(pannedFrame, "AAPL - AUTO");
648
- expect(pannedHeader).not.toContain("view:");
856
+ const pannedControls = getFrameLineContaining(pannedFrame, "AUTO 1M");
857
+ expect(pannedControls).not.toContain("view:");
649
858
  expect(detailRequests.some((request) => /(m|h)$/i.test(request))).toBe(false);
650
859
  });
651
860
 
@@ -685,7 +894,7 @@ describe("StockChart renderer switching", () => {
685
894
  } satisfies DataProvider;
686
895
  sharedCoordinator = new MarketDataCoordinator(provider);
687
896
  setSharedMarketDataCoordinator(sharedCoordinator);
688
- setSharedDataProviderForTests(provider);
897
+ setSharedMarketDataForTests(provider);
689
898
  const financials: TickerFinancials = {
690
899
  annualStatements: [],
691
900
  quarterlyStatements: [],
@@ -706,14 +915,14 @@ describe("StockChart renderer switching", () => {
706
915
  });
707
916
 
708
917
  await flushFrames(6);
709
- expect(testSetup.captureCharFrame()).toContain("AAPL - 1D");
918
+ expect(testSetup.captureCharFrame()).toContain("1D");
710
919
 
711
920
  await emitKeypress({ name: "a", sequence: "a" });
712
921
  await flushFrames(3);
713
922
 
714
923
  const loadingFrame = testSetup.captureCharFrame();
715
924
  expect(pendingResolvers.length).toBeGreaterThan(0);
716
- expect(loadingFrame).toContain("AAPL - 1D");
925
+ expect(loadingFrame).toContain("1D");
717
926
  expect(loadingFrame).not.toContain("Loading chart...");
718
927
 
719
928
  await emitKeypress({ name: "a", sequence: "a" });
@@ -766,7 +975,7 @@ describe("StockChart renderer switching", () => {
766
975
  } satisfies DataProvider;
767
976
  sharedCoordinator = new MarketDataCoordinator(provider);
768
977
  setSharedMarketDataCoordinator(sharedCoordinator);
769
- setSharedDataProviderForTests(provider);
978
+ setSharedMarketDataForTests(provider);
770
979
  const financials: TickerFinancials = {
771
980
  annualStatements: [],
772
981
  quarterlyStatements: [],
@@ -787,7 +996,7 @@ describe("StockChart renderer switching", () => {
787
996
  });
788
997
 
789
998
  await flushFrames(6);
790
- expect(testSetup.captureCharFrame()).toContain("AAPL - 1D");
999
+ expect(testSetup.captureCharFrame()).toContain("1D");
791
1000
 
792
1001
  holdDetailRequests = true;
793
1002
  for (let index = 0; index < 5; index += 1) {
@@ -798,7 +1007,7 @@ describe("StockChart renderer switching", () => {
798
1007
 
799
1008
  const loadingFrame = testSetup.captureCharFrame();
800
1009
  expect(pendingResolvers.length).toBeGreaterThan(0);
801
- expect(loadingFrame).toContain("AAPL - 1D");
1010
+ expect(loadingFrame).toContain("1D");
802
1011
  expect(loadingFrame).not.toContain("Loading chart...");
803
1012
 
804
1013
  await act(async () => {
@@ -854,7 +1063,7 @@ describe("StockChart renderer switching", () => {
854
1063
  } satisfies DataProvider;
855
1064
  sharedCoordinator = new MarketDataCoordinator(provider);
856
1065
  setSharedMarketDataCoordinator(sharedCoordinator);
857
- setSharedDataProviderForTests(provider);
1066
+ setSharedMarketDataForTests(provider);
858
1067
  const financials: TickerFinancials = {
859
1068
  annualStatements: [],
860
1069
  quarterlyStatements: [],
@@ -880,7 +1089,6 @@ describe("StockChart renderer switching", () => {
880
1089
  const firstFrame = testSetup.captureCharFrame();
881
1090
  expect(pendingOneDayResolvers.length).toBeGreaterThan(0);
882
1091
  expect(fallbackRequests).toBeGreaterThan(0);
883
- expect(firstFrame).toContain("AAPL - 1D");
884
1092
  expect(firstFrame).toContain("showing 1W");
885
1093
  expect(firstFrame).toContain("updating");
886
1094
  expect(firstFrame).not.toContain("Loading chart...");
@@ -922,7 +1130,7 @@ describe("StockChart renderer switching", () => {
922
1130
  } satisfies DataProvider;
923
1131
  sharedCoordinator = new MarketDataCoordinator(provider);
924
1132
  setSharedMarketDataCoordinator(sharedCoordinator);
925
- setSharedDataProviderForTests(provider);
1133
+ setSharedMarketDataForTests(provider);
926
1134
  const financials: TickerFinancials = {
927
1135
  annualStatements: [],
928
1136
  quarterlyStatements: [],
@@ -950,7 +1158,6 @@ describe("StockChart renderer switching", () => {
950
1158
  const frame = testSetup.captureCharFrame();
951
1159
  expect(detailRequests).toContain("1m");
952
1160
  expect(detailRequests).toContain("1d");
953
- expect(frame).toContain("AAPL - 1M");
954
1161
  expect(frame).toContain("showing 1D");
955
1162
  expect(frame).not.toContain("No price history available.");
956
1163
  });
@@ -984,7 +1191,7 @@ describe("StockChart renderer switching", () => {
984
1191
  } satisfies DataProvider;
985
1192
  sharedCoordinator = new MarketDataCoordinator(provider);
986
1193
  setSharedMarketDataCoordinator(sharedCoordinator);
987
- setSharedDataProviderForTests(provider);
1194
+ setSharedMarketDataForTests(provider);
988
1195
  const financials: TickerFinancials = {
989
1196
  annualStatements: [],
990
1197
  quarterlyStatements: [],