gloomberb 0.16.1 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (574) hide show
  1. package/README.md +2 -1
  2. package/package.json +2 -1
  3. package/src/api-client/beneficial-owners.ts +92 -0
  4. package/src/api-client/data.ts +26 -8
  5. package/src/api-client/errors.ts +12 -0
  6. package/src/api-client/geo.ts +363 -0
  7. package/src/api-client/index.ts +2 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/paths.ts +30 -1
  10. package/src/api-client/perps.ts +37 -0
  11. package/src/api-client/request.ts +5 -2
  12. package/src/api-client/types.ts +2 -0
  13. package/src/brokers/account-cache.ts +24 -0
  14. package/src/cli/commands/command-utils.ts +8 -0
  15. package/src/cli/commands/crypto-hints.ts +75 -0
  16. package/src/cli/commands/market.ts +414 -106
  17. package/src/cli/commands/overview.ts +77 -32
  18. package/src/cli/commands/ticker.ts +101 -43
  19. package/src/cli/desktop-pane-shot.ts +34 -4
  20. package/src/cli/freshness.ts +61 -0
  21. package/src/cli/help.ts +1 -0
  22. package/src/cli/helpers.ts +4 -8
  23. package/src/cli/index.ts +12 -2
  24. package/src/cli/listing-arg.ts +321 -0
  25. package/src/cli/pane-functions/access-gate.ts +42 -0
  26. package/src/cli/pane-functions/catalog.ts +28 -1
  27. package/src/cli/pane-functions/data.ts +3 -1
  28. package/src/cli/pane-functions/dom.ts +20 -2
  29. package/src/cli/pane-functions/freshness.ts +400 -0
  30. package/src/cli/pane-functions/function-help.ts +27 -20
  31. package/src/cli/pane-functions/headless.ts +39 -11
  32. package/src/cli/pane-functions/index.ts +15 -4
  33. package/src/cli/pane-functions/options.ts +3 -0
  34. package/src/cli/pane-functions/report.ts +4 -0
  35. package/src/cli/pane-functions/resolver.ts +35 -7
  36. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  37. package/src/cli/pane-functions/screenshot.ts +7 -3
  38. package/src/cli/result.ts +41 -27
  39. package/src/cli/ticker-resolution.ts +7 -5
  40. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  41. package/src/components/chart/composite/drawing-store.ts +59 -0
  42. package/src/components/chart/composite/legend.tsx +319 -0
  43. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  44. package/src/components/chart/composite/panel-gestures.ts +59 -0
  45. package/src/components/chart/composite/panel-labels.ts +107 -0
  46. package/src/components/chart/composite/panel-surface.tsx +876 -0
  47. package/src/components/chart/composite/tool-catalog.ts +98 -0
  48. package/src/components/chart/composite/toolbar.tsx +186 -0
  49. package/src/components/chart/composite/tools.ts +8 -0
  50. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  51. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  52. package/src/components/command-bar/list/model.ts +5 -0
  53. package/src/components/command-bar/list/view.tsx +16 -3
  54. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  55. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  56. package/src/components/command-bar/workflow/ops.ts +1 -1
  57. package/src/components/command-bar/workflow/tickers.ts +6 -0
  58. package/src/components/data-table/view.tsx +29 -10
  59. package/src/components/feedback-dialog.tsx +2 -1
  60. package/src/components/form-modal/field-row.tsx +2 -2
  61. package/src/components/layout/detached-pane-shell.tsx +6 -3
  62. package/src/components/layout/pane/content.tsx +23 -10
  63. package/src/components/layout/pane/error-boundary.tsx +103 -0
  64. package/src/components/layout/pane/footer/registration.tsx +68 -23
  65. package/src/components/layout/pane/header.tsx +11 -11
  66. package/src/components/layout/shell/menu.ts +2 -1
  67. package/src/components/layout/shell/pane/actions.ts +2 -1
  68. package/src/components/layout/shell/pane/layers.tsx +14 -3
  69. package/src/components/metric-treemap/heat-surface.tsx +43 -16
  70. package/src/components/metric-treemap/heat-tiles.ts +18 -0
  71. package/src/components/metric-treemap/layout.ts +2 -0
  72. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  73. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  74. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  75. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  76. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  77. package/src/components/ticker/list-table-view.tsx +13 -1
  78. package/src/components/ui/fields.tsx +8 -0
  79. package/src/components/ui/range-track.tsx +10 -3
  80. package/src/components/ui/status.tsx +8 -2
  81. package/src/components/ui/tabs.tsx +7 -4
  82. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  83. package/src/data/config/store/normalize.ts +17 -1
  84. package/src/i18n/es.ts +19 -1
  85. package/src/i18n/ja.ts +19 -1
  86. package/src/i18n/ko.ts +19 -1
  87. package/src/i18n/zh-cn.ts +19 -1
  88. package/src/i18n/zh-tw.ts +19 -1
  89. package/src/market-data/coordinator/chart.ts +1 -1
  90. package/src/market-data/coordinator/quotes.ts +23 -4
  91. package/src/market-data/fx-closes.ts +72 -0
  92. package/src/market-data/market/freshness.ts +78 -6
  93. package/src/market-data/market/session-close-note.ts +57 -0
  94. package/src/market-data/market/status.ts +151 -0
  95. package/src/market-data/published-apac-sessions.ts +66 -0
  96. package/src/market-data/quotes/contributions.ts +2 -0
  97. package/src/market-data/quotes/resolution.ts +2 -0
  98. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  99. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  100. package/src/plugins/builtin/alerts/cli.ts +10 -5
  101. package/src/plugins/builtin/alerts/index.tsx +1 -0
  102. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  103. package/src/plugins/builtin/analytics/risk-client.ts +191 -66
  104. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  105. package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
  106. package/src/plugins/builtin/analytics/risk-model.ts +45 -17
  107. package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
  108. package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
  109. package/src/plugins/builtin/attention/headless.ts +6 -4
  110. package/src/plugins/builtin/attention/index.tsx +1 -1
  111. package/src/plugins/builtin/attention/pane.tsx +1 -1
  112. package/src/plugins/builtin/awards/headless.ts +1 -0
  113. package/src/plugins/builtin/awards/pane.tsx +1 -1
  114. package/src/plugins/builtin/backtest/headless.ts +1 -0
  115. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  116. package/src/plugins/builtin/buildout/index.tsx +1 -0
  117. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  118. package/src/plugins/builtin/cds/headless.ts +2 -0
  119. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  120. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  121. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  122. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  123. package/src/plugins/builtin/chat/channels.ts +19 -3
  124. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  125. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  126. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  127. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  128. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  129. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  130. package/src/plugins/builtin/chat/index.tsx +1 -0
  131. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  132. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  133. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  134. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  135. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  136. package/src/plugins/builtin/chat/message/types.ts +14 -2
  137. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  138. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  139. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  140. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  141. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  142. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  143. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  144. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  145. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  146. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  147. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  148. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  149. package/src/plugins/builtin/correlation/compute.ts +59 -16
  150. package/src/plugins/builtin/correlation/geo.ts +34 -0
  151. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  152. package/src/plugins/builtin/correlation/headless.ts +42 -8
  153. package/src/plugins/builtin/correlation/history.ts +2 -0
  154. package/src/plugins/builtin/correlation/index.tsx +68 -14
  155. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  156. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  157. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  158. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  159. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  160. package/src/plugins/builtin/correlation/settings.ts +1 -1
  161. package/src/plugins/builtin/cot/headless.ts +6 -3
  162. package/src/plugins/builtin/cot/index.tsx +3 -3
  163. package/src/plugins/builtin/cot/model.ts +36 -3
  164. package/src/plugins/builtin/cpi/headless.ts +4 -0
  165. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  166. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  167. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  168. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  169. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  170. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  171. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  172. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  173. package/src/plugins/builtin/doe/headless.ts +7 -0
  174. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  175. package/src/plugins/builtin/earnings/headless.ts +5 -0
  176. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  177. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  178. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  179. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  180. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  181. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  182. package/src/plugins/builtin/econ/index.tsx +1 -0
  183. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  184. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  185. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  186. package/src/plugins/builtin/executives/index.tsx +1 -0
  187. package/src/plugins/builtin/exposure/headless.ts +3 -1
  188. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  189. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  190. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  191. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  192. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  193. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  194. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  195. package/src/plugins/builtin/gpu/headless.ts +7 -3
  196. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  197. package/src/plugins/builtin/gpu/model.ts +27 -1
  198. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  199. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  200. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  201. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  202. package/src/plugins/builtin/holders/headless.ts +139 -5
  203. package/src/plugins/builtin/holders/index.tsx +10 -3
  204. package/src/plugins/builtin/holders/pane.tsx +20 -3
  205. package/src/plugins/builtin/holders/report-header.ts +95 -0
  206. package/src/plugins/builtin/holders/table-model.ts +20 -5
  207. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  208. package/src/plugins/builtin/holders/types.ts +2 -1
  209. package/src/plugins/builtin/insider/headless.ts +2 -0
  210. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  211. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  212. package/src/plugins/builtin/jobs/headless.ts +1 -0
  213. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  214. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  215. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  216. package/src/plugins/builtin/market-heatmap/data.ts +2 -0
  217. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  218. package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
  219. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  220. package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
  221. package/src/plugins/builtin/market-movers/headless.ts +2 -0
  222. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  223. package/src/plugins/builtin/members/client.ts +20 -3
  224. package/src/plugins/builtin/members/headless.ts +5 -3
  225. package/src/plugins/builtin/members/model.ts +10 -2
  226. package/src/plugins/builtin/members/pane.tsx +13 -6
  227. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  228. package/src/plugins/builtin/mna/headless.ts +1 -0
  229. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  230. package/src/plugins/builtin/news/headless.ts +2 -0
  231. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  232. package/src/plugins/builtin/notes/cli.ts +14 -6
  233. package/src/plugins/builtin/notes/index.tsx +1 -0
  234. package/src/plugins/builtin/openfda/index.tsx +1 -0
  235. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  236. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  237. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  238. package/src/plugins/builtin/pe-band/client.ts +48 -3
  239. package/src/plugins/builtin/pe-band/headless.ts +25 -7
  240. package/src/plugins/builtin/pe-band/model.ts +92 -16
  241. package/src/plugins/builtin/pe-band/pane.tsx +33 -16
  242. package/src/plugins/builtin/perps/client.ts +50 -3
  243. package/src/plugins/builtin/perps/headless.ts +144 -16
  244. package/src/plugins/builtin/perps/index.tsx +6 -6
  245. package/src/plugins/builtin/perps/model.ts +189 -12
  246. package/src/plugins/builtin/perps/pane.tsx +248 -47
  247. package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
  248. package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
  249. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  250. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  251. package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
  252. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  253. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  254. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  255. package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
  256. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  257. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  258. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  259. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  260. package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
  261. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  262. package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
  263. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  264. package/src/plugins/builtin/power/headless.ts +3 -1
  265. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  266. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  267. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  268. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  269. package/src/plugins/builtin/research/events-headless.ts +2 -0
  270. package/src/plugins/builtin/research/headless.ts +2 -0
  271. package/src/plugins/builtin/research/index.tsx +1 -0
  272. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  273. package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
  274. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  275. package/src/plugins/builtin/research-search/index.tsx +1 -0
  276. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  277. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  278. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  279. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  280. package/src/plugins/builtin/scanner/headless.ts +14 -0
  281. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  282. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  283. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  284. package/src/plugins/builtin/sec/forms.ts +12 -0
  285. package/src/plugins/builtin/sec/headless.ts +2 -0
  286. package/src/plugins/builtin/sectors/client.ts +1 -0
  287. package/src/plugins/builtin/sectors/headless.ts +9 -1
  288. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  289. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  290. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  291. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  292. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  293. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  294. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  295. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  296. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  297. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  298. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  299. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  300. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  301. package/src/plugins/builtin/themes/headless.ts +3 -0
  302. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  303. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  304. package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
  305. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  306. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
  307. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
  308. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  309. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  310. package/src/plugins/builtin/volatility/headless.ts +6 -1
  311. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  312. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
  313. package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
  314. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  315. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  316. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  317. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  318. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  319. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  320. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  321. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
  322. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  323. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  324. package/src/plugins/builtin/world-venue-map/index.ts +67 -4
  325. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
  326. package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
  327. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  328. package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
  329. package/src/plugins/builtin/world-venue-map/model.ts +7 -4
  330. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
  331. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  332. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  333. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  334. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  335. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  336. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  337. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  338. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  339. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  340. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  341. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  342. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  343. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  344. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  345. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  346. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  347. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  348. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  349. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  350. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  351. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  352. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  353. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  354. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  355. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  356. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  357. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  358. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  359. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  360. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  361. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  362. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  363. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  364. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  365. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  366. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  367. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  368. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  369. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  370. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  371. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  372. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  373. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  374. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  375. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  376. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  377. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  378. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  379. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  380. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  381. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  382. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  383. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  384. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  385. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  386. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  387. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  388. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  389. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  390. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  391. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  392. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  393. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  394. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  395. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  396. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  397. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  398. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  399. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  400. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  401. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  402. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  403. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  404. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  405. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  406. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  407. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  408. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  409. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  410. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  411. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  412. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  413. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  414. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  415. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  416. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  417. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  418. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
  524. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  525. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  526. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  527. package/src/plugins/loader.ts +13 -1
  528. package/src/plugins/registry/pane-settings.ts +1 -0
  529. package/src/renderers/dom/build-assets.ts +81 -3
  530. package/src/renderers/dom/data-table/row.tsx +2 -0
  531. package/src/renderers/dom/desktop/controls.tsx +7 -3
  532. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  533. package/src/renderers/dom/desktop/popover.tsx +73 -14
  534. package/src/renderers/dom/host/input.tsx +14 -3
  535. package/src/renderers/dom/styles.css +6 -7
  536. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  537. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -0
  538. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  539. package/src/renderers/opentui/host.tsx +5 -0
  540. package/src/sources/gloomberb-cloud/index.ts +25 -4
  541. package/src/sources/gloomberb-cloud/normalizers.ts +27 -3
  542. package/src/sources/provider-router/cached-routes.ts +4 -1
  543. package/src/sources/provider-router/financials.ts +8 -7
  544. package/src/sources/provider-router/history.ts +15 -10
  545. package/src/sources/sec-registrant.ts +75 -0
  546. package/src/state/app/context/index.tsx +24 -8
  547. package/src/state/hooks/quote-streaming.ts +41 -26
  548. package/src/sync/core-contributors.ts +4 -0
  549. package/src/telemetry/crash-reports.ts +4 -1
  550. package/src/test-support/cli-context.ts +10 -2
  551. package/src/theme/heat-colors.ts +266 -84
  552. package/src/time-series/resolve.ts +1 -1
  553. package/src/time-series/use-chart-resolution.ts +1 -1
  554. package/src/types/context-menu.ts +6 -0
  555. package/src/types/data-provider.ts +2 -0
  556. package/src/types/financials.ts +3 -0
  557. package/src/types/headless.ts +79 -2
  558. package/src/types/plugin.ts +20 -1
  559. package/src/types/ticker.ts +15 -0
  560. package/src/ui/host.tsx +14 -0
  561. package/src/updater/index.ts +9 -11
  562. package/src/utils/async-deadline.ts +21 -0
  563. package/src/utils/cli-output.ts +5 -1
  564. package/src/utils/crypto-pair.ts +41 -0
  565. package/src/utils/currency-units.ts +14 -0
  566. package/src/utils/depositary-receipt.ts +26 -0
  567. package/src/utils/exchanges.ts +72 -0
  568. package/src/utils/fire-and-forget.ts +24 -0
  569. package/src/utils/format.ts +13 -0
  570. package/src/utils/price-earnings.ts +70 -3
  571. package/src/utils/price-history.ts +58 -13
  572. package/src/utils/rpc-timeout-error.ts +27 -0
  573. package/src/utils/sec.ts +13 -1
  574. package/src/utils/utc-time.ts +79 -0
@@ -1,5 +1,6 @@
1
1
  import { readFile, writeFile } from "fs/promises";
2
- import { join, relative } from "path";
2
+ import { dirname, join, relative, resolve } from "path";
3
+ import type { BunPlugin } from "bun";
3
4
  import { TITLEBAR_OVERLAY_HEIGHT_PX } from "../../components/layout/titlebar-overlay";
4
5
 
5
6
  /** Imports whose path ends with the first entry resolve to the second, relative to the view directory. */
@@ -27,6 +28,13 @@ interface ViewBundleOptions {
27
28
  }
28
29
 
29
30
  const ELECTROBUN_VIEW_DIR = join(process.cwd(), "src", "renderers", "electrobun", "view");
31
+
32
+ /**
33
+ * Where the world map finds its land data, relative to the map's
34
+ * `basemap.ts`. Only view bundles define it, so the terminal binary, which
35
+ * never draws that map, leaves the data out.
36
+ */
37
+ export const WORLD_MAP_DATA_SPECIFIER = "./natural-earth/index.chunk.js";
30
38
  const DOM_RENDERER_DIR = join(process.cwd(), "src", "renderers", "dom");
31
39
 
32
40
  export function electrobunViewPath(...parts: string[]): string {
@@ -50,6 +58,7 @@ export async function buildViewBundle({
50
58
  failureMessage,
51
59
  missingEntryMessage,
52
60
  }: ViewBundleOptions): Promise<{ script: string; stylesheet: string | null }> {
61
+ const chunks = new Map<string, string>();
53
62
  const result = await Bun.build({
54
63
  entrypoints: [entrypoint],
55
64
  outdir,
@@ -58,8 +67,15 @@ export async function buildViewBundle({
58
67
  splitting: false,
59
68
  sourcemap,
60
69
  minify: true,
61
- define: { "process.env.NODE_ENV": "\"production\"", ...define },
62
- plugins: aliasRules.length > 0 ? [electrobunViewAliasPlugin(aliasRules)] : [],
70
+ define: {
71
+ "process.env.NODE_ENV": "\"production\"",
72
+ __GLOOM_WORLD_MAP_DATA__: JSON.stringify(WORLD_MAP_DATA_SPECIFIER),
73
+ ...define,
74
+ },
75
+ plugins: [
76
+ lazyChunkPlugin(outdir, outdir, chunks),
77
+ ...(aliasRules.length > 0 ? [electrobunViewAliasPlugin(aliasRules)] : []),
78
+ ],
63
79
  });
64
80
 
65
81
  if (!result.success) {
@@ -69,6 +85,7 @@ export async function buildViewBundle({
69
85
 
70
86
  const script = result.outputs.find((output) => output.kind === "entry-point" && output.path.endsWith(".js"));
71
87
  if (!script) throw new Error(missingEntryMessage);
88
+ await buildLazyChunks(outdir, chunks, failureMessage);
72
89
 
73
90
  const stylesheet = result.outputs.find((output) => output.path.endsWith(".css"))?.path ?? null;
74
91
  if (stylesheet) await writeFile(stylesheet, withTitlebarOverlayHeight(await readFile(stylesheet, "utf8")));
@@ -122,6 +139,67 @@ ${bootstrapScript}
122
139
  `;
123
140
  }
124
141
 
142
+ /**
143
+ * The view bundle is one file (no splitting), so a module reached through
144
+ * `import()` would land in it. A module named `*.chunk.ts` and imported as
145
+ * `import("./path/name.chunk.js")` instead ships as its own file at that path
146
+ * next to the importing bundle, fetched the first time it is asked for: large
147
+ * data only some panes draw, such as the world map's coastlines. The terminal
148
+ * and the tests run the source, where the same `import()` loads the module.
149
+ */
150
+ function lazyChunkPlugin(rootOutdir: string, emitDir: string, chunks: Map<string, string>): BunPlugin {
151
+ return {
152
+ name: "lazy-chunks",
153
+ setup(build) {
154
+ build.onResolve({ filter: /\.chunk(\.js|\.ts)?$/ }, (args) => {
155
+ if (args.kind.startsWith("entry-point") || /[\\/]node_modules[\\/]/.test(args.importer)) return undefined;
156
+ if (args.kind !== "dynamic-import") {
157
+ throw new Error(`${args.path} is a lazy chunk; load it with import() (from ${args.importer})`);
158
+ }
159
+ if (!args.path.startsWith("./") || !args.path.endsWith(".chunk.js")) {
160
+ throw new Error(`Lazy chunk ${args.path} must be imported as "./<path>.chunk.js" (from ${args.importer})`);
161
+ }
162
+ const source = resolve(dirname(args.importer), args.path.replace(/\.js$/, ".ts"));
163
+ const output = resolve(emitDir, args.path);
164
+ if (relative(rootOutdir, output).startsWith("..")) throw new Error(`Lazy chunk ${args.path} would land outside ${rootOutdir}`);
165
+ const existing = chunks.get(output);
166
+ if (existing && existing !== source) throw new Error(`Two lazy chunks emit ${output}: ${existing} and ${source}`);
167
+ chunks.set(output, source);
168
+ return { path: args.path, external: true };
169
+ });
170
+ },
171
+ };
172
+ }
173
+
174
+ /** Builds each lazy chunk on its own, and the chunks those load in turn. */
175
+ async function buildLazyChunks(rootOutdir: string, chunks: Map<string, string>, failureMessage: string): Promise<void> {
176
+ const built = new Set<string>();
177
+ let pending = [...chunks.entries()];
178
+ while (pending.length) {
179
+ const nested = new Map<string, string>();
180
+ for (const [output, source] of pending) {
181
+ if (built.has(output)) continue;
182
+ built.add(output);
183
+ const result = await Bun.build({
184
+ entrypoints: [source],
185
+ outdir: dirname(output),
186
+ naming: relative(dirname(output), output),
187
+ target: "browser",
188
+ format: "esm",
189
+ splitting: false,
190
+ sourcemap: "none",
191
+ minify: true,
192
+ plugins: [lazyChunkPlugin(rootOutdir, dirname(output), nested)],
193
+ });
194
+ if (!result.success) {
195
+ const details = result.logs.map((log) => log.message).filter(Boolean).join("\n");
196
+ throw new Error(`${failureMessage}: lazy chunk ${source}\n${details}`);
197
+ }
198
+ }
199
+ pending = [...nested.entries()];
200
+ }
201
+ }
202
+
125
203
  function electrobunViewAliasPlugin(aliasRules: AliasRule[]) {
126
204
  return {
127
205
  name: "electrobun-view-aliases",
@@ -353,6 +353,8 @@ function WebDataTableRowInner<
353
353
  <div
354
354
  key={column.id}
355
355
  data-gloom-role="data-table-cell"
356
+ // The instant behind a shortened time ("Wed 11:27"), so a rendered-view report can print it whole.
357
+ data-gloom-cell-instant={cell.value instanceof Date && Number.isFinite(cell.value.getTime()) ? cell.value.toISOString() : undefined}
356
358
  style={{
357
359
  minWidth: 0,
358
360
  position: freezeFirstColumn && columnIndex === 0 ? "sticky" : undefined,
@@ -345,8 +345,10 @@ export function WebTextField({
345
345
  focusedBackgroundColor={plain ? "transparent" : resolvedBackgroundColor}
346
346
  cursorColor={colors.textBright}
347
347
  style={{
348
- paddingLeft: plain ? 0 : comfortable ? 8 : 10,
349
- paddingRight: plain ? 0 : comfortable ? 8 : 10,
348
+ // A framed field keeps its text one cell off the frame; a plain one
349
+ // sits flush in the row or band that holds it.
350
+ paddingLeft: plain ? 0 : "var(--cell-w)",
351
+ paddingRight: plain ? 0 : "var(--cell-w)",
350
352
  borderRadius: plain ? 0 : CONTROL_RADIUS,
351
353
  // The field is taller than a cell, so the input takes the inner
352
354
  // height and centers its text on the box's own line.
@@ -581,8 +583,10 @@ export function WebDialogFrame({
581
583
  </Box>
582
584
  {children}
583
585
  {footer && (
586
+ // Sized by its line, not one cell: a cell-high box with this padding
587
+ // left the key line hanging out of its bottom.
584
588
  <Box
585
- height={1}
589
+ flexShrink={0}
586
590
  style={{
587
591
  borderTop: `1px solid ${panelBorder(colors)}`,
588
592
  paddingTop: 8,
@@ -5,6 +5,7 @@ import { TextAttributes } from "../../../ui";
5
5
  import type { ListRowState, ListViewItem, ListViewProps } from "../../../components/ui/list-view";
6
6
  import { blendHex, hoverBg, type ThemeColors } from "../../../theme/colors";
7
7
  import { useThemeColors } from "../../../theme/theme-context";
8
+ import { WEB_CELL_HEIGHT } from "../../../theme/font-scale";
8
9
  import { isInsideDialogSurface } from "../host/focus-scope";
9
10
  import { isEditableKeyboardTarget } from "../key-event";
10
11
  import {
@@ -58,6 +59,10 @@ function DefaultDesktopRow({
58
59
  );
59
60
  }
60
61
 
62
+ const FRAMED_LIST_PADDING_PX = 4;
63
+ /** What a framed list adds above and below its rows: padding and a 1px border on each side. */
64
+ const FRAMED_LIST_CHROME_PX = 2 * (FRAMED_LIST_PADDING_PX + 1);
65
+
61
66
  function listRowStyle(selected: boolean, disabled: boolean, colors: ThemeColors): CSSProperties {
62
67
  return {
63
68
  borderRadius: CONTROL_RADIUS,
@@ -109,6 +114,16 @@ export function WebListView({
109
114
  const tabStopIndex = selectedIndex >= 0 && items[selectedIndex] && !items[selectedIndex].disabled
110
115
  ? selectedIndex : items.findIndex((item) => !item.disabled);
111
116
  const effectiveSurface = surface ?? (scrollable ? "framed" : "plain");
117
+ // `height` counts terminal rows. A list that is not meant to scroll takes
118
+ // only the rows it has, up to that many; one with more rows than that
119
+ // scrolls inside the height instead of drawing over whatever follows it.
120
+ const rowsHeight = items.length === 0 ? 1 : items.length * rowHeight + (items.length - 1) * rowGap;
121
+ const overflowsHeight = !scrollable && height != null && rowsHeight > height;
122
+ const scrolls = scrollable || overflowsHeight;
123
+ // The frame's padding and border sit outside the rows it was asked to hold.
124
+ const scrollHeight = overflowsHeight
125
+ ? `${height * WEB_CELL_HEIGHT + (effectiveSurface === "plain" ? 0 : FRAMED_LIST_CHROME_PX)}px`
126
+ : height;
112
127
  const frameStyle = effectiveSurface === "plain"
113
128
  ? {
114
129
  border: "none",
@@ -119,12 +134,12 @@ export function WebListView({
119
134
  : {
120
135
  border: `1px solid ${panelBorder(colors)}`,
121
136
  borderRadius: CONTROL_RADIUS,
122
- padding: 4,
137
+ padding: FRAMED_LIST_PADDING_PX,
123
138
  backgroundColor: subtlePanelFill(colors),
124
139
  };
125
140
 
126
141
  useEffect(() => {
127
- if (!scrollable || !autoScrollToIndex || activeScrollIndex < 0) return;
142
+ if (!scrolls || !autoScrollToIndex || activeScrollIndex < 0) return;
128
143
  const scrollBox = scrollRef.current;
129
144
  if (!scrollBox) return;
130
145
  const safeIndex = Math.min(activeScrollIndex, items.length - 1);
@@ -136,16 +151,16 @@ export function WebListView({
136
151
  } else if (rowBottom > scrollBox.scrollTop + viewportHeight) {
137
152
  scrollBox.scrollTo(rowBottom - viewportHeight);
138
153
  }
139
- }, [activeScrollIndex, autoScrollToIndex, items.length, rowHeight, rowStride, scrollable]);
154
+ }, [activeScrollIndex, autoScrollToIndex, items.length, rowHeight, rowStride, scrolls]);
140
155
 
141
156
  useEffect(() => {
142
- if (!scrollable) return;
157
+ if (!scrolls) return;
143
158
  const scrollBox = scrollRef.current;
144
159
  if (!scrollBox) return;
145
160
  if (scrollBox.verticalScrollBar) {
146
161
  scrollBox.verticalScrollBar.visible = items.length * rowStride - rowGap > (scrollBox.viewport?.height ?? 0);
147
162
  }
148
- }, [items.length, height, flexGrow, rowGap, rowStride, scrollable]);
163
+ }, [items.length, height, flexGrow, rowGap, rowStride, scrolls]);
149
164
 
150
165
  // The dialog or pane around the list moves its cursor (j/k, Home/End). A row
151
166
  // Tab or a press left focused follows it, or Space and Enter would act on the
@@ -156,8 +171,8 @@ export function WebListView({
156
171
  const active = document.activeElement;
157
172
  if (!list || !active || !list.contains(active) || isEditableKeyboardTarget(active)) return;
158
173
  const row = list.querySelectorAll<HTMLElement>('[role="option"]')[selectedIndex];
159
- if (row && !row.contains(active)) row.focus({ preventScroll: scrollable });
160
- }, [listDomId, scrollable, selectedIndex]);
174
+ if (row && !row.contains(active)) row.focus({ preventScroll: scrolls });
175
+ }, [listDomId, scrolls, selectedIndex]);
161
176
 
162
177
  const rows = items.length === 0
163
178
  ? (
@@ -233,11 +248,21 @@ export function WebListView({
233
248
  });
234
249
 
235
250
  return (
236
- <Box id={listDomId} flexDirection="column" height={height} flexGrow={flexGrow} gap={1} role="listbox" aria-label={remoteLabel}>
237
- {scrollable ? (
251
+ <Box
252
+ id={listDomId}
253
+ flexDirection="column"
254
+ height={scrollable ? height : undefined}
255
+ // A list sized by its container gives up height to it, and scrolls.
256
+ minHeight={scrollable && height == null ? 0 : undefined}
257
+ flexGrow={flexGrow}
258
+ gap={1}
259
+ role="listbox"
260
+ aria-label={remoteLabel}
261
+ >
262
+ {scrolls ? (
238
263
  <ScrollBox
239
264
  ref={scrollRef}
240
- height={height}
265
+ height={scrollHeight}
241
266
  flexGrow={flexGrow}
242
267
  scrollY
243
268
  focusable={false}
@@ -2,12 +2,16 @@
2
2
 
3
3
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
4
4
  import { createPortal } from "react-dom";
5
- import type { HostPopoverProps } from "../../../ui";
5
+ import type { BoxRenderable, HostPopoverProps } from "../../../ui";
6
6
  import { blendHex } from "../../../theme/colors";
7
+ import { WEB_CELL_HEIGHT, WEB_CELL_WIDTH } from "../../../theme/font-scale";
7
8
  import { useThemeColors } from "../../../theme/theme-context";
8
9
 
9
10
  const VIEWPORT_MARGIN = 10;
11
+ /** How far a popover kept inside its pane stays off the pane's edge. */
12
+ const PANE_MARGIN = 4;
10
13
  const POPOVER_GAP = 6;
14
+ const PANE_SELECTOR = '[data-gloom-role="pane-window"], [data-gloom-role="detached-pane-window"]';
11
15
  /** `.gloom-popover` in styles.css: above dialogs and toasts. */
12
16
  const POPOVER_Z_INDEX = 10_001;
13
17
 
@@ -21,6 +25,51 @@ function cssSize(value: number | string | undefined): number | string | undefine
21
25
  return typeof value === "number" ? `${value}px` : value;
22
26
  }
23
27
 
28
+ interface Edges {
29
+ left: number;
30
+ top: number;
31
+ right: number;
32
+ bottom: number;
33
+ }
34
+
35
+ /**
36
+ * Where an anchor element is now, in viewport pixels. Null once it is gone
37
+ * from the page (a removed message), so the popover falls back to its trigger.
38
+ */
39
+ function anchorEdges(anchor: BoxRenderable): Edges | null {
40
+ const rect = anchor.getBoundingClientRect?.();
41
+ if (rect) {
42
+ if (rect.width === 0 && rect.height === 0) return null;
43
+ return { left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height };
44
+ }
45
+ const bounds = anchor.absoluteBounds;
46
+ if (!bounds) return null;
47
+ return {
48
+ left: bounds.x * WEB_CELL_WIDTH,
49
+ top: bounds.y * WEB_CELL_HEIGHT,
50
+ right: (bounds.x + bounds.width) * WEB_CELL_WIDTH,
51
+ bottom: (bounds.y + bounds.height) * WEB_CELL_HEIGHT,
52
+ };
53
+ }
54
+
55
+ /** The area a popover must stay in: the window, and for `pane` the pane that holds its trigger too. */
56
+ function placementEdges(wrapper: Element | null, boundary: HostPopoverProps["boundary"]): Edges {
57
+ const viewport = {
58
+ left: VIEWPORT_MARGIN,
59
+ top: VIEWPORT_MARGIN,
60
+ right: window.innerWidth - VIEWPORT_MARGIN,
61
+ bottom: window.innerHeight - VIEWPORT_MARGIN,
62
+ };
63
+ const pane = boundary === "pane" ? wrapper?.closest(PANE_SELECTOR)?.getBoundingClientRect() : null;
64
+ if (!pane) return viewport;
65
+ return {
66
+ left: Math.max(viewport.left, pane.left + PANE_MARGIN),
67
+ top: Math.max(viewport.top, pane.top + PANE_MARGIN),
68
+ right: Math.min(viewport.right, pane.right - PANE_MARGIN),
69
+ bottom: Math.min(viewport.bottom, pane.bottom - PANE_MARGIN),
70
+ };
71
+ }
72
+
24
73
  /**
25
74
  * The popover is portalled to <body>, so its z-index only competes in the root
26
75
  * stacking context. A trigger inside a surface stacked above the popover layer
@@ -45,6 +94,10 @@ export function WebPopover({
45
94
  trigger,
46
95
  children,
47
96
  anchorPoint,
97
+ anchor,
98
+ boundary = "viewport",
99
+ onPointerEnter,
100
+ onPointerLeave,
48
101
  placement = "bottom-start",
49
102
  minWidth = 280,
50
103
  maxWidth = "min(420px, calc(100vw - 20px))",
@@ -59,18 +112,19 @@ export function WebPopover({
59
112
  const [zIndex, setZIndex] = useState<number | undefined>(undefined);
60
113
 
61
114
  const updatePosition = useCallback(() => {
62
- const anchor = anchorRef.current;
115
+ const wrapper = anchorRef.current;
63
116
  const popover = popoverRef.current;
64
- if (!anchor || !popover) return;
117
+ if (!wrapper || !popover) return;
65
118
 
66
119
  const popoverRect = popover.getBoundingClientRect();
67
- const triggerRect = anchor.getBoundingClientRect();
120
+ const triggerRect = wrapper.getBoundingClientRect();
121
+ const elementEdges = anchor ? anchorEdges(anchor) : null;
68
122
  // Keyboard-driven popovers can intentionally omit a visible trigger. In
69
123
  // that case the anchor wrapper still inherits a line-height, so its DOM
70
124
  // rect is not truly empty even though there is nothing useful to anchor to.
71
125
  // Center these unanchored menus; explicit pointer/footer coordinates still
72
126
  // take precedence below.
73
- if (!anchorPoint && (trigger == null || (triggerRect.width === 0 && triggerRect.height === 0))) {
127
+ if (!elementEdges && !anchorPoint && (trigger == null || (triggerRect.width === 0 && triggerRect.height === 0))) {
74
128
  setPosition({
75
129
  left: Math.max(
76
130
  VIEWPORT_MARGIN,
@@ -90,28 +144,26 @@ export function WebPopover({
90
144
  });
91
145
  return;
92
146
  }
93
- const anchorRect = anchorPoint
147
+ const anchorRect = elementEdges ?? (anchorPoint
94
148
  ? {
95
149
  left: anchorPoint.x,
96
150
  right: anchorPoint.x,
97
151
  top: anchorPoint.y,
98
152
  bottom: anchorPoint.y,
99
153
  }
100
- : triggerRect;
154
+ : triggerRect);
155
+ const edges = placementEdges(wrapper, boundary);
101
156
  const preferredLeft = placement === "bottom-end"
102
157
  ? anchorRect.right - popoverRect.width
103
158
  : anchorRect.left;
104
- const left = Math.max(
105
- VIEWPORT_MARGIN,
106
- Math.min(preferredLeft, window.innerWidth - popoverRect.width - VIEWPORT_MARGIN),
107
- );
159
+ const left = Math.max(edges.left, Math.min(preferredLeft, edges.right - popoverRect.width));
108
160
  const below = anchorRect.bottom + POPOVER_GAP;
109
161
  const above = anchorRect.top - popoverRect.height - POPOVER_GAP;
110
- const top = below + popoverRect.height <= window.innerHeight - VIEWPORT_MARGIN
162
+ const top = below + popoverRect.height <= edges.bottom
111
163
  ? below
112
- : Math.max(VIEWPORT_MARGIN, above);
164
+ : Math.max(edges.top, above);
113
165
  setPosition({ left, top, visible: true });
114
- }, [anchorPoint, placement, trigger]);
166
+ }, [anchor, anchorPoint, boundary, placement, trigger]);
115
167
 
116
168
  useLayoutEffect(() => {
117
169
  if (!open) {
@@ -123,10 +175,15 @@ export function WebPopover({
123
175
  const frame = window.requestAnimationFrame(updatePosition);
124
176
  window.addEventListener("resize", updatePosition);
125
177
  document.addEventListener("scroll", updatePosition, true);
178
+ // New content (a hover card swapped to another name) can change the size
179
+ // the placement was worked out for.
180
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(updatePosition) : null;
181
+ if (popoverRef.current) resizeObserver?.observe(popoverRef.current);
126
182
  return () => {
127
183
  window.cancelAnimationFrame(frame);
128
184
  window.removeEventListener("resize", updatePosition);
129
185
  document.removeEventListener("scroll", updatePosition, true);
186
+ resizeObserver?.disconnect();
130
187
  };
131
188
  }, [open, updatePosition]);
132
189
 
@@ -181,6 +238,8 @@ export function WebPopover({
181
238
  tabIndex={-1}
182
239
  onMouseDown={(event) => event.stopPropagation()}
183
240
  onClick={(event) => event.stopPropagation()}
241
+ onMouseEnter={onPointerEnter}
242
+ onMouseLeave={onPointerLeave}
184
243
  style={{
185
244
  left: position.left,
186
245
  top: position.top,
@@ -27,9 +27,21 @@ function textInputStyle(props: Record<string, unknown>, multiline: boolean): CSS
27
27
  const backgroundColor = focused && typeof props.focusedBackgroundColor === "string"
28
28
  ? props.focusedBackgroundColor
29
29
  : props.backgroundColor;
30
+ const base = commonStyle(props);
31
+ const overrides = props.style as CSSProperties | undefined;
30
32
 
31
33
  return {
32
- ...commonStyle(props),
34
+ ...base,
35
+ // Flush unless the caller insets the text. Longhands, never the `padding`
36
+ // shorthand: React writes style keys in order, and a shorthand here landed
37
+ // after a caller's `paddingLeft` and wiped it, so every bordered field's
38
+ // text sat on its border.
39
+ ...(overrides?.padding === undefined ? {
40
+ paddingTop: base.paddingTop ?? 0,
41
+ paddingRight: base.paddingRight ?? 0,
42
+ paddingBottom: base.paddingBottom ?? 0,
43
+ paddingLeft: base.paddingLeft ?? 0,
44
+ } : {}),
33
45
  display: "block",
34
46
  resize: "none",
35
47
  border: "none",
@@ -40,10 +52,9 @@ function textInputStyle(props: Record<string, unknown>, multiline: boolean): CSS
40
52
  overflow: multiline ? "auto" : "hidden",
41
53
  width: cellWidth(props.width) ?? "100%",
42
54
  height: cellHeight(props.height) ?? (multiline ? "100%" : "var(--cell-h)"),
43
- padding: 0,
44
55
  margin: 0,
45
56
  caretColor: typeof props.cursorColor === "string" ? props.cursorColor : "auto",
46
- ...(props.style as CSSProperties | undefined),
57
+ ...overrides,
47
58
  };
48
59
  }
49
60
 
@@ -140,10 +140,12 @@ button, [data-gloom-interactive="true"] { cursor: pointer; }
140
140
  -webkit-user-select: none;
141
141
  user-select: none;
142
142
  }
143
- [data-gloom-role="pane-grip"],
144
- [data-gloom-role="pane-header-chrome"] {
143
+ [data-gloom-role="pane-header"][data-drag-surface="pane"] {
145
144
  cursor: grab;
146
145
  }
146
+ [data-gloom-role="pane-header-tabs"] {
147
+ cursor: default;
148
+ }
147
149
  [data-gloom-role="pane-header"] [data-gloom-role="tab-button"],
148
150
  [data-gloom-role="pane-header"] button,
149
151
  [data-gloom-role="pane-header"] [data-gloom-interactive="true"] {
@@ -157,11 +159,8 @@ button, [data-gloom-interactive="true"] { cursor: pointer; }
157
159
  [data-gloom-role="pane-restore"] {
158
160
  cursor: pointer;
159
161
  }
160
- body.gloom-dragging [data-gloom-role="pane-grip"],
161
- body.gloom-dragging [data-gloom-role="pane-header-chrome"] {
162
- cursor: grabbing;
163
- }
164
- body.gloom-dragging {
162
+ body.gloom-dragging,
163
+ body.gloom-dragging [data-gloom-role="pane-header"] {
165
164
  cursor: grabbing;
166
165
  }
167
166
  [data-gloom-role="pane-title"] {
@@ -14,7 +14,8 @@ import {
14
14
  } from "../shared/protocol";
15
15
  import { decodeRpcResponse, decodeRpcValue, encodeRpcValue } from "../shared/rpc-codec";
16
16
  import { subscribeCapability, type CapabilitySubscriptionOptions } from "./capability-subscription";
17
- import { nameRpcTimeout } from "./rpc-timeout";
17
+ import { RpcTimeoutError } from "../../../utils/rpc-timeout-error";
18
+ import { nameRpcTimeout, RPC_MAX_REQUEST_TIME_MS } from "./rpc-timeout";
18
19
  import type { RemoteControlRequest, RemoteControlResponse } from "../../../remote/types";
19
20
 
20
21
  type BackendMessages = ElectrobunDesktopRpcSchema["webview"]["messages"];
@@ -43,7 +44,7 @@ function emit<K extends BackendMessageName>(name: K, message: BackendMessages[K]
43
44
  }
44
45
 
45
46
  const rpc = Electroview.defineRPC<ElectrobunDesktopRpcSchema>({
46
- maxRequestTime: 120_000,
47
+ maxRequestTime: RPC_MAX_REQUEST_TIME_MS,
47
48
  handlers: {
48
49
  requests: {
49
50
  "remote.request": async (message: RemoteControlRequestMessage) => {
@@ -107,15 +108,20 @@ const rpc = Electroview.defineRPC<ElectrobunDesktopRpcSchema>({
107
108
 
108
109
  const electroview = new Electroview({ rpc });
109
110
 
111
+ const BRIDGE_READY_LIMIT_MS = 5_000;
112
+
110
113
  async function waitForBridgeReady(): Promise<void> {
111
114
  const start = Date.now();
112
- while (Date.now() - start < 5_000) {
115
+ while (Date.now() - start < BRIDGE_READY_LIMIT_MS) {
113
116
  if (electroview.bunSocket?.readyState === WebSocket.OPEN) {
114
117
  return;
115
118
  }
116
119
  await new Promise((resolve) => setTimeout(resolve, 25));
117
120
  }
118
- throw new Error("Electrobun RPC socket did not open in time.");
121
+ throw new RpcTimeoutError("Electrobun RPC socket did not open in time.", {
122
+ elapsedMs: Date.now() - start,
123
+ limitMs: BRIDGE_READY_LIMIT_MS,
124
+ });
119
125
  }
120
126
 
121
127
  export function backendRequest<T = unknown>(
@@ -443,6 +443,7 @@ function ShotPane({ payload, registry }: { payload: DesktopPaneShotPayload; regi
443
443
  component={pane.component}
444
444
  paneId={instance.instanceId}
445
445
  paneType={instance.paneId}
446
+ title={title}
446
447
  focused
447
448
  width={bodyFrame.width ?? 1}
448
449
  height={bodyFrame.height ?? 1}
@@ -1,6 +1,10 @@
1
1
  import { getCloudApiBaseUrl } from "../../../api-client/request";
2
+ import { RpcTimeoutError } from "../../../utils/rpc-timeout-error";
2
3
  import type { DesktopBackendRequestMethod } from "../shared/protocol";
3
4
 
5
+ /** How long the view waits for the Bun process to answer one request. */
6
+ export const RPC_MAX_REQUEST_TIME_MS = 120_000;
7
+
4
8
  /** What Electrobun's request timer rejects with: no method, request id or caller. */
5
9
  const ELECTROBUN_REQUEST_TIMEOUT_MESSAGE = "RPC request timed out.";
6
10
 
@@ -16,7 +20,9 @@ const ELECTROBUN_REQUEST_TIMEOUT_MESSAGE = "RPC request timed out.";
16
20
  * from the user's config (a broker gateway, a feed, a plugin endpoint) and is
17
21
  * only called external. Never the payload, rest of the path, query or headers.
18
22
  * Elapsed time is rounded to 10 s because crash reports are deduplicated per
19
- * session on the message.
23
+ * session on the message. The error keeps its message and `Error` type, and
24
+ * carries the elapsed time so a timer that fired long after its limit (the
25
+ * machine slept) can be told from a request that really stalled.
20
26
  */
21
27
  export async function nameRpcTimeout<T>(
22
28
  method: DesktopBackendRequestMethod,
@@ -28,8 +34,13 @@ export async function nameRpcTimeout<T>(
28
34
  return await request();
29
35
  } catch (error) {
30
36
  if (!(error instanceof Error) || error.message !== ELECTROBUN_REQUEST_TIMEOUT_MESSAGE) throw error;
31
- const seconds = Math.round((performance.now() - startedAt) / 10_000) * 10;
32
- throw new Error(`RPC request timed out: ${describeRequest(method, payload)} after ~${seconds}s`, { cause: error });
37
+ const elapsedMs = performance.now() - startedAt;
38
+ const seconds = Math.round(elapsedMs / 10_000) * 10;
39
+ throw new RpcTimeoutError(`RPC request timed out: ${describeRequest(method, payload)} after ~${seconds}s`, {
40
+ elapsedMs,
41
+ limitMs: RPC_MAX_REQUEST_TIME_MS,
42
+ cause: error,
43
+ });
33
44
  }
34
45
  }
35
46
 
@@ -108,6 +108,11 @@ export async function createOpenTuiHost(): Promise<OpenTuiHost> {
108
108
  enableMouseMovement: true,
109
109
  });
110
110
  const root = createRoot(renderer);
111
+ // Every mounted ScrollBox listens for `selection` and many components for
112
+ // `resize`, so the counts grow with the panes on screen (14 and 18 with one
113
+ // DES open at 80x24) and fall back when they close. Node's default warning
114
+ // at 11 is not a leak here, and it prints over the panes.
115
+ renderer.setMaxListeners(0);
111
116
  installResolutionEventBridge(renderer);
112
117
  // Streamed quotes apply and notify on one clock of up to 10 Hz: every
113
118
  // visible row stays live while a burst of ticks costs one terminal redraw,
@@ -40,6 +40,8 @@ import { resolveCurrencyUnit } from "../../utils/currency-units";
40
40
  import { canonicalExchange, canonicalTickerKey, parsePublicTickerKey } from "../../utils/exchanges";
41
41
  import { normalizePriceHistory, priceHistoryIntervalMs, reachesLatestSettledSession } from "../../utils/price-history";
42
42
  import { createProviderMiss } from "../provider-errors";
43
+ import { assertSecRegistrantMatches } from "../sec-registrant";
44
+ import { nonUsSecListingVenue } from "../../utils/sec";
43
45
  import { publicListingTarget } from "../listing-target";
44
46
  import { canonicalHistoryInterval, HistoryRetentionError, parseHistoryRecoveryCandidate, parseHistoryRetention, type HistoryRetention } from "../history-retention";
45
47
  import { getRouterEntityKey } from "../provider-router/cache";
@@ -195,7 +197,7 @@ function mapCloudPriceHistory(
195
197
  `Cloud chart data is unavailable for ${ticker}`,
196
198
  ).map((point) => mapPricePoint(point, divisor, exchange)),
197
199
  );
198
- if (stale && !reachesLatestSettledSession(points, Date.now(), { exchange, intervalMs: priceHistoryIntervalMs(interval) })) {
200
+ if (stale && !reachesLatestSettledSession(points, Date.now(), { symbol: ticker, exchange, intervalMs: priceHistoryIntervalMs(interval) })) {
199
201
  throw createProviderMiss(`Cloud chart data is stale for ${ticker}`);
200
202
  }
201
203
  if (
@@ -486,11 +488,30 @@ export class GloomberbCloudProvider implements AssetDataProvider {
486
488
  );
487
489
  }
488
490
 
489
- async getSecFilings(ticker: string, count = 15): Promise<SecFilingItem[]> {
490
- return withCloudFallback(async () => {
491
- const response = await apiClient.getCloudSecFilings({ ticker, limit: count, offset: 0 });
491
+ async getSecFilings(ticker: string, count = 15, exchange?: string, context?: MarketDataRequestContext): Promise<SecFilingItem[]> {
492
+ const venue = nonUsSecListingVenue(ticker, exchange);
493
+ const name = venue ? context?.listingName?.trim() || await this.listingName(ticker, venue) || undefined : undefined;
494
+ const filings = await withCloudFallback(async () => {
495
+ const response = await apiClient.getCloudSecFilings({ ticker, exchange, name, limit: count, offset: 0 });
492
496
  return response.filings.map(mapCloudSecFiling);
493
497
  }, `Cloud SEC filings are unavailable for ${ticker}`);
498
+ if (!venue || filings.length === 0) return filings;
499
+ const symbol = parsePublicTickerKey(ticker).symbol;
500
+ // Without the listing's company the filings cannot be told apart from another company's.
501
+ if (!name) throw createProviderMiss(`SEC filings for ${symbol} could not be matched to its ${venue} listing`);
502
+ assertSecRegistrantMatches(filings, { symbol, exchange: venue, name });
503
+ return filings;
504
+ }
505
+
506
+ /** The company a listing belongs to, from its own quote; null when the quote prices another venue. */
507
+ private async listingName(ticker: string, venue: string): Promise<string | null> {
508
+ try {
509
+ const quote = await this.getQuote(ticker, venue);
510
+ const quoteVenue = canonicalExchange(quote.listingExchangeName || quote.exchangeName);
511
+ return quoteVenue === venue ? quote.name?.trim() || null : null;
512
+ } catch {
513
+ return null;
514
+ }
494
515
  }
495
516
 
496
517
  async getSecFilingDocuments(filing: SecFilingItem): Promise<SecFilingDocument[]> {