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,5 @@
1
- import { colors } from "./colors";
2
- import { blendHex, contrastRatio, relativeLuminance } from "./color-utils";
1
+ import { colors, type ThemeColors } from "./colors";
2
+ import { blendHex, contrastRatio, higherContrast, relativeLuminance } from "./color-utils";
3
3
 
4
4
  const HEATMAP_BASE_BLEND = 0.35;
5
5
  const HEATMAP_TEXT_MIN_CONTRAST = 4.5;
@@ -100,46 +100,66 @@ export function resolveHeatCellColors(
100
100
  }
101
101
 
102
102
  /**
103
- * Heat map tiles: one fixed diverging hue scale for every theme, so a move
104
- * reads the same in Amber as in GitHub Light. Losses run to a bright hot
105
- * pink, a flat session sits on a muted violet and gains run to a bright aqua;
106
- * pink against aqua also separates for red-green colour blindness, where red
107
- * against green does not. Each tile takes whichever text reads best on it,
108
- * white on the violet middle and a dark navy on the bright ends, at 4.5:1 or
109
- * better. The stops were sampled from a market wall's pinks, violets and
110
- * aquas. A light theme starts from a pale lavender so the page is not a dark
111
- * block; the ends stay the same.
103
+ * Heat map tiles take their colours from the selected theme. Losses run from
104
+ * a muted middle to the theme's negative colour and gains to its positive, so
105
+ * the strongest tiles are the app's own down and up colours. The middle is
106
+ * the theme's neutral tone, lifted off a dark page or set into a light one
107
+ * just far enough to read as a tile. Colour builds in OKLab, hue ahead of
108
+ * lightness so a small move already leans to its side, and is full at 3%.
109
+ * Each tile takes whichever of the theme's light or dark text reads better
110
+ * on it, or white or black where neither reaches 4.5:1.
112
111
  */
113
112
  const HEATMAP_TILE_FULL_SCALE_PERCENT = 3;
114
- /** How fast colour builds from flat: below 1 a small move already leans to its hue. */
113
+ /** How fast colour builds from flat: below 1 a small move already leans to its side. */
115
114
  const HEATMAP_TILE_EASING = 0.8;
115
+ /** Hue arrives ahead of lightness, so a mid-size move is a clear colour, not a grey. */
116
+ const HEATMAP_TILE_HUE_LEAD = 0.4;
116
117
  const HEATMAP_TILE_TEXT_MIN_CONTRAST = 4.5;
117
- const HEATMAP_FLAT_DARK = { l: 0.53, c: 0.12, h: 296 } as const;
118
- const HEATMAP_FLAT_LIGHT = { l: 0.9, c: 0.035, h: 290 } as const;
119
- /** From flat to full strength, evenly spaced; dark pages pass a saturated middle stop on the way. */
120
- const HEATMAP_STOPS = {
121
- dark: {
122
- loss: [{ l: 0.62, c: 0.2, h: 350 }, { l: 0.7, c: 0.22, h: 356 }],
123
- gain: [{ l: 0.64, c: 0.1, h: 205 }, { l: 0.8, c: 0.13, h: 185 }],
124
- },
125
- light: {
126
- loss: [{ l: 0.7, c: 0.22, h: 356 }],
127
- gain: [{ l: 0.8, c: 0.13, h: 185 }],
128
- },
118
+ /** How far the flat middle stands off the page, as contrast against the background. */
119
+ const HEATMAP_FLAT_CONTRAST = { dark: 2.1, light: 1.4 } as const;
120
+ /** A missing move sits between the page and the flat middle: there, but saying nothing. */
121
+ const HEATMAP_MISSING_CONTRAST = { dark: 1.35, light: 1.16 } as const;
122
+ /** The middle keeps a hint of the theme's neutral tint, never a colour of its own. */
123
+ const HEATMAP_FLAT_MAX_CHROMA = 0.025;
124
+ const HEATMAP_MISSING_MAX_CHROMA = 0.008;
125
+ /** Light text tokens with more colour than this (a phosphor green, amber) are left off the tiles. */
126
+ const HEATMAP_INK_MAX_CHROMA = 0.06;
127
+ /** Luminance a token needs to count as the theme's light text, and may not exceed to count as its dark text. */
128
+ const HEATMAP_INK_LUMINANCE = { light: 0.6, dark: 0.05 } as const;
129
+ /** Below this an end has no hue to carry the scale. */
130
+ const HEATMAP_END_MIN_CHROMA = 0.05;
131
+ /** The full-strength end must stand this far from the flat middle... */
132
+ const HEATMAP_END_MIN_FROM_FLAT = 0.12;
133
+ /** ...and the two ends this far from each other. */
134
+ const HEATMAP_ENDS_MIN_APART = 0.15;
135
+ /**
136
+ * Only for a palette whose own up and down colours cannot carry the scale: an
137
+ * end too close to the page keeps its hue at this lightness, and an end with
138
+ * no hue, or two ends too alike, take the usual red and green.
139
+ */
140
+ const HEATMAP_FALLBACK = {
141
+ lightness: { dark: 0.7, light: 0.52 },
142
+ chroma: 0.15,
143
+ lossHue: 25,
144
+ gainHue: 150,
129
145
  } as const;
130
- const HEATMAP_MISSING_DARK = "#3a3a40";
131
- const HEATMAP_MISSING_LIGHT = "#cfcfd6";
132
- const HEATMAP_TEXT_LIGHT = "#ffffff";
133
- const HEATMAP_TEXT_DARK = "#0a0d1f";
134
- /** Where neither white nor the navy reaches 4.5:1, black always does. */
135
- const HEATMAP_TEXT_BLACK = "#000000";
146
+ /** How far a selected tile is pulled away from the page, further for a tile already near the end of the range. */
147
+ const HEATMAP_SELECTED_LIFT = { start: 0.45, step: 0.05, max: 0.8 } as const;
148
+ const HEATMAP_SELECTED_MIN_DISTANCE = 0.1;
136
149
  const HEATMAP_STEPS = 64;
150
+ const HEATMAP_SCALE_CACHE_LIMIT = 32;
137
151
 
138
152
  export interface HeatmapTileColors {
139
153
  background: string;
140
154
  foreground: string;
141
155
  }
142
156
 
157
+ /** A selected tile's outline on the desktop and the web: a ring, then a hairline of the page. */
158
+ export interface HeatmapSelectionRing {
159
+ outer: string;
160
+ inner: string;
161
+ }
162
+
143
163
  type Oklab = readonly [number, number, number];
144
164
 
145
165
  function srgbToLinear(channel: number): number {
@@ -168,89 +188,253 @@ export function hexToOklab(hex: string): Oklab {
168
188
  ];
169
189
  }
170
190
 
171
- function oklabToHex([lightness, a, b]: Oklab): string {
191
+ function oklabToLinear([lightness, a, b]: Oklab): [number, number, number] {
172
192
  const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;
173
193
  const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;
174
194
  const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;
175
- const r = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
176
- const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
177
- const blue = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
178
- return `#${[r, g, blue].map((channel) => linearToSrgb(channel).toString(16).padStart(2, "0")).join("")}`;
195
+ return [
196
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
197
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
198
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,
199
+ ];
200
+ }
201
+
202
+ function inGamut(color: Oklab): boolean {
203
+ return oklabToLinear(color).every((channel) => channel >= -0.0005 && channel <= 1.0005);
204
+ }
205
+
206
+ /** Into sRGB by giving up chroma, never lightness or hue, so a clipped colour cannot drift toward another. */
207
+ function toGamut(color: Oklab): Oklab {
208
+ if (inGamut(color)) return color;
209
+ const [lightness, a, b] = color;
210
+ let low = 0;
211
+ let high = 1;
212
+ for (let index = 0; index < 20; index += 1) {
213
+ const mid = (low + high) / 2;
214
+ if (inGamut([lightness, a * mid, b * mid])) low = mid;
215
+ else high = mid;
216
+ }
217
+ return [lightness, a * low, b * low];
218
+ }
219
+
220
+ function oklabToHex(color: Oklab): string {
221
+ return `#${oklabToLinear(toGamut(color)).map((channel) => linearToSrgb(channel).toString(16).padStart(2, "0")).join("")}`;
222
+ }
223
+
224
+ function chromaOf(color: Oklab): number {
225
+ return Math.hypot(color[1], color[2]);
226
+ }
227
+
228
+ function oklabDistance(left: Oklab, right: Oklab): number {
229
+ return Math.hypot(left[0] - right[0], left[1] - right[1], left[2] - right[2]);
179
230
  }
180
231
 
181
- function lch({ l, c, h }: Lch): Oklab {
182
- const radians = h * Math.PI / 180;
183
- return [l, c * Math.cos(radians), c * Math.sin(radians)];
232
+ /** The colour's hue at most `maxChroma` strong. */
233
+ function tint(color: Oklab, maxChroma: number): [number, number] {
234
+ const chroma = chromaOf(color);
235
+ const scale = chroma > maxChroma ? maxChroma / chroma : 1;
236
+ return [color[1] * scale, color[2] * scale];
237
+ }
238
+
239
+ /**
240
+ * The lightness at which a tile of this tint stands `contrast` off the page:
241
+ * above a dark page, below a light one.
242
+ */
243
+ function standOffPage(page: string, [a, b]: readonly [number, number], contrast: number, dark: boolean): Oklab {
244
+ const pageLightness = hexToOklab(page)[0];
245
+ let low = dark ? pageLightness : 0;
246
+ let high = dark ? 1 : pageLightness;
247
+ for (let index = 0; index < 24; index += 1) {
248
+ const mid = (low + high) / 2;
249
+ const reaches = contrastRatio(oklabToHex([mid, a, b]), page) >= contrast;
250
+ if (dark === reaches) high = mid;
251
+ else low = mid;
252
+ }
253
+ return toGamut([dark ? high : low, a, b]);
184
254
  }
185
255
 
186
- type Lch = { readonly l: number; readonly c: number; readonly h: number };
256
+ interface HeatmapInks {
257
+ light: string;
258
+ dark: string;
259
+ }
187
260
 
188
- /** Around the hue wheel the short way, so the scale passes through magenta and blue instead of grey. */
189
- function mixLch(from: Lch, to: Lch, ratio: number): Lch {
190
- const turn = ((to.h - from.h + 540) % 360) - 180;
261
+ /**
262
+ * The theme's own text for tiles: its lightest near-neutral tone and its
263
+ * darkest, with white and black where the theme has none.
264
+ */
265
+ function heatmapInks(palette: ThemeColors): HeatmapInks {
266
+ const tokens = [palette.textBright, palette.text, palette.selectedText, palette.headerText, palette.bg, palette.panel];
267
+ const lights = tokens.filter((token) => relativeLuminance(token) >= HEATMAP_INK_LUMINANCE.light && chromaOf(hexToOklab(token)) <= HEATMAP_INK_MAX_CHROMA);
268
+ const darks = tokens.filter((token) => relativeLuminance(token) <= HEATMAP_INK_LUMINANCE.dark);
191
269
  return {
192
- l: from.l + (to.l - from.l) * ratio,
193
- c: from.c + (to.c - from.c) * ratio,
194
- h: from.h + turn * ratio,
270
+ light: lights.reduce((best, token) => (relativeLuminance(token) > relativeLuminance(best) ? token : best), lights[0] ?? "#ffffff"),
271
+ dark: darks.reduce((best, token) => (relativeLuminance(token) < relativeLuminance(best) ? token : best), darks[0] ?? "#000000"),
195
272
  };
196
273
  }
197
274
 
198
- function heatmapTextColor(background: string): string {
199
- const best = highestContrast([HEATMAP_TEXT_LIGHT, HEATMAP_TEXT_DARK], background);
275
+ function heatmapTextColor(background: string, inks: HeatmapInks): string {
276
+ const best = higherContrast(inks.light, inks.dark, background);
200
277
  if (contrastRatio(best, background) >= HEATMAP_TILE_TEXT_MIN_CONTRAST) return best;
201
- return highestContrast([HEATMAP_TEXT_LIGHT, HEATMAP_TEXT_BLACK], background);
278
+ return higherContrast("#ffffff", "#000000", background);
279
+ }
280
+
281
+ interface HeatmapEnd {
282
+ color: Oklab;
283
+ /** The theme's own token when it carries the scale as is. */
284
+ hex: string;
285
+ }
286
+
287
+ function fallbackEnd(hue: number, dark: boolean): HeatmapEnd {
288
+ const radians = hue * Math.PI / 180;
289
+ const color = toGamut([
290
+ dark ? HEATMAP_FALLBACK.lightness.dark : HEATMAP_FALLBACK.lightness.light,
291
+ HEATMAP_FALLBACK.chroma * Math.cos(radians),
292
+ HEATMAP_FALLBACK.chroma * Math.sin(radians),
293
+ ]);
294
+ return { color, hex: oklabToHex(color) };
295
+ }
296
+
297
+ /**
298
+ * The theme's up or down colour as the end of the scale. One that sits too
299
+ * close to the page keeps its hue at a lightness that stands clear; one with
300
+ * no hue to speak of gives way to the fallback.
301
+ */
302
+ function heatmapEnd(token: string, fallbackHue: number, flat: Oklab, page: Oklab, dark: boolean): HeatmapEnd {
303
+ const color = hexToOklab(token);
304
+ const chroma = chromaOf(color);
305
+ if (chroma < HEATMAP_END_MIN_CHROMA) return fallbackEnd(fallbackHue, dark);
306
+ if (oklabDistance(color, flat) >= HEATMAP_END_MIN_FROM_FLAT && oklabDistance(color, page) >= oklabDistance(flat, page)) {
307
+ return { color, hex: token };
308
+ }
309
+ const scale = Math.max(chroma, HEATMAP_FALLBACK.chroma) / chroma;
310
+ const lifted = toGamut([
311
+ dark ? HEATMAP_FALLBACK.lightness.dark : HEATMAP_FALLBACK.lightness.light,
312
+ color[1] * scale,
313
+ color[2] * scale,
314
+ ]);
315
+ return { color: lifted, hex: oklabToHex(lifted) };
316
+ }
317
+
318
+ interface HeatmapScale {
319
+ /** 2 * HEATMAP_STEPS + 1 tiles from full loss to full gain. */
320
+ tiles: HeatmapTileColors[];
321
+ selected: HeatmapTileColors[];
322
+ missing: HeatmapTileColors;
323
+ missingSelected: HeatmapTileColors;
324
+ ring: HeatmapSelectionRing;
202
325
  }
203
326
 
204
- const heatmapScaleCache = new Map<string, HeatmapTileColors[]>();
327
+ function buildHeatmapScale(palette: ThemeColors): HeatmapScale {
328
+ // Dark is defined as the theme defines it: text lighter than the page.
329
+ const dark = relativeLuminance(palette.text) > relativeLuminance(palette.bg);
330
+ const inks = heatmapInks(palette);
331
+ const page = hexToOklab(palette.bg);
332
+ // Halfway between the page's tint and the neutral's, so a warm page gets a warm grey and a black one the neutral's.
333
+ const neutral = hexToOklab(palette.neutral);
334
+ const grey: Oklab = [neutral[0], (page[1] + neutral[1]) / 2, (page[2] + neutral[2]) / 2];
335
+ const flat = standOffPage(palette.bg, tint(grey, HEATMAP_FLAT_MAX_CHROMA), dark ? HEATMAP_FLAT_CONTRAST.dark : HEATMAP_FLAT_CONTRAST.light, dark);
336
+ let loss = heatmapEnd(palette.negative, HEATMAP_FALLBACK.lossHue, flat, page, dark);
337
+ let gain = heatmapEnd(palette.positive, HEATMAP_FALLBACK.gainHue, flat, page, dark);
338
+ if (oklabDistance(loss.color, gain.color) < HEATMAP_ENDS_MIN_APART) {
339
+ loss = fallbackEnd(HEATMAP_FALLBACK.lossHue, dark);
340
+ gain = fallbackEnd(HEATMAP_FALLBACK.gainHue, dark);
341
+ }
205
342
 
206
- /** 2 * HEATMAP_STEPS + 1 colours from full loss to full gain, built once per light or dark page. */
207
- function heatmapScale(light: boolean): HeatmapTileColors[] {
208
- const key = light ? "light" : "dark";
209
- const cached = heatmapScaleCache.get(key);
210
- if (cached) return cached;
211
- const flat = light ? HEATMAP_FLAT_LIGHT : HEATMAP_FLAT_DARK;
212
- const stops = HEATMAP_STOPS[key];
213
- const scale: HeatmapTileColors[] = [];
343
+ const lift = dark ? inks.light : inks.dark;
344
+ const tile = (background: string): HeatmapTileColors => ({ background, foreground: heatmapTextColor(background, inks) });
345
+ const selectedTile = (background: string) => {
346
+ let ratio: number = HEATMAP_SELECTED_LIFT.start;
347
+ while (ratio < HEATMAP_SELECTED_LIFT.max && oklabDistance(hexToOklab(blendHex(background, lift, ratio)), hexToOklab(background)) < HEATMAP_SELECTED_MIN_DISTANCE) {
348
+ ratio += HEATMAP_SELECTED_LIFT.step;
349
+ }
350
+ return tile(blendHex(background, lift, Math.min(ratio, HEATMAP_SELECTED_LIFT.max)));
351
+ };
352
+ const tiles: HeatmapTileColors[] = [];
214
353
  for (let step = -HEATMAP_STEPS; step <= HEATMAP_STEPS; step += 1) {
354
+ const end = step < 0 ? loss : gain;
355
+ if (Math.abs(step) === HEATMAP_STEPS) {
356
+ tiles.push(tile(end.hex));
357
+ continue;
358
+ }
215
359
  const strength = (Math.abs(step) / HEATMAP_STEPS) ** HEATMAP_TILE_EASING;
216
- const path: readonly Lch[] = [flat, ...(step < 0 ? stops.loss : stops.gain)];
217
- const position = strength * (path.length - 1);
218
- const segment = Math.min(path.length - 2, Math.floor(position));
219
- const background = oklabToHex(lch(mixLch(path[segment]!, path[segment + 1]!, position - segment)));
220
- scale.push({ background, foreground: heatmapTextColor(background) });
360
+ const hue = strength ** HEATMAP_TILE_HUE_LEAD;
361
+ tiles.push(tile(oklabToHex([
362
+ flat[0] + (end.color[0] - flat[0]) * strength,
363
+ flat[1] + (end.color[1] - flat[1]) * hue,
364
+ flat[2] + (end.color[2] - flat[2]) * hue,
365
+ ])));
221
366
  }
222
- heatmapScaleCache.set(key, scale);
223
- return scale;
367
+ const missing = tile(oklabToHex(standOffPage(
368
+ palette.bg,
369
+ tint(grey, HEATMAP_MISSING_MAX_CHROMA),
370
+ dark ? HEATMAP_MISSING_CONTRAST.dark : HEATMAP_MISSING_CONTRAST.light,
371
+ dark,
372
+ )));
373
+ return {
374
+ tiles,
375
+ selected: tiles.map(({ background }) => selectedTile(background)),
376
+ missing,
377
+ missingSelected: selectedTile(missing.background),
378
+ ring: { outer: lift, inner: palette.bg },
379
+ };
224
380
  }
225
381
 
226
- function isLightPage(): boolean {
227
- return relativeLuminance(colors.bg) > 0.4;
228
- }
382
+ const heatmapScaleCache = new Map<string, HeatmapScale>();
229
383
 
230
384
  /**
231
- * The tile colours for a day's move in percent. Full strength at +/-3%; a
232
- * missing move is neutral grey, never the flat colour, so it cannot pass for
233
- * an unchanged price.
385
+ * Built once per palette and keyed by its colours, never by its name or a
386
+ * light or dark flag, so a theme switch or an edited palette recolours the
387
+ * map at once.
234
388
  */
235
- export function resolveHeatmapTileColors(changePercent: number | null | undefined): HeatmapTileColors {
236
- const light = isLightPage();
237
- if (changePercent == null || !Number.isFinite(changePercent)) {
238
- const background = light ? HEATMAP_MISSING_LIGHT : HEATMAP_MISSING_DARK;
239
- return { background, foreground: heatmapTextColor(background) };
389
+ function heatmapScale(palette: ThemeColors): HeatmapScale {
390
+ const key = `${palette.bg}|${palette.panel}|${palette.text}|${palette.textBright}|${palette.selectedText}|${palette.headerText}|${palette.neutral}|${palette.positive}|${palette.negative}`;
391
+ let scale = heatmapScaleCache.get(key);
392
+ if (!scale) {
393
+ scale = buildHeatmapScale(palette);
394
+ if (heatmapScaleCache.size >= HEATMAP_SCALE_CACHE_LIMIT) heatmapScaleCache.clear();
395
+ heatmapScaleCache.set(key, scale);
240
396
  }
397
+ return scale;
398
+ }
399
+
400
+ function heatmapStep(changePercent: number): number {
241
401
  const ratio = Math.max(-1, Math.min(1, changePercent / HEATMAP_TILE_FULL_SCALE_PERCENT));
242
- return heatmapScale(light)[Math.round(ratio * HEATMAP_STEPS) + HEATMAP_STEPS]!;
402
+ return Math.round(ratio * HEATMAP_STEPS) + HEATMAP_STEPS;
403
+ }
404
+
405
+ function hasMove(changePercent: number | null | undefined): changePercent is number {
406
+ return changePercent != null && Number.isFinite(changePercent);
243
407
  }
244
408
 
245
- const HEATMAP_SELECTED_LIFT = 0.45;
409
+ /**
410
+ * The tile colours for a day's move in percent. Full strength at +/-3%; a
411
+ * missing move is the theme's grey, never the flat colour, so it cannot pass
412
+ * for an unchanged price.
413
+ */
414
+ export function resolveHeatmapTileColors(
415
+ changePercent: number | null | undefined,
416
+ palette: ThemeColors = colors,
417
+ ): HeatmapTileColors {
418
+ const scale = heatmapScale(palette);
419
+ return hasMove(changePercent) ? scale.tiles[heatmapStep(changePercent)]! : scale.missing;
420
+ }
246
421
 
247
422
  /**
248
423
  * The selected tile on a cell grid, which cannot draw an outline: the same
249
- * hue lifted toward white, so the selection still says which way it moved.
424
+ * hue pulled away from the page, lighter on a dark theme and deeper on a
425
+ * light one, so the selection still says which way it moved.
250
426
  */
251
- export function resolveHeatmapSelectedTileColors(changePercent: number | null | undefined): HeatmapTileColors {
252
- const background = blendHex(resolveHeatmapTileColors(changePercent).background, "#ffffff", HEATMAP_SELECTED_LIFT);
253
- return { background, foreground: heatmapTextColor(background) };
427
+ export function resolveHeatmapSelectedTileColors(
428
+ changePercent: number | null | undefined,
429
+ palette: ThemeColors = colors,
430
+ ): HeatmapTileColors {
431
+ const scale = heatmapScale(palette);
432
+ return hasMove(changePercent) ? scale.selected[heatmapStep(changePercent)]! : scale.missingSelected;
433
+ }
434
+
435
+ /** The selected tile's outline where one can be drawn: the theme's text tone against the page, then a hairline of the page. */
436
+ export function resolveHeatmapSelectionRing(palette: ThemeColors = colors): HeatmapSelectionRing {
437
+ return heatmapScale(palette).ring;
254
438
  }
255
439
 
256
440
  const oklabCache = new Map<string, Oklab>();
@@ -267,7 +451,5 @@ export function heatmapColorDistance(left: string, right: string): number {
267
451
  }
268
452
  return value;
269
453
  };
270
- const [l1, a1, b1] = read(left);
271
- const [l2, a2, b2] = read(right);
272
- return Math.hypot(l1 - l2, a1 - a2, b1 - b2);
454
+ return oklabDistance(read(left), read(right));
273
455
  }
@@ -1647,7 +1647,7 @@ async function resolveChartSpecPass(
1647
1647
  || (request.bounds.end !== null && now() - (request.bounds.end + 1) < 60 * 60_000);
1648
1648
  const staleCurrent = (value: LoadedPriceHistory) => currentWindow() && !!value.session
1649
1649
  && isPriceHistoryStaleForCurrentWindow(value.points, now(), {
1650
- exchange: source.instrument.exchange, session: value.session,
1650
+ symbol: source.instrument.symbol, exchange: source.instrument.exchange, session: value.session,
1651
1651
  ...(value.resolution ? { intervalMs: CHART_RESOLUTION_STEP_MS[value.resolution] } : {}),
1652
1652
  });
1653
1653
  if (staleCurrent(loaded)) {
@@ -105,7 +105,7 @@ function freshSeedPoints(
105
105
  // Broker contract/session interpretation remains unproven, as at acquisition.
106
106
  const session = instrument.instrument ? undefined : result.session;
107
107
  if (currentWindow && isIntradayResolution(resolution) && isPriceHistoryStaleForCurrentWindow(points, now, {
108
- exchange: target.exchange, intervalMs: CHART_RESOLUTION_STEP_MS[resolution], session,
108
+ symbol: target.symbol, exchange: target.exchange, intervalMs: CHART_RESOLUTION_STEP_MS[resolution], session,
109
109
  })) return null;
110
110
  return points.length ? points : null;
111
111
  }
@@ -80,6 +80,12 @@ export type ContextMenuContext =
80
80
  layoutIndex: number;
81
81
  layoutName: string;
82
82
  active: boolean;
83
+ }
84
+ | {
85
+ /** A person's name or @mention in the chat. */
86
+ kind: "chat-user";
87
+ userId: string;
88
+ username: string | null;
83
89
  };
84
90
 
85
91
  export function hasRunnableContextMenuItem(items: readonly ContextMenuItem[]): boolean {
@@ -116,6 +116,8 @@ export interface MarketDataRequestContext {
116
116
  historyRequestKey?: string;
117
117
  /** Intraday history should include pre-market and after-hours bars where the source has them. */
118
118
  historySession?: "extended";
119
+ /** The listing's company, from its own quote: an SEC lookup for a non-US listing checks the registrant against it. */
120
+ listingName?: string;
119
121
  }
120
122
 
121
123
  export interface CachedFinancialsTarget {
@@ -58,6 +58,9 @@ export interface Quote {
58
58
  regularClose?: number;
59
59
  /** Exchange-local date of regularClose; separate from the daily previous-close reference. */
60
60
  regularCloseSessionDate?: string;
61
+ /** Move of that completed regular session from the one before it, in this quote's currency; set and cleared together with regularClose. */
62
+ regularChange?: number;
63
+ regularChangePercent?: number;
61
64
  /** Provider's exchange-local session date for the daily quote reference. */
62
65
  changeSessionDate?: string;
63
66
  high52w?: number;
@@ -71,7 +71,12 @@ export interface HeadlessPaneContext {
71
71
  settings?: Record<string, unknown>;
72
72
  capabilities?: CapabilityInvoker;
73
73
  /** Read one local portfolio without passing holdings through a remote endpoint. */
74
- resolvePortfolio?: (id: string) => Promise<{ portfolio: import("./ticker").Portfolio; tickers: import("./ticker").TickerRecord[] } | null>;
74
+ resolvePortfolio?: (id: string) => Promise<{
75
+ portfolio: import("./ticker").Portfolio;
76
+ tickers: import("./ticker").TickerRecord[];
77
+ /** The broker account the portfolio was last synced with, as saved on this device. */
78
+ account?: import("./trading").BrokerAccount | null;
79
+ } | null>;
75
80
  /** Read locally remembered watchlist membership. */
76
81
  resolveWatchlist?: (id: string) => Promise<import("./ticker").TickerRecord[] | null>;
77
82
  /** Resolve locally remembered exchange identities without coupling plugins to storage. */
@@ -97,6 +102,63 @@ export interface HeadlessPaneEntry {
97
102
  formatted?: string;
98
103
  }
99
104
 
105
+ /**
106
+ * How current a report's data is (docs/usage.md#how-current-a-report-is):
107
+ * - `live`: a real-time feed, such as a streaming venue or a real-time quote.
108
+ * - `delayed`: a feed held back on purpose, by `delayMinutes` when known.
109
+ * - `stale`: a feed or scheduled release whose newest observation is older
110
+ * than that kind of data allows.
111
+ * - `not-a-feed`: data that is not a feed at all (filings, fundamentals,
112
+ * calendars, statistics releases, calculators, local portfolio data). It
113
+ * never reads stale just because it is old.
114
+ */
115
+ export type HeadlessFreshnessStatus = "live" | "delayed" | "stale" | "not-a-feed";
116
+
117
+ /**
118
+ * What a report can cite about its data. Every field is optional: the report
119
+ * fills what is missing from the result itself (quote `dataSource`,
120
+ * `delayMinutes`, `stale`, `asOf`/`observedAt`/`lastUpdated` fields, the last
121
+ * point of each series), so a pane declares only what that would get wrong.
122
+ */
123
+ export interface HeadlessPaneFreshness {
124
+ /**
125
+ * Who a reader would cite: the venue, exchange or agency for primary data
126
+ * ("SEC EDGAR", "Hyperliquid"), "Gloom Cloud" for aggregated market data,
127
+ * "Local data" or "Your inputs". Never a data vendor or an internal provider id.
128
+ */
129
+ source?: string;
130
+ /** Newest observation in the data. A `YYYY-MM-DD` string reads as a date without a time. */
131
+ asOf?: string | number | Date | null;
132
+ /** Oldest observation, mentioned when it is far older than `asOf`; `null` when the rows are a history. */
133
+ oldest?: string | number | Date | null;
134
+ /**
135
+ * The row field that says when each row was observed, when it is not one of
136
+ * the standard names (`asOf`, `observedAt`, `lastUpdated`...). The report is
137
+ * then dated by that field alone, not by metadata stamps.
138
+ */
139
+ observedKey?: string;
140
+ status?: HeadlessFreshnessStatus;
141
+ /** How far a delayed feed is held back, in minutes. */
142
+ delayMinutes?: number;
143
+ /** What not-a-feed data is, in a few words: "filed data", "monthly release", "your inputs". */
144
+ basis?: string;
145
+ /** The newest observation is stale once it is older than this many minutes. */
146
+ maxAgeMinutes?: number;
147
+ /**
148
+ * The rows' and metadata's own `stale` flags mean something other than "this
149
+ * value is out of date" (a historical marker, a cache state), so the report
150
+ * judges staleness from the schedule alone.
151
+ */
152
+ ignoreStaleFlags?: boolean;
153
+ /**
154
+ * `daily`: one observation per US trading day, stale once more than one
155
+ * completed session has passed after the newest (a day's lag is allowed).
156
+ */
157
+ cadence?: "daily";
158
+ /** The newest observation is stale once this time (the next scheduled release) has passed by a day. */
159
+ nextExpectedAt?: string | number | Date | null;
160
+ }
161
+
100
162
  interface HeadlessPaneResultBase {
101
163
  /** False when usable output does not fully cover the requested inputs/depth. */
102
164
  complete?: boolean;
@@ -104,8 +166,17 @@ interface HeadlessPaneResultBase {
104
166
  symbols?: string[];
105
167
  /** Missing inputs must remain visible even when other inputs returned rows. */
106
168
  unavailableSymbols?: string[];
169
+ /** Failures: a source that did not answer, or a value that could not be computed. */
107
170
  errors?: string[];
171
+ /**
172
+ * Caveats about a report that did load: what it leaves out, what it assumes,
173
+ * how a value was marked. One sentence each. They never make a report fail;
174
+ * `complete: false` says when the report does not cover what was asked.
175
+ */
176
+ notes?: string[];
108
177
  metadata?: Record<string, unknown>;
178
+ /** What this load knows about its data's source and age; overrides the definition's `freshness`. */
179
+ freshness?: HeadlessPaneFreshness;
109
180
  }
110
181
 
111
182
  export interface HeadlessRowsResult extends HeadlessPaneResultBase {
@@ -185,8 +256,14 @@ export interface HeadlessPaneDefinition<Shape extends HeadlessPaneShape = Headle
185
256
  description?: string;
186
257
  argument: HeadlessPaneArgumentDef;
187
258
  options: HeadlessPaneOptionDef[];
259
+ /** What is true of every load: its source, and whether it is a feed. */
260
+ freshness?: HeadlessPaneFreshness;
188
261
  columns?: HeadlessPaneColumn[];
189
- describe?: string | ((args: HeadlessPaneLoadArgs) => string);
262
+ /**
263
+ * The report title. A report passes the loaded result, so a title can name
264
+ * what the load resolved (the view an `auto` query became, a fund's name).
265
+ */
266
+ describe?: string | ((args: HeadlessPaneLoadArgs, result?: HeadlessPaneResult) => string);
190
267
  load(
191
268
  args: HeadlessPaneLoadArgs,
192
269
  ctx: HeadlessPaneContext,
@@ -1,10 +1,11 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { AppTickerRepositoryPort } from "../core/app-service-ports";
3
- import type { HeadlessPaneDefinition } from "./headless";
3
+ import type { HeadlessPaneDefinition, HeadlessPaneFreshness } from "./headless";
4
4
 
5
5
  export type {
6
6
  HeadlessBundleResult,
7
7
  HeadlessBundleSection,
8
+ HeadlessFreshnessStatus,
8
9
  HeadlessPaneApiClient,
9
10
  HeadlessPaneArgumentDef,
10
11
  HeadlessPaneArgumentKind,
@@ -12,6 +13,7 @@ export type {
12
13
  HeadlessPaneContext,
13
14
  HeadlessPaneDefinition,
14
15
  HeadlessPaneEntry,
16
+ HeadlessPaneFreshness,
15
17
  HeadlessPaneLoadArgs,
16
18
  HeadlessPaneOptionDef,
17
19
  HeadlessPaneOptionType,
@@ -124,6 +126,12 @@ export interface PaneDef {
124
126
  tickerFollower?: boolean | ((pane: PaneInstanceConfig) => boolean);
125
127
  /** Renderer-neutral data model used by CLI functions, automation, and hosted tools. */
126
128
  headless?: HeadlessPaneDefinition;
129
+ /**
130
+ * Source and status a rendered-view report (`fn` on a pane without a
131
+ * `headless` model) cites, when "Gloom Cloud" with the state the footer
132
+ * shows would be wrong: local data, a calculator, filed records.
133
+ */
134
+ reportFreshness?: Pick<HeadlessPaneFreshness, "source" | "status" | "basis">;
127
135
  /** Add an Excel-compatible CSV action for the pane's single active DataTable. */
128
136
  tableExport?: true;
129
137
  settings?: PaneSettingsDef | ((context: PaneSettingsContext) => PaneSettingsDef | null);
@@ -146,6 +154,12 @@ export interface PaneQuickSettingDef {
146
154
  * it off picks the field's other option.
147
155
  */
148
156
  onValue?: string;
157
+ /**
158
+ * Shows the control only where it changes something, for a setting that
159
+ * applies to some of what the pane can show. The field stays in the
160
+ * settings dialog either way.
161
+ */
162
+ visible?: (context: PaneSettingsContext) => boolean;
149
163
  }
150
164
 
151
165
  export interface PaneSettingsContext {
@@ -264,6 +278,11 @@ interface PaneTemplateShortcut {
264
278
  aliases?: readonly string[];
265
279
  argPlaceholder?: string;
266
280
  argKind?: "text" | "ticker" | "ticker-list";
281
+ /**
282
+ * For a ticker list, entries kept as typed instead of resolved as tickers:
283
+ * CORR keeps map series (`GEO:HORMUZ`) beside its tickers.
284
+ */
285
+ keepArgToken?: (token: string) => boolean;
267
286
  argOptional?: boolean;
268
287
  /**
269
288
  * With no argument typed and none to infer from the active ticker, open