gloomberb 0.11.3 → 0.12.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 (489) hide show
  1. package/README.md +6 -4
  2. package/README.zh-CN.md +4 -2
  3. package/package.json +28 -1
  4. package/src/api-client/auth.ts +10 -0
  5. package/src/api-client/data.ts +103 -1
  6. package/src/api-client/index.test.ts +127 -0
  7. package/src/api-client/index.ts +129 -1
  8. package/src/api-client/normalizers.ts +39 -0
  9. package/src/api-client/paths.ts +85 -1
  10. package/src/api-client/types.ts +196 -0
  11. package/src/app/pane-runtime/index.tsx +15 -12
  12. package/src/app/pane-runtime/layout-placement.test.ts +27 -0
  13. package/src/app/pane-runtime/layout-placement.ts +13 -0
  14. package/src/app/pane-runtime/plugin-bindings.ts +62 -0
  15. package/src/app.tsx +60 -18
  16. package/src/architecture/browser-entry-graph.test.ts +96 -0
  17. package/src/brokers/profile-form.test.ts +25 -27
  18. package/src/brokers/test-broker.ts +68 -0
  19. package/src/cli/commands/plugins.ts +39 -11
  20. package/src/cli/desktop-pane-shot.ts +285 -16
  21. package/src/cli/index.ts +1 -1
  22. package/src/cli/pane-functions/capabilities.ts +58 -28
  23. package/src/cli/pane-functions/catalog.ts +16 -4
  24. package/src/cli/pane-functions/discovery.ts +1 -0
  25. package/src/cli/pane-functions/headless.test.ts +247 -0
  26. package/src/cli/pane-functions/headless.ts +423 -0
  27. package/src/cli/pane-functions/index.test.ts +9 -0
  28. package/src/cli/pane-functions/index.ts +6 -2
  29. package/src/cli/pane-functions/options.ts +27 -2
  30. package/src/cli/pane-functions/report.ts +4 -0
  31. package/src/cli/pane-functions/resolver.ts +26 -8
  32. package/src/cli/pane-functions/screenshot.test.ts +76 -0
  33. package/src/cli/pane-functions/screenshot.ts +236 -20
  34. package/src/cli/restore-plugins.ts +34 -0
  35. package/src/components/chart/{static/chart → composite}/axis-overlays.test.tsx +3 -3
  36. package/src/components/chart/{static/chart → composite}/axis-overlays.tsx +6 -11
  37. package/src/components/chart/{static/chart → composite}/bitmap.ts +17 -3
  38. package/src/components/chart/composite/composite-chart.test.tsx +68 -20
  39. package/src/components/chart/composite/composite-chart.tsx +301 -204
  40. package/src/components/chart/composite/format.ts +8 -2
  41. package/src/components/chart/composite/interactions.test.ts +68 -102
  42. package/src/components/chart/composite/interactions.ts +214 -264
  43. package/src/components/chart/composite/price-axis-labels.test.ts +21 -0
  44. package/src/components/chart/{price-axis-labels.tsx → composite/price-axis-labels.tsx} +9 -4
  45. package/src/components/chart/composite/scene.ts +57 -3
  46. package/src/components/chart/composite/text-renderer.ts +3 -2
  47. package/src/components/chart/composite/time-scale.ts +138 -57
  48. package/src/components/chart/composite/types.ts +25 -1
  49. package/src/components/chart/core/data.ts +9 -13
  50. package/src/components/chart/core/date-window.ts +7 -1
  51. package/src/components/chart/core/pointer.ts +3 -0
  52. package/src/components/chart/core/types.ts +0 -45
  53. package/src/components/chart/native/chart-rasterizer.ts +0 -1
  54. package/src/components/chart/native/kitty/index.test.ts +0 -188
  55. package/src/components/chart/native/raster/crosshair.ts +6 -5
  56. package/src/components/chart/native/raster/primitives.ts +0 -23
  57. package/src/components/chart/native/renderer-selection.ts +81 -31
  58. package/src/components/chart/static/{chart/surface.test.tsx → chart-surface.test.tsx} +28 -80
  59. package/src/components/chart/static/chart-surface.tsx +150 -0
  60. package/src/components/chart/static/index.ts +8 -0
  61. package/src/components/chart/static/multi-line-chart-surface.tsx +51 -166
  62. package/src/components/chart/static/scatter-chart-surface.test.ts +30 -0
  63. package/src/components/chart/static/scatter-chart-surface.tsx +135 -34
  64. package/src/components/chart/static/series.ts +49 -0
  65. package/src/components/command-bar/action-runtime.ts +1 -3
  66. package/src/components/command-bar/assist/model.test.ts +17 -2
  67. package/src/components/command-bar/assist/model.ts +40 -9
  68. package/src/components/command-bar/commands/direct/index.ts +1 -1
  69. package/src/components/command-bar/commands/direct/runtime.ts +1 -1
  70. package/src/components/command-bar/commands/registry.ts +0 -11
  71. package/src/components/command-bar/helpers.test.ts +2 -2
  72. package/src/components/command-bar/helpers.ts +2 -6
  73. package/src/components/command-bar/keyboard-shortcuts.ts +0 -11
  74. package/src/components/command-bar/list/badge.test.ts +54 -0
  75. package/src/components/command-bar/list/badge.ts +62 -0
  76. package/src/components/command-bar/list/model.test.ts +103 -0
  77. package/src/components/command-bar/list/model.ts +61 -4
  78. package/src/components/command-bar/list/view.test.tsx +113 -0
  79. package/src/components/command-bar/list/view.tsx +147 -131
  80. package/src/components/command-bar/pane-templates/workflow.ts +1 -1
  81. package/src/components/command-bar/panel/body.tsx +51 -65
  82. package/src/components/command-bar/panel/index.tsx +48 -13
  83. package/src/components/command-bar/panel/layout.test.ts +139 -0
  84. package/src/components/command-bar/panel/layout.ts +65 -28
  85. package/src/components/command-bar/panel/native-surface.ts +24 -0
  86. package/src/components/command-bar/panel/prompt-binding.ts +54 -0
  87. package/src/components/command-bar/panel/runtime.ts +6 -3
  88. package/src/components/command-bar/panel/state.ts +41 -7
  89. package/src/components/command-bar/panel/types.ts +7 -1
  90. package/src/components/command-bar/routes/root/provider-search.ts +34 -15
  91. package/src/components/command-bar/routes/root/results.test.ts +161 -0
  92. package/src/components/command-bar/routes/root/results.ts +30 -28
  93. package/src/components/command-bar/routes/root/runtime.ts +37 -20
  94. package/src/components/command-bar/routes/root/search-providers.test.tsx +224 -0
  95. package/src/components/command-bar/routes/root/search-providers.ts +205 -0
  96. package/src/components/command-bar/routes/root/selection.ts +1 -12
  97. package/src/components/command-bar/routes/root/shortcuts.test.ts +8 -8
  98. package/src/components/command-bar/routes/ticker-search/actions.ts +10 -9
  99. package/src/components/command-bar/routes/ticker-search/results.test.ts +54 -1
  100. package/src/components/command-bar/routes/ticker-search/results.ts +60 -19
  101. package/src/components/command-bar/routes/ticker-search/route.ts +1 -0
  102. package/src/components/command-bar/routing/actions.ts +1 -81
  103. package/src/components/command-bar/routing/launch-request.ts +1 -1
  104. package/src/components/command-bar/routing/list-state.ts +6 -21
  105. package/src/components/command-bar/selection-runtime.ts +1 -1
  106. package/src/components/command-bar/surface/assist.test.tsx +14 -10
  107. package/src/components/command-bar/surface/environment.ts +8 -1
  108. package/src/components/command-bar/surface/index.test.tsx +84 -68
  109. package/src/components/command-bar/surface/index.tsx +33 -36
  110. package/src/components/command-bar/surface/test-harness.tsx +15 -3
  111. package/src/components/command-bar/theme-picker.tsx +43 -15
  112. package/src/components/command-bar/view-model.test.ts +53 -8
  113. package/src/components/command-bar/view-model.ts +43 -14
  114. package/src/components/command-bar/workflow/tickers.ts +1 -0
  115. package/src/components/command-bar/workflow/types.ts +1 -1
  116. package/src/components/data-table/view.test.tsx +45 -6
  117. package/src/components/data-table/view.tsx +55 -9
  118. package/src/components/index.ts +10 -2
  119. package/src/components/input-search-bar.test.tsx +36 -2
  120. package/src/components/input-search-bar.tsx +18 -1
  121. package/src/components/layout/header.test.tsx +57 -10
  122. package/src/components/layout/header.tsx +292 -149
  123. package/src/components/layout/market-summary.test.ts +81 -0
  124. package/src/components/layout/market-summary.ts +109 -0
  125. package/src/components/layout/shell/chrome.ts +96 -1
  126. package/src/components/layout/shell/index.tsx +11 -3
  127. package/src/components/layout/shell/menu.ts +9 -0
  128. package/src/components/layout/shell/pane/actions.ts +29 -0
  129. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  130. package/src/components/layout/shell/shortcuts.ts +3 -0
  131. package/src/components/layout/status-bar.test.tsx +9 -8
  132. package/src/components/layout/status-bar.tsx +85 -54
  133. package/src/components/onboarding/onboarding-frame.tsx +2 -26
  134. package/src/components/price-sparkline/index.ts +61 -34
  135. package/src/components/price-sparkline/view.tsx +1 -1
  136. package/src/components/sign-in-gate.test.tsx +128 -0
  137. package/src/components/sign-in-gate.tsx +149 -0
  138. package/src/components/speedometer-gauge/desktop.tsx +2 -12
  139. package/src/components/ticker/badge/list.tsx +17 -3
  140. package/src/components/ticker/list-table-view.tsx +6 -3
  141. package/src/components/ui/data-table/index.tsx +3 -2
  142. package/src/components/ui/data-table/opentui/index.tsx +165 -120
  143. package/src/components/ui/frame.tsx +28 -0
  144. package/src/components/ui/index.ts +3 -0
  145. package/src/components/ui/native-select.tsx +20 -10
  146. package/src/components/ui/select-button.tsx +138 -0
  147. package/src/components/ui/status.tsx +2 -2
  148. package/src/components/ui/table-layout.ts +1 -1
  149. package/src/components/use-double-click-activation.ts +7 -3
  150. package/src/core/app-services.ts +3 -3
  151. package/src/data/config/layout.ts +12 -6
  152. package/src/data/config/store/index.test.ts +97 -0
  153. package/src/data/config/store/migrations.ts +41 -0
  154. package/src/data/config/store/normalize.ts +5 -3
  155. package/src/i18n/es.ts +6 -2
  156. package/src/i18n/ja.ts +6 -2
  157. package/src/i18n/ko.ts +6 -2
  158. package/src/i18n/zh-cn.ts +6 -2
  159. package/src/i18n/zh-tw.ts +6 -2
  160. package/src/layout-marketplace/pane-imagery.ts +1 -0
  161. package/src/layout-marketplace/payload.test.ts +17 -0
  162. package/src/layout-marketplace/payload.ts +40 -5
  163. package/src/market-data/coordinator/index.ts +3 -2
  164. package/src/market-data/coordinator/quotes.ts +173 -66
  165. package/src/market-data/coordinator/subscriptions.test.ts +215 -37
  166. package/src/pane-settings.ts +1 -1
  167. package/src/plugins/builtin/analytics/pane-model.ts +1 -1
  168. package/src/plugins/builtin/analytics/view.tsx +1 -1
  169. package/src/plugins/builtin/broker-manager/index.test.tsx +3 -2
  170. package/src/plugins/builtin/broker-manager/model.test.ts +2 -2
  171. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +16 -2
  172. package/src/plugins/builtin/chart-composer/pane.tsx +22 -8
  173. package/src/plugins/builtin/chat/content/composer.tsx +8 -4
  174. package/src/plugins/builtin/cloud/auth-dialog.tsx +14 -228
  175. package/src/plugins/builtin/cloud/auth-form.tsx +277 -0
  176. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  177. package/src/plugins/builtin/composite-plugins.ts +14 -1
  178. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  179. package/src/plugins/builtin/correlation/relationship/pane.tsx +2 -6
  180. package/src/plugins/builtin/correlation/relationship/view-model.ts +2 -2
  181. package/src/plugins/builtin/credit-conditions/index.test.tsx +12 -6
  182. package/src/plugins/builtin/credit-conditions/index.tsx +2 -21
  183. package/src/plugins/builtin/dividend-yield/index.tsx +1 -0
  184. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  185. package/src/plugins/builtin/earnings-calls/data.ts +223 -0
  186. package/src/plugins/builtin/earnings-calls/format.ts +49 -0
  187. package/src/plugins/builtin/earnings-calls/index.tsx +69 -0
  188. package/src/plugins/builtin/earnings-calls/pane.tsx +756 -0
  189. package/src/plugins/builtin/earnings-calls/prose.test.ts +36 -0
  190. package/src/plugins/builtin/earnings-calls/prose.ts +59 -0
  191. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +334 -0
  192. package/src/plugins/builtin/econ/detail-view.tsx +1 -2
  193. package/src/plugins/builtin/econ/fred-series-map.ts +16 -1
  194. package/src/plugins/builtin/econ/index.tsx +2 -1
  195. package/src/plugins/builtin/econ-statistics/cache.ts +4 -0
  196. package/src/plugins/builtin/econ-statistics/client.ts +92 -0
  197. package/src/plugins/builtin/econ-statistics/defs.ts +66 -0
  198. package/src/plugins/builtin/econ-statistics/detail.tsx +154 -0
  199. package/src/plugins/builtin/econ-statistics/headless.test.ts +54 -0
  200. package/src/plugins/builtin/econ-statistics/headless.ts +171 -0
  201. package/src/plugins/builtin/econ-statistics/index.tsx +54 -0
  202. package/src/plugins/builtin/econ-statistics/pane.tsx +356 -0
  203. package/src/plugins/builtin/econ-statistics/stats.ts +522 -0
  204. package/src/plugins/builtin/econ-statistics/transform.test.ts +86 -0
  205. package/src/plugins/builtin/econ-statistics/transform.ts +85 -0
  206. package/src/plugins/builtin/econ-statistics/trend.ts +57 -0
  207. package/src/plugins/builtin/econ-statistics/view.ts +90 -0
  208. package/src/plugins/builtin/fear-greed/charts.tsx +7 -18
  209. package/src/plugins/builtin/fear-greed/data.ts +6 -1
  210. package/src/plugins/builtin/help/index.tsx +4 -0
  211. package/src/plugins/builtin/holders/index.tsx +1 -0
  212. package/src/plugins/builtin/insider/index.tsx +1 -0
  213. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  214. package/src/plugins/builtin/kelly-sizer/sections.tsx +2 -3
  215. package/src/plugins/builtin/market-valuation/align.ts +122 -0
  216. package/src/plugins/builtin/market-valuation/cache.ts +32 -0
  217. package/src/plugins/builtin/market-valuation/chart-projection.ts +217 -0
  218. package/src/plugins/builtin/market-valuation/chart-series.ts +89 -0
  219. package/src/plugins/builtin/market-valuation/client.test.ts +141 -0
  220. package/src/plugins/builtin/market-valuation/client.ts +116 -0
  221. package/src/plugins/builtin/market-valuation/defs.ts +251 -0
  222. package/src/plugins/builtin/market-valuation/detail.tsx +159 -0
  223. package/src/plugins/builtin/market-valuation/headless.test.ts +58 -0
  224. package/src/plugins/builtin/market-valuation/headless.ts +170 -0
  225. package/src/plugins/builtin/market-valuation/index.tsx +64 -0
  226. package/src/plugins/builtin/market-valuation/indicators.ts +422 -0
  227. package/src/plugins/builtin/market-valuation/model.test.ts +350 -0
  228. package/src/plugins/builtin/market-valuation/model.ts +8 -0
  229. package/src/plugins/builtin/market-valuation/pane.test.tsx +247 -0
  230. package/src/plugins/builtin/market-valuation/pane.tsx +344 -0
  231. package/src/plugins/builtin/market-valuation/series.ts +12 -0
  232. package/src/plugins/builtin/market-valuation/settings.ts +38 -0
  233. package/src/plugins/builtin/market-valuation/sources.ts +130 -0
  234. package/src/plugins/builtin/market-valuation/trend.ts +89 -0
  235. package/src/plugins/builtin/market-valuation/view.ts +137 -0
  236. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +123 -0
  237. package/src/plugins/builtin/market-valuation/zone-scale/index.tsx +12 -0
  238. package/src/plugins/builtin/market-valuation/zone-scale/model.ts +60 -0
  239. package/src/plugins/builtin/market-valuation/zone-scale/terminal.tsx +94 -0
  240. package/src/plugins/builtin/news/wire/breaking/filters.test.ts +99 -0
  241. package/src/plugins/builtin/news/wire/breaking/filters.ts +110 -0
  242. package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +157 -53
  243. package/src/plugins/builtin/news/wire/breaking/notifications.ts +91 -25
  244. package/src/plugins/builtin/news/wire/index.tsx +31 -44
  245. package/src/plugins/builtin/options/index.tsx +1 -0
  246. package/src/plugins/builtin/options/view.test.tsx +29 -1
  247. package/src/plugins/builtin/options/view.tsx +1 -22
  248. package/src/plugins/builtin/plugin-marketplace/feed.ts +80 -0
  249. package/src/plugins/builtin/plugin-marketplace/index.tsx +31 -0
  250. package/src/plugins/builtin/plugin-marketplace/model.test.ts +200 -0
  251. package/src/plugins/builtin/plugin-marketplace/model.ts +204 -0
  252. package/src/plugins/builtin/plugin-marketplace/pane.tsx +385 -0
  253. package/src/plugins/builtin/plugin-marketplace/store.ts +46 -0
  254. package/src/plugins/builtin/plugin-module.ts +9 -1
  255. package/src/plugins/builtin/research/index.tsx +4 -0
  256. package/src/plugins/builtin/research-search/command-bar-search.test.ts +81 -0
  257. package/src/plugins/builtin/research-search/command-bar-search.ts +175 -0
  258. package/src/plugins/builtin/research-search/data.ts +109 -0
  259. package/src/plugins/builtin/research-search/document-view.test.tsx +75 -0
  260. package/src/plugins/builtin/research-search/document-view.tsx +254 -0
  261. package/src/plugins/builtin/research-search/filter-bar.tsx +62 -0
  262. package/src/plugins/builtin/research-search/focus-handoff.ts +47 -0
  263. package/src/plugins/builtin/research-search/index.tsx +85 -0
  264. package/src/plugins/builtin/research-search/model.test.ts +40 -0
  265. package/src/plugins/builtin/research-search/model.ts +291 -0
  266. package/src/plugins/builtin/research-search/pane.test.tsx +241 -0
  267. package/src/plugins/builtin/research-search/pane.tsx +678 -0
  268. package/src/plugins/builtin/research-search/saved-view.tsx +171 -0
  269. package/src/plugins/builtin/research-search/snippet-text.tsx +35 -0
  270. package/src/plugins/builtin/research-search/snippet.test.ts +78 -0
  271. package/src/plugins/builtin/research-search/snippet.ts +134 -0
  272. package/src/plugins/builtin/scanner/flow-model.test.ts +11 -1
  273. package/src/plugins/builtin/scanner/flow-model.ts +29 -1
  274. package/src/plugins/builtin/scanner/flow-pane.tsx +78 -22
  275. package/src/plugins/builtin/sec/index.tsx +1 -0
  276. package/src/plugins/builtin/shared/series-cache.ts +93 -0
  277. package/src/plugins/builtin/short-interest/index.tsx +1 -0
  278. package/src/plugins/builtin/short-interest/pane.tsx +1 -1
  279. package/src/plugins/builtin/thirteenf/index.tsx +1 -0
  280. package/src/plugins/builtin/ticker-detail/index.tsx +0 -14
  281. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
  282. package/src/plugins/builtin/volatility/index.tsx +1 -1
  283. package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +106 -0
  284. package/src/plugins/builtin/world-venue-map/map.tsx +213 -69
  285. package/src/plugins/builtin/world-venue-map/model.test.ts +32 -0
  286. package/src/plugins/builtin/world-venue-map/model.ts +134 -13
  287. package/src/plugins/builtin/yield-curve/index.tsx +1 -1
  288. package/src/plugins/bundle.test.ts +109 -0
  289. package/src/plugins/bundle.ts +139 -0
  290. package/src/plugins/catalog-browser.test.ts +1 -0
  291. package/src/plugins/catalog-browser.ts +10 -0
  292. package/src/plugins/catalog-manifest.test.ts +43 -0
  293. package/src/plugins/catalog-manifest.ts +92 -0
  294. package/src/plugins/catalog-ui.ts +20 -4
  295. package/src/plugins/catalog.ts +9 -2
  296. package/src/plugins/current-target.ts +28 -0
  297. package/src/plugins/host-contract.ts +37 -0
  298. package/src/plugins/host-link.ts +158 -0
  299. package/src/plugins/host-modules.ts +61 -0
  300. package/src/plugins/loader.ts +41 -22
  301. package/src/plugins/ownership.ts +1 -0
  302. package/src/plugins/prediction-markets/index.tsx +1 -0
  303. package/src/plugins/registry/context.ts +3 -0
  304. package/src/plugins/registry/contributions.ts +27 -0
  305. package/src/plugins/registry/index.test.ts +25 -0
  306. package/src/plugins/registry/index.ts +8 -0
  307. package/src/plugins/registry/pane-settings.ts +6 -13
  308. package/src/plugins/seed.test.ts +83 -0
  309. package/src/plugins/seed.ts +80 -0
  310. package/src/public/broker.ts +31 -0
  311. package/src/public/market-data.ts +9 -0
  312. package/src/public/pane-hooks.ts +57 -0
  313. package/src/public/public-api.test.ts +285 -0
  314. package/src/public/react.ts +62 -0
  315. package/src/public/test-support.ts +23 -0
  316. package/src/public/time-series.ts +8 -0
  317. package/src/public/utils.ts +77 -0
  318. package/src/remote/layout-helpers.ts +6 -8
  319. package/src/remote/resources.ts +2 -0
  320. package/src/remote/schema.ts +1 -0
  321. package/src/remote/semantic-tree.test.tsx +105 -0
  322. package/src/remote/semantic-tree.tsx +53 -35
  323. package/src/renderers/browser/main.tsx +6 -0
  324. package/src/renderers/cloudflare/worker.test.ts +19 -0
  325. package/src/renderers/cloudflare/worker.ts +1 -1
  326. package/src/renderers/electrobun/bun/external-plugins.ts +140 -0
  327. package/src/renderers/electrobun/bun/index.ts +5 -2
  328. package/src/renderers/electrobun/shared/protocol.ts +21 -0
  329. package/src/renderers/electrobun/view/build-assets.ts +0 -1
  330. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +51 -1
  331. package/src/renderers/electrobun/view/external-plugins.test.ts +45 -0
  332. package/src/renderers/electrobun/view/external-plugins.ts +63 -0
  333. package/src/renderers/electrobun/view/host/ascii-text.test.ts +48 -0
  334. package/src/renderers/electrobun/view/host/ascii-text.ts +11 -1
  335. package/src/renderers/electrobun/view/host/chart-surface.tsx +38 -32
  336. package/src/renderers/electrobun/view/host/mouse.ts +16 -2
  337. package/src/renderers/electrobun/view/main.tsx +27 -2
  338. package/src/renderers/electrobun/view/styles.css +5 -0
  339. package/src/renderers/electrobun/view/toast-host.tsx +18 -0
  340. package/src/renderers/opentui/chart-surface.tsx +5 -1
  341. package/src/renderers/opentui/host.tsx +16 -2
  342. package/src/renderers/opentui/interaction-performance.test.ts +79 -0
  343. package/src/renderers/opentui/interaction-performance.ts +188 -0
  344. package/src/renderers/opentui/start.tsx +26 -1
  345. package/src/renderers/opentui/test-utils.tsx +13 -0
  346. package/src/renderers/opentui/toast-host.tsx +26 -2
  347. package/src/renderers/opentui/ui-host.tsx +1 -0
  348. package/src/sources/provider-router/search.test.ts +191 -0
  349. package/src/sources/provider-router/search.ts +92 -39
  350. package/src/state/app/context/index.tsx +2 -0
  351. package/src/state/app/context/selector.test.tsx +33 -1
  352. package/src/state/hooks/quote-streaming.test.tsx +93 -0
  353. package/src/state/hooks/quote-streaming.ts +106 -30
  354. package/src/state/pane-table-export-registry.ts +19 -0
  355. package/src/theme/color-utils.ts +1 -1
  356. package/src/theme/colors.ts +50 -0
  357. package/src/theme/themes.test.ts +15 -2
  358. package/src/theme/themes.ts +19 -1
  359. package/src/tickers/search/index.test.ts +26 -0
  360. package/src/tickers/search/index.ts +42 -17
  361. package/src/tickers/search/ranking.ts +14 -0
  362. package/src/time-series/chart-data.test.ts +216 -0
  363. package/src/time-series/resolution.test.ts +25 -26
  364. package/src/time-series/resolution.ts +41 -10
  365. package/src/time-series/resolve.ts +7 -0
  366. package/src/time-series/types.ts +3 -1
  367. package/src/time-series/use-chart-resolution.ts +5 -0
  368. package/src/types/config.ts +123 -3
  369. package/src/types/data-provider.ts +11 -0
  370. package/src/types/headless.ts +161 -0
  371. package/src/types/plugin.ts +102 -0
  372. package/src/ui/host.tsx +12 -1
  373. package/src/ui/index.tsx +1 -0
  374. package/src/ui/toast.tsx +8 -4
  375. package/src/utils/format.ts +35 -0
  376. package/src/utils/fuzzy-search.test.ts +94 -0
  377. package/src/utils/fuzzy-search.ts +81 -22
  378. package/src/utils/shortcut-labels.ts +14 -0
  379. package/src/components/chart/core/axis-format.ts +0 -157
  380. package/src/components/chart/core/index.test.ts +0 -1075
  381. package/src/components/chart/core/projection.ts +0 -357
  382. package/src/components/chart/core/render-utils.ts +0 -4
  383. package/src/components/chart/core/renderer.ts +0 -244
  384. package/src/components/chart/core/scene.ts +0 -180
  385. package/src/components/chart/core/time-axis.ts +0 -330
  386. package/src/components/chart/cursor-motion.ts +0 -47
  387. package/src/components/chart/indicators/types.ts +0 -26
  388. package/src/components/chart/market-session.ts +0 -176
  389. package/src/components/chart/multi-line/renderer.test.ts +0 -83
  390. package/src/components/chart/multi-line/renderer.ts +0 -161
  391. package/src/components/chart/multi-line/scene.ts +0 -188
  392. package/src/components/chart/native/raster/layout.ts +0 -129
  393. package/src/components/chart/native/raster/price-chart.ts +0 -244
  394. package/src/components/chart/rendering/chart-draw.ts +0 -270
  395. package/src/components/chart/rendering/geometry.ts +0 -95
  396. package/src/components/chart/rendering/pixel-buffer.ts +0 -267
  397. package/src/components/chart/scatter-chart-renderer.test.ts +0 -31
  398. package/src/components/chart/scatter-chart-renderer.ts +0 -223
  399. package/src/components/chart/static/chart/surface.tsx +0 -358
  400. package/src/components/command-bar/routes/root/article-results.test.ts +0 -83
  401. package/src/components/command-bar/routes/root/article-results.ts +0 -55
  402. package/src/plugins/builtin/news/wire/article-search.test.ts +0 -72
  403. package/src/plugins/builtin/news/wire/article-search.ts +0 -140
  404. package/src/plugins/builtin/substack/api/auth.ts +0 -185
  405. package/src/plugins/builtin/substack/api/cache.ts +0 -82
  406. package/src/plugins/builtin/substack/api/loaders.ts +0 -170
  407. package/src/plugins/builtin/substack/api/store.ts +0 -186
  408. package/src/plugins/builtin/substack/api/types.ts +0 -42
  409. package/src/plugins/builtin/substack/api.test.ts +0 -298
  410. package/src/plugins/builtin/substack/article-detail.tsx +0 -397
  411. package/src/plugins/builtin/substack/article-stack.tsx +0 -133
  412. package/src/plugins/builtin/substack/content.ts +0 -478
  413. package/src/plugins/builtin/substack/feed-tabs.tsx +0 -44
  414. package/src/plugins/builtin/substack/index.tsx +0 -49
  415. package/src/plugins/builtin/substack/login-view.tsx +0 -126
  416. package/src/plugins/builtin/substack/model.test.ts +0 -155
  417. package/src/plugins/builtin/substack/normalize.ts +0 -343
  418. package/src/plugins/builtin/substack/pane-footer.ts +0 -52
  419. package/src/plugins/builtin/substack/pane-state.ts +0 -170
  420. package/src/plugins/builtin/substack/pane.tsx +0 -547
  421. package/src/plugins/builtin/substack/read-state.ts +0 -30
  422. package/src/plugins/builtin/substack/table.ts +0 -111
  423. package/src/plugins/builtin/substack/types.ts +0 -71
  424. package/src/plugins/builtin/substack/utils.ts +0 -131
  425. package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +0 -229
  426. package/src/plugins/ibkr/account-cache.test.ts +0 -102
  427. package/src/plugins/ibkr/account-cache.ts +0 -24
  428. package/src/plugins/ibkr/broker-adapter.ts +0 -286
  429. package/src/plugins/ibkr/config.test.ts +0 -79
  430. package/src/plugins/ibkr/config.ts +0 -250
  431. package/src/plugins/ibkr/dialogs.tsx +0 -40
  432. package/src/plugins/ibkr/flex/index.test.ts +0 -264
  433. package/src/plugins/ibkr/flex/index.ts +0 -367
  434. package/src/plugins/ibkr/flex/statement-client.ts +0 -235
  435. package/src/plugins/ibkr/fundamental-parser.ts +0 -149
  436. package/src/plugins/ibkr/gateway/account-loaders.ts +0 -266
  437. package/src/plugins/ibkr/gateway/account-summary.ts +0 -164
  438. package/src/plugins/ibkr/gateway/client-lock.ts +0 -154
  439. package/src/plugins/ibkr/gateway/connection-events.ts +0 -114
  440. package/src/plugins/ibkr/gateway/connection.ts +0 -152
  441. package/src/plugins/ibkr/gateway/contracts.ts +0 -132
  442. package/src/plugins/ibkr/gateway/fundamentals.ts +0 -83
  443. package/src/plugins/ibkr/gateway/helpers.ts +0 -33
  444. package/src/plugins/ibkr/gateway/history-requests.ts +0 -158
  445. package/src/plugins/ibkr/gateway/history.ts +0 -120
  446. package/src/plugins/ibkr/gateway/instrument-lookup.ts +0 -117
  447. package/src/plugins/ibkr/gateway/market-data.ts +0 -345
  448. package/src/plugins/ibkr/gateway/order-execution.ts +0 -218
  449. package/src/plugins/ibkr/gateway/orders.ts +0 -63
  450. package/src/plugins/ibkr/gateway/price-normalization.test.ts +0 -44
  451. package/src/plugins/ibkr/gateway/price-normalization.ts +0 -50
  452. package/src/plugins/ibkr/gateway/quote-stream-controller.ts +0 -203
  453. package/src/plugins/ibkr/gateway/quote-stream.ts +0 -171
  454. package/src/plugins/ibkr/gateway/selection.ts +0 -51
  455. package/src/plugins/ibkr/gateway/service/index.test.ts +0 -675
  456. package/src/plugins/ibkr/gateway/service/index.ts +0 -429
  457. package/src/plugins/ibkr/gateway/service/lifecycle.ts +0 -191
  458. package/src/plugins/ibkr/gateway/service/manager.ts +0 -52
  459. package/src/plugins/ibkr/gateway/service/market-data.ts +0 -48
  460. package/src/plugins/ibkr/gateway/service/native-loader.ts +0 -12
  461. package/src/plugins/ibkr/gateway/service/native.ts +0 -543
  462. package/src/plugins/ibkr/gateway/timeouts.ts +0 -13
  463. package/src/plugins/ibkr/gateway/types.ts +0 -27
  464. package/src/plugins/ibkr/index.test.tsx +0 -162
  465. package/src/plugins/ibkr/index.tsx +0 -159
  466. package/src/plugins/ibkr/instance-selection.test.ts +0 -120
  467. package/src/plugins/ibkr/instance-selection.ts +0 -36
  468. package/src/plugins/ibkr/portfolio-performance.test.ts +0 -32
  469. package/src/plugins/ibkr/portfolio-performance.ts +0 -129
  470. package/src/plugins/ibkr/trade/badge.tsx +0 -28
  471. package/src/plugins/ibkr/trade/dialogs.tsx +0 -44
  472. package/src/plugins/ibkr/trade/preview-panel.tsx +0 -130
  473. package/src/plugins/ibkr/trade/tab/actions.tsx +0 -443
  474. package/src/plugins/ibkr/trade/tab/field-editors.tsx +0 -79
  475. package/src/plugins/ibkr/trade/tab/footer.ts +0 -53
  476. package/src/plugins/ibkr/trade/tab/header.tsx +0 -167
  477. package/src/plugins/ibkr/trade/tab/index.test.tsx +0 -178
  478. package/src/plugins/ibkr/trade/tab/index.tsx +0 -298
  479. package/src/plugins/ibkr/trade/tab/model.ts +0 -159
  480. package/src/plugins/ibkr/trade/tab/order-request.ts +0 -64
  481. package/src/plugins/ibkr/trade/tab/shortcuts.ts +0 -89
  482. package/src/plugins/ibkr/trade/tab/state-sync.ts +0 -86
  483. package/src/plugins/ibkr/trade/ticket-panel.tsx +0 -301
  484. package/src/plugins/ibkr/trade/utils.test.ts +0 -175
  485. package/src/plugins/ibkr/trade/utils.ts +0 -144
  486. package/src/plugins/ibkr/trading/pane-view.tsx +0 -237
  487. package/src/plugins/ibkr/trading/pane.tsx +0 -332
  488. package/src/plugins/ibkr/trading/state.test.ts +0 -109
  489. package/src/plugins/ibkr/trading/state.ts +0 -335
@@ -1,357 +0,0 @@
1
- import type { PricePoint } from "../../../types/financials";
2
- import type { ChartRenderMode } from "./types";
3
-
4
- export interface ProjectedChartPoint {
5
- date: Date;
6
- open: number;
7
- high: number;
8
- low: number;
9
- close: number;
10
- volume: number;
11
- }
12
-
13
- export interface ChartProjection {
14
- points: ProjectedChartPoint[];
15
- requestedMode: ChartRenderMode;
16
- effectiveMode: ChartRenderMode;
17
- fallbackMode: ChartRenderMode | null;
18
- }
19
-
20
- export interface ProjectChartDataOptions {
21
- ohlcBucketWidth?: number;
22
- ohlcSourceBucketSize?: number;
23
- ohlcTargetBucketCount?: number;
24
- sourceIndexOffset?: number;
25
- }
26
-
27
- export interface IndexProjectionBucket {
28
- index: number;
29
- start: number;
30
- end: number;
31
- }
32
-
33
- interface StableOhlcProjectionOptionsInput {
34
- pointCount: number;
35
- sourceIndexOffset: number;
36
- bucketWidth: number;
37
- navigationPointCount?: number;
38
- countRatioTolerance?: number;
39
- }
40
-
41
- const DEFAULT_OHLC_COUNT_RATIO_TOLERANCE = 1.2;
42
-
43
- function coerceDate(value: Date | string | number): Date {
44
- return value instanceof Date ? value : new Date(value);
45
- }
46
-
47
- function getRequestedRenderMode(mode?: ChartRenderMode, compact = false): ChartRenderMode {
48
- if (compact) return "area";
49
- return mode ?? "area";
50
- }
51
-
52
- function isOhlcProjectionMode(mode: ChartRenderMode): boolean {
53
- return mode === "candles" || mode === "ohlc" || mode === "hlc";
54
- }
55
-
56
- export function resolveRenderMode(
57
- mode: ChartRenderMode | undefined,
58
- chartWidth: number,
59
- compact = false,
60
- ): { requestedMode: ChartRenderMode; effectiveMode: ChartRenderMode; fallbackMode: ChartRenderMode | null } {
61
- const requestedMode = getRequestedRenderMode(mode, compact);
62
- if (compact) {
63
- return {
64
- requestedMode,
65
- effectiveMode: "area",
66
- fallbackMode: null,
67
- };
68
- }
69
-
70
- let effectiveMode = requestedMode;
71
- switch (requestedMode) {
72
- case "candles":
73
- if (chartWidth < 28) effectiveMode = "line";
74
- else if (chartWidth < 40) effectiveMode = "ohlc";
75
- break;
76
- case "ohlc":
77
- case "hlc":
78
- if (chartWidth < 28) effectiveMode = "line";
79
- break;
80
- }
81
-
82
- return {
83
- requestedMode,
84
- effectiveMode,
85
- fallbackMode: effectiveMode === requestedMode ? null : effectiveMode,
86
- };
87
- }
88
-
89
- function normalizePoint(point: PricePoint): ProjectedChartPoint {
90
- const open = point.open ?? point.close;
91
- const high = point.high ?? point.close;
92
- const low = point.low ?? point.close;
93
-
94
- return {
95
- date: coerceDate(point.date as Date | string | number),
96
- open,
97
- high,
98
- low,
99
- close: point.close,
100
- volume: point.volume ?? 0,
101
- };
102
- }
103
-
104
- function getMinimumPositiveDateGapMs(points: readonly ProjectedChartPoint[]): number | null {
105
- let minimum = Number.POSITIVE_INFINITY;
106
- for (let index = 1; index < points.length; index += 1) {
107
- const previous = points[index - 1]!.date.getTime();
108
- const current = points[index]!.date.getTime();
109
- const gap = current - previous;
110
- if (Number.isFinite(gap) && gap > 0 && gap < minimum) {
111
- minimum = gap;
112
- }
113
- }
114
- return Number.isFinite(minimum) ? minimum : null;
115
- }
116
-
117
- function aggregateOhlcBucket(bucket: readonly ProjectedChartPoint[]): ProjectedChartPoint {
118
- const first = bucket[0]!;
119
- const last = bucket[bucket.length - 1]!;
120
- let high = first.high;
121
- let low = first.low;
122
- let volume = 0;
123
-
124
- for (const point of bucket) {
125
- high = Math.max(high, point.high);
126
- low = Math.min(low, point.low);
127
- volume += point.volume;
128
- }
129
-
130
- return {
131
- date: last.date,
132
- open: first.open,
133
- high,
134
- low,
135
- close: last.close,
136
- volume,
137
- };
138
- }
139
-
140
- export function buildIndexProjectionBuckets(
141
- itemCount: number,
142
- targetWidth: number,
143
- ): IndexProjectionBucket[] {
144
- const normalizedItemCount = Math.max(Math.floor(itemCount), 0);
145
- if (normalizedItemCount === 0) return [];
146
-
147
- const bucketCount = Math.min(normalizedItemCount, Math.max(Math.floor(targetWidth), 1));
148
- const bucketSize = normalizedItemCount / bucketCount;
149
-
150
- return Array.from({ length: bucketCount }, (_, index) => {
151
- const start = Math.floor(index * bucketSize);
152
- const end = Math.min(
153
- normalizedItemCount,
154
- Math.max(Math.floor((index + 1) * bucketSize), start + 1),
155
- );
156
- return { index, start, end };
157
- });
158
- }
159
-
160
- export function selectRepresentativeCloseValue<T>(
161
- bucket: readonly T[],
162
- index: number,
163
- getClose: (item: T) => number,
164
- ): T {
165
- let best = bucket[0] as T;
166
- if (index % 2 === 0) {
167
- for (const item of bucket) {
168
- if (getClose(item) > getClose(best)) best = item;
169
- }
170
- } else {
171
- for (const item of bucket) {
172
- if (getClose(item) < getClose(best)) best = item;
173
- }
174
- }
175
- return best;
176
- }
177
-
178
- function bucketOhlcBySourceIndex(
179
- normalizedPoints: readonly ProjectedChartPoint[],
180
- bucketSize: number,
181
- sourceIndexOffset: number,
182
- targetBucketCount?: number,
183
- ): ProjectedChartPoint[] {
184
- const normalizedBucketSize = Math.max(Math.floor(bucketSize), 1);
185
- const normalizedSourceIndexOffset = Math.max(Math.floor(sourceIndexOffset), 0);
186
- const maximumBucketCount = targetBucketCount === undefined
187
- ? Number.POSITIVE_INFINITY
188
- : Math.max(Math.floor(targetBucketCount), 1);
189
- const result: ProjectedChartPoint[] = [];
190
- const firstBucketStart = Math.floor(normalizedSourceIndexOffset / normalizedBucketSize) * normalizedBucketSize;
191
- const endSourceIndex = normalizedSourceIndexOffset + normalizedPoints.length;
192
-
193
- for (
194
- let bucketStart = firstBucketStart;
195
- bucketStart < endSourceIndex && result.length < maximumBucketCount;
196
- bucketStart += normalizedBucketSize
197
- ) {
198
- const bucketEnd = bucketStart + normalizedBucketSize;
199
- const start = Math.max(bucketStart - normalizedSourceIndexOffset, 0);
200
- const end = Math.min(bucketEnd - normalizedSourceIndexOffset, normalizedPoints.length);
201
- if (end <= start) continue;
202
- const bucket = normalizedPoints.slice(start, end);
203
- if (bucket.length === 0) continue;
204
- result.push(aggregateOhlcBucket(bucket));
205
- }
206
-
207
- return result;
208
- }
209
-
210
- export function resolveStableOhlcProjectionOptions({
211
- pointCount,
212
- sourceIndexOffset,
213
- bucketWidth,
214
- navigationPointCount = 0,
215
- countRatioTolerance = DEFAULT_OHLC_COUNT_RATIO_TOLERANCE,
216
- }: StableOhlcProjectionOptionsInput): ProjectChartDataOptions {
217
- const ohlcBucketWidth = Math.max(Math.floor(bucketWidth), 1);
218
- const ohlcProjectionWidth = Math.max(Math.floor(ohlcBucketWidth / 2), 1);
219
- const normalizedPointCount = Math.max(Math.floor(pointCount), 0);
220
- const normalizedNavigationPointCount = Math.max(Math.floor(navigationPointCount), 0);
221
- const canUseNavigationCount = normalizedNavigationPointCount > 0
222
- && normalizedPointCount > 0
223
- && Math.max(normalizedNavigationPointCount, normalizedPointCount)
224
- / Math.max(Math.min(normalizedNavigationPointCount, normalizedPointCount), 1)
225
- <= countRatioTolerance;
226
- const stableSourceCount = canUseNavigationCount
227
- ? normalizedNavigationPointCount
228
- : normalizedPointCount;
229
- const ohlcSourceBucketSize = Math.max(Math.ceil(stableSourceCount / ohlcProjectionWidth), 1);
230
- const ohlcTargetBucketCount = Math.max(Math.ceil(stableSourceCount / ohlcSourceBucketSize), 1);
231
-
232
- return {
233
- ohlcBucketWidth,
234
- ohlcSourceBucketSize,
235
- ohlcTargetBucketCount,
236
- sourceIndexOffset,
237
- };
238
- }
239
-
240
- /**
241
- * Downsample close-driven chart data to fit the target width.
242
- * Uses representative closes so line/area charts preserve the broad shape.
243
- */
244
- function projectCloseSeries(
245
- points: PricePoint[],
246
- targetWidth: number,
247
- ): ProjectedChartPoint[] {
248
- if (points.length === 0) return [];
249
- return buildIndexProjectionBuckets(points.length, targetWidth).map((bucket) => (
250
- normalizePoint(selectRepresentativeCloseValue(
251
- points.slice(bucket.start, bucket.end),
252
- bucket.index,
253
- (point) => point.close,
254
- ))
255
- ));
256
- }
257
-
258
- /**
259
- * Bucket OHLC data so each rendered column preserves open, close, high, low, and volume.
260
- *
261
- * The default path aligns buckets by timestamp. Interactive manual panning can pass
262
- * ohlcSourceBucketSize/ohlcTargetBucketCount to align buckets by source bar index,
263
- * which keeps the rendered candle count stable as partial edge buckets enter/leave.
264
- */
265
- export function bucketOhlcSeries(
266
- points: PricePoint[],
267
- targetWidth: number,
268
- options: ProjectChartDataOptions = {},
269
- ): ProjectedChartPoint[] {
270
- if (points.length === 0) return [];
271
- const normalizedPoints = points.map(normalizePoint);
272
- if (points.length <= targetWidth) return normalizedPoints;
273
- if (options.ohlcSourceBucketSize !== undefined) {
274
- return bucketOhlcBySourceIndex(
275
- normalizedPoints,
276
- options.ohlcSourceBucketSize,
277
- options.sourceIndexOffset ?? 0,
278
- options.ohlcTargetBucketCount,
279
- );
280
- }
281
-
282
- const result: ProjectedChartPoint[] = [];
283
- const minimumGapMs = getMinimumPositiveDateGapMs(normalizedPoints);
284
- const firstTime = normalizedPoints[0]!.date.getTime();
285
- const lastTime = normalizedPoints[normalizedPoints.length - 1]!.date.getTime();
286
- if (
287
- minimumGapMs
288
- && Number.isFinite(firstTime)
289
- && Number.isFinite(lastTime)
290
- && lastTime > firstTime
291
- ) {
292
- const spanMs = Math.max(lastTime - firstTime, minimumGapMs);
293
- const rawBucketDurationMs = spanMs / Math.max(targetWidth, 1);
294
- const bucketDurationMs = Math.max(Math.ceil(rawBucketDurationMs / minimumGapMs) * minimumGapMs, minimumGapMs);
295
- let currentBucketKey: number | null = null;
296
- let currentBucket: ProjectedChartPoint[] = [];
297
-
298
- for (const point of normalizedPoints) {
299
- const time = point.date.getTime();
300
- const bucketKey = Math.floor(time / bucketDurationMs);
301
- if (currentBucketKey !== null && bucketKey !== currentBucketKey) {
302
- result.push(aggregateOhlcBucket(currentBucket));
303
- currentBucket = [];
304
- }
305
- currentBucketKey = bucketKey;
306
- currentBucket.push(point);
307
- }
308
-
309
- if (currentBucket.length > 0) {
310
- result.push(aggregateOhlcBucket(currentBucket));
311
- }
312
-
313
- return result;
314
- }
315
-
316
- const bucketSize = Math.max(Math.ceil(normalizedPoints.length / Math.max(targetWidth, 1)), 1);
317
- const sourceIndexOffset = Math.max(Math.floor(options.sourceIndexOffset ?? 0), 0);
318
- const firstBucketStart = Math.floor(sourceIndexOffset / bucketSize) * bucketSize;
319
- const endSourceIndex = sourceIndexOffset + normalizedPoints.length;
320
-
321
- for (let bucketStart = firstBucketStart; bucketStart < endSourceIndex; bucketStart += bucketSize) {
322
- const bucketEnd = bucketStart + bucketSize;
323
- const start = Math.max(bucketStart - sourceIndexOffset, 0);
324
- const end = Math.min(bucketEnd - sourceIndexOffset, normalizedPoints.length);
325
- if (end <= start) continue;
326
- const bucket = normalizedPoints.slice(start, end);
327
- if (bucket.length === 0) continue;
328
- result.push(aggregateOhlcBucket(bucket));
329
- }
330
-
331
- return result;
332
- }
333
-
334
- export function projectChartData(
335
- points: PricePoint[],
336
- targetWidth: number,
337
- mode: ChartRenderMode | undefined,
338
- compact = false,
339
- options: ProjectChartDataOptions = {},
340
- ): ChartProjection {
341
- const { requestedMode, effectiveMode, fallbackMode } = resolveRenderMode(mode, targetWidth, compact);
342
- const ohlcBucketWidth = options.ohlcBucketWidth ?? targetWidth;
343
- const projectionWidth = isOhlcProjectionMode(effectiveMode)
344
- ? Math.max(Math.floor(ohlcBucketWidth / 2), 1)
345
- : targetWidth;
346
-
347
- const projectedPoints = isOhlcProjectionMode(effectiveMode)
348
- ? bucketOhlcSeries(points, projectionWidth, options)
349
- : projectCloseSeries(points, projectionWidth);
350
-
351
- return {
352
- points: projectedPoints,
353
- requestedMode,
354
- effectiveMode,
355
- fallbackMode,
356
- };
357
- }
@@ -1,4 +0,0 @@
1
- export function normalizeCount(value: number, min: number): number {
2
- if (!Number.isFinite(value)) return min;
3
- return Math.max(Math.floor(value), min);
4
- }
@@ -1,244 +0,0 @@
1
- import type { PixelBuffer } from "./types";
2
- import type { ProjectedChartPoint } from "./data";
3
- import { buildTimeAxis } from "./time-axis";
4
- import {
5
- formatAxisValue,
6
- getAxisFractionDigitFloor,
7
- resolveAxisFractionDigits,
8
- } from "./axis-format";
9
- import {
10
- bufferToBrailleLines,
11
- createPixelBuffer,
12
- drawCrosshair,
13
- drawGridLines,
14
- type StyledContent,
15
- } from "../rendering/pixel-buffer";
16
- import {
17
- isHighLowMode,
18
- } from "../rendering/geometry";
19
- import {
20
- drawAreaChart,
21
- drawCandlestickChart,
22
- drawIndicatorOverlays,
23
- drawLineSeries,
24
- drawOhlcChart,
25
- drawSessionBackgrounds,
26
- drawVolumeBars,
27
- } from "../rendering/chart-draw";
28
- import {
29
- buildChartScene,
30
- type RenderChartOptions,
31
- } from "./scene";
32
-
33
- export { buildCursorTimeAxisSegments, buildTimeAxis } from "./time-axis";
34
- export {
35
- formatAxisCell,
36
- formatAxisValue,
37
- formatCursorAxisValue,
38
- formatPrice,
39
- resolveAxisFractionDigits,
40
- resolveChartAxisWidth,
41
- } from "./axis-format";
42
- export { resolveChartPalette } from "./palette";
43
- export type { ResolvedChartPalette } from "./palette";
44
- export {
45
- bufferToBrailleLines,
46
- createPixelBuffer,
47
- drawCrosshair,
48
- drawGridLines,
49
- drawLine,
50
- } from "../rendering/pixel-buffer";
51
- export { getPointTerminalColumn } from "../rendering/geometry";
52
- export type { StyledContent } from "../rendering/pixel-buffer";
53
- export {
54
- buildChartScene,
55
- getActivePointIndex,
56
- type ChartScene,
57
- type RenderChartOptions,
58
- } from "./scene";
59
-
60
- // ---------------------------------------------------------------------------
61
- // Grid lines & price axis
62
- // ---------------------------------------------------------------------------
63
-
64
- export function computeGridLines(
65
- min: number,
66
- max: number,
67
- chartTop: number,
68
- chartBottom: number,
69
- numLines: number,
70
- ): { y: number; price: number }[] {
71
- const range = max - min || 1;
72
- const chartH = chartBottom - chartTop;
73
- const result: { y: number; price: number }[] = [];
74
-
75
- for (let i = 0; i <= numLines; i++) {
76
- const frac = i / numLines;
77
- result.push({
78
- y: chartTop + Math.round(frac * chartH),
79
- price: max - frac * range,
80
- });
81
- }
82
-
83
- return result;
84
- }
85
-
86
- // ---------------------------------------------------------------------------
87
- // Main render entry point
88
- // ---------------------------------------------------------------------------
89
-
90
- export interface RenderChartResult {
91
- lines: StyledContent[];
92
- axisLabels: { row: number; label: string }[];
93
- timeLabels: string;
94
- activePoint: ProjectedChartPoint | null;
95
- priceAtCursor: number | null;
96
- crosshairPrice: number | null;
97
- dateAtCursor: Date | null;
98
- changeAtCursor: number | null;
99
- changePctAtCursor: number | null;
100
- cursorColumn: number | null;
101
- cursorRow: number | null;
102
- axisFractionDigits: number | null;
103
- priceRange: number | null;
104
- /** Raw pixel buffer for GPU/Kitty rendering path */
105
- pixelBuffer: PixelBuffer | null;
106
- }
107
-
108
- export function renderChart(
109
- points: ProjectedChartPoint[],
110
- opts: RenderChartOptions,
111
- ): RenderChartResult {
112
- const scene = buildChartScene(points, opts);
113
- if (!scene) {
114
- return {
115
- lines: [],
116
- axisLabels: [],
117
- timeLabels: "",
118
- activePoint: null,
119
- priceAtCursor: null,
120
- crosshairPrice: null,
121
- dateAtCursor: null,
122
- changeAtCursor: null,
123
- changePctAtCursor: null,
124
- cursorColumn: null,
125
- cursorRow: null,
126
- axisFractionDigits: null,
127
- priceRange: null,
128
- pixelBuffer: null,
129
- };
130
- }
131
-
132
- const { width, height, showVolume, volumeHeight, colors: palette, mode } = scene;
133
- const axisMode = opts.axisMode ?? "price";
134
- const currency = opts.currency ?? "USD";
135
- const assetCategory = opts.assetCategory;
136
-
137
- // Braille resolution: 2 dot-columns per terminal column, 4 dot-rows per terminal row
138
- const dotWidth = width * 2;
139
- const volTermRows = showVolume ? volumeHeight : 0;
140
- const chartTermRows = height - volTermRows;
141
- const totalDotH = height * 4;
142
- const chartDotBottom = chartTermRows * 4 - 1;
143
- const volDotTop = chartTermRows * 4;
144
- const volDotBottom = totalDotH - 1;
145
-
146
- const buf = createPixelBuffer(dotWidth, totalDotH);
147
- const { min, max } = scene;
148
- const priceRange = max - min;
149
-
150
- const gridLines = computeGridLines(min, max, 0, chartDotBottom, 3);
151
- const axisFractionDigits = axisMode === "price"
152
- ? resolveAxisFractionDigits(
153
- gridLines.map((line) => line.price),
154
- (price, fixedFractionDigits) => formatAxisValue(
155
- price,
156
- axisMode,
157
- points[0]!.close,
158
- currency,
159
- assetCategory,
160
- priceRange,
161
- fixedFractionDigits,
162
- ),
163
- getAxisFractionDigitFloor(assetCategory, priceRange),
164
- )
165
- : null;
166
- drawSessionBackgrounds(
167
- buf,
168
- points,
169
- scene.sessionBackgroundSpans,
170
- 0,
171
- showVolume ? volDotBottom : chartDotBottom,
172
- palette,
173
- );
174
- drawGridLines(buf, gridLines.map((line) => line.y), palette.gridColor);
175
-
176
- switch (mode) {
177
- case "area":
178
- drawAreaChart(buf, points, 0, chartDotBottom, palette.lineColor, palette.fillColor, min, max);
179
- break;
180
- case "line":
181
- drawLineSeries(buf, points, 0, chartDotBottom, palette.lineColor, min, max);
182
- break;
183
- case "candles":
184
- drawCandlestickChart(buf, points, 0, chartDotBottom, palette, min, max);
185
- break;
186
- case "ohlc":
187
- drawOhlcChart(buf, points, 0, chartDotBottom, palette, min, max, "ohlc");
188
- break;
189
- case "hlc":
190
- drawOhlcChart(buf, points, 0, chartDotBottom, palette, min, max, "hlc");
191
- break;
192
- }
193
-
194
- if (showVolume && volTermRows > 0) {
195
- drawVolumeBars(
196
- buf,
197
- points,
198
- volDotTop,
199
- volDotBottom,
200
- palette.volumeUp,
201
- palette.volumeDown,
202
- isHighLowMode(mode) ? "openClose" : "previousClose",
203
- mode,
204
- );
205
- }
206
-
207
- if (opts.indicators) {
208
- drawIndicatorOverlays(buf, opts.indicators, points.length, 0, chartDotBottom, min, max, mode);
209
- }
210
-
211
- // Cursor mapping stays in terminal-column space
212
- const { activePoint, priceAtCursor, crosshairPrice, dateAtCursor, changeAtCursor, changePctAtCursor } = scene;
213
-
214
- if (scene.cursorDotX !== null) {
215
- drawCrosshair(buf, scene.cursorDotX, 0, showVolume ? volDotBottom : chartDotBottom, palette.crosshairColor);
216
- }
217
-
218
- const axisLabelsByRow = new Map<number, string>();
219
- for (const line of gridLines) {
220
- axisLabelsByRow.set(
221
- Math.min(Math.floor(line.y / 4), Math.max(chartTermRows - 1, 0)),
222
- formatAxisValue(line.price, axisMode, points[0]!.close, currency, assetCategory, priceRange, axisFractionDigits ?? undefined),
223
- );
224
- }
225
-
226
- const timeAxisDates = opts.timeAxisDates ?? points.map((point) => point.date);
227
-
228
- return {
229
- lines: bufferToBrailleLines(buf),
230
- axisLabels: [...axisLabelsByRow.entries()].map(([row, label]) => ({ row, label })),
231
- timeLabels: buildTimeAxis(timeAxisDates, width),
232
- activePoint,
233
- priceAtCursor,
234
- crosshairPrice,
235
- dateAtCursor,
236
- changeAtCursor,
237
- changePctAtCursor,
238
- cursorColumn: scene.cursorColumn,
239
- cursorRow: scene.cursorRow,
240
- axisFractionDigits,
241
- priceRange,
242
- pixelBuffer: buf,
243
- };
244
- }