gloomberb 0.16.0 → 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 (691) 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 +44 -11
  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 +5 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/members.ts +26 -0
  10. package/src/api-client/paths.ts +30 -1
  11. package/src/api-client/perps.ts +41 -0
  12. package/src/api-client/request.ts +5 -2
  13. package/src/api-client/types.ts +9 -1
  14. package/src/app/global-shortcuts.ts +14 -6
  15. package/src/app/keybindings/actions.ts +1 -1
  16. package/src/app/runtime/update.ts +38 -2
  17. package/src/app.tsx +10 -6
  18. package/src/brokers/account-cache.ts +24 -0
  19. package/src/cli/commands/command-utils.ts +8 -0
  20. package/src/cli/commands/crypto-hints.ts +75 -0
  21. package/src/cli/commands/market.ts +414 -106
  22. package/src/cli/commands/overview.ts +77 -32
  23. package/src/cli/commands/ticker.ts +101 -43
  24. package/src/cli/desktop-pane-shot.ts +34 -4
  25. package/src/cli/freshness.ts +61 -0
  26. package/src/cli/help.ts +1 -0
  27. package/src/cli/helpers.ts +4 -8
  28. package/src/cli/index.ts +12 -2
  29. package/src/cli/listing-arg.ts +321 -0
  30. package/src/cli/pane-functions/access-gate.ts +42 -0
  31. package/src/cli/pane-functions/catalog.ts +28 -1
  32. package/src/cli/pane-functions/data.ts +3 -1
  33. package/src/cli/pane-functions/dom.ts +20 -2
  34. package/src/cli/pane-functions/freshness.ts +400 -0
  35. package/src/cli/pane-functions/function-help.ts +36 -22
  36. package/src/cli/pane-functions/headless.ts +39 -11
  37. package/src/cli/pane-functions/index.ts +15 -4
  38. package/src/cli/pane-functions/options.ts +3 -0
  39. package/src/cli/pane-functions/report.ts +4 -0
  40. package/src/cli/pane-functions/resolver.ts +35 -7
  41. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  42. package/src/cli/pane-functions/screenshot.ts +7 -3
  43. package/src/cli/result.ts +41 -27
  44. package/src/cli/ticker-resolution.ts +7 -5
  45. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  46. package/src/components/chart/composite/drawing-store.ts +59 -0
  47. package/src/components/chart/composite/legend.tsx +319 -0
  48. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  49. package/src/components/chart/composite/panel-gestures.ts +59 -0
  50. package/src/components/chart/composite/panel-labels.ts +107 -0
  51. package/src/components/chart/composite/panel-surface.tsx +876 -0
  52. package/src/components/chart/composite/tool-catalog.ts +98 -0
  53. package/src/components/chart/composite/toolbar.tsx +186 -0
  54. package/src/components/chart/composite/tools.ts +8 -0
  55. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  56. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  57. package/src/components/command-bar/commands/collection.ts +5 -1
  58. package/src/components/command-bar/list/model.ts +5 -0
  59. package/src/components/command-bar/list/view.tsx +16 -3
  60. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  61. package/src/components/command-bar/routes/root/command-items.ts +9 -2
  62. package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
  63. package/src/components/command-bar/routes/root/provider-search.ts +19 -5
  64. package/src/components/command-bar/routes/root/runtime.ts +14 -5
  65. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  66. package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
  67. package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
  68. package/src/components/command-bar/routing/actions.ts +2 -0
  69. package/src/components/command-bar/selection-runtime.ts +38 -0
  70. package/src/components/command-bar/surface/index.tsx +7 -2
  71. package/src/components/command-bar/workflow/ops.ts +1 -1
  72. package/src/components/command-bar/workflow/tickers.ts +6 -0
  73. package/src/components/data-table/view.tsx +29 -10
  74. package/src/components/feedback-dialog.tsx +2 -1
  75. package/src/components/form-modal/field-row.tsx +2 -2
  76. package/src/components/index.ts +2 -2
  77. package/src/components/layout/detached-pane-shell.tsx +6 -3
  78. package/src/components/layout/floating-pane.tsx +6 -0
  79. package/src/components/layout/header.tsx +24 -7
  80. package/src/components/layout/missing-pane.tsx +2 -2
  81. package/src/components/layout/pane/content.tsx +23 -10
  82. package/src/components/layout/pane/error-boundary.tsx +103 -0
  83. package/src/components/layout/pane/footer/registration.tsx +68 -23
  84. package/src/components/layout/pane/header.tsx +61 -28
  85. package/src/components/layout/pane/index.tsx +6 -0
  86. package/src/components/layout/pane/title.ts +31 -7
  87. package/src/components/layout/shell/drag/index.ts +6 -5
  88. package/src/components/layout/shell/drag/runtime.ts +3 -0
  89. package/src/components/layout/shell/index.tsx +6 -0
  90. package/src/components/layout/shell/menu.ts +2 -1
  91. package/src/components/layout/shell/pane/actions.ts +2 -1
  92. package/src/components/layout/shell/pane/layers.tsx +29 -10
  93. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
  94. package/src/components/layout/shell/ticker-link-menu.ts +23 -9
  95. package/src/components/metric-treemap/heat-surface.tsx +745 -0
  96. package/src/components/metric-treemap/heat-tiles.ts +228 -0
  97. package/src/components/metric-treemap/index.tsx +2 -0
  98. package/src/components/metric-treemap/layout.ts +8 -0
  99. package/src/components/metric-treemap/scene.ts +432 -0
  100. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  101. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  102. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  103. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  104. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  105. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
  106. package/src/components/ticker/list-table-view.tsx +13 -1
  107. package/src/components/toggle-list.tsx +38 -12
  108. package/src/components/ui/country-flag-art.tsx +449 -0
  109. package/src/components/ui/country-flag.tsx +41 -0
  110. package/src/components/ui/data-table/types.ts +13 -0
  111. package/src/components/ui/fields.tsx +8 -0
  112. package/src/components/ui/icon.tsx +2 -0
  113. package/src/components/ui/index.ts +4 -0
  114. package/src/components/ui/multi-select/dialog.tsx +108 -22
  115. package/src/components/ui/range-track.tsx +53 -0
  116. package/src/components/ui/status.tsx +8 -2
  117. package/src/components/ui/tabs.tsx +11 -4
  118. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  119. package/src/core/state/app/types.ts +10 -1
  120. package/src/data/config/store/normalize.ts +17 -1
  121. package/src/i18n/es.ts +24 -4
  122. package/src/i18n/ja.ts +24 -4
  123. package/src/i18n/ko.ts +24 -4
  124. package/src/i18n/zh-cn.ts +24 -4
  125. package/src/i18n/zh-tw.ts +24 -4
  126. package/src/layout/ticker-navigation.ts +28 -2
  127. package/src/market-data/coordinator/chart.ts +1 -1
  128. package/src/market-data/coordinator/quotes.ts +23 -4
  129. package/src/market-data/fx-closes.ts +72 -0
  130. package/src/market-data/market/freshness.ts +78 -6
  131. package/src/market-data/market/session-close-note.ts +57 -0
  132. package/src/market-data/market/status.ts +151 -0
  133. package/src/market-data/published-apac-sessions.ts +66 -0
  134. package/src/market-data/quotes/contributions.ts +8 -0
  135. package/src/market-data/quotes/freshness.ts +36 -0
  136. package/src/market-data/quotes/resolution.ts +24 -8
  137. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  138. package/src/market-data/quotes/time.ts +16 -0
  139. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  140. package/src/plugins/builtin/alerts/cli.ts +10 -5
  141. package/src/plugins/builtin/alerts/index.tsx +1 -0
  142. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  143. package/src/plugins/builtin/analytics/risk-client.ts +330 -79
  144. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  145. package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
  146. package/src/plugins/builtin/analytics/risk-math.ts +33 -13
  147. package/src/plugins/builtin/analytics/risk-model.ts +282 -64
  148. package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
  149. package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
  150. package/src/plugins/builtin/attention/headless.ts +6 -4
  151. package/src/plugins/builtin/attention/index.tsx +1 -1
  152. package/src/plugins/builtin/attention/pane.tsx +1 -1
  153. package/src/plugins/builtin/awards/headless.ts +1 -0
  154. package/src/plugins/builtin/awards/pane.tsx +1 -1
  155. package/src/plugins/builtin/backtest/headless.ts +1 -0
  156. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  157. package/src/plugins/builtin/buildout/cells.tsx +15 -12
  158. package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
  159. package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
  160. package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
  161. package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
  162. package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
  163. package/src/plugins/builtin/buildout/index.tsx +1 -0
  164. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  165. package/src/plugins/builtin/catalysts/index.tsx +2 -2
  166. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  167. package/src/plugins/builtin/cds/headless.ts +2 -0
  168. package/src/plugins/builtin/cds/index.tsx +1 -0
  169. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  170. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  171. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  172. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  173. package/src/plugins/builtin/chat/channels.ts +19 -3
  174. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  175. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  176. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  177. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  178. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  179. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  180. package/src/plugins/builtin/chat/index.tsx +1 -0
  181. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  182. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  183. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  184. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  185. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  186. package/src/plugins/builtin/chat/message/types.ts +14 -2
  187. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  188. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  189. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  190. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  191. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  192. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  193. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  194. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  195. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  196. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  197. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  198. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  199. package/src/plugins/builtin/correlation/compute.ts +59 -16
  200. package/src/plugins/builtin/correlation/geo.ts +34 -0
  201. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  202. package/src/plugins/builtin/correlation/headless.ts +42 -8
  203. package/src/plugins/builtin/correlation/history.ts +2 -0
  204. package/src/plugins/builtin/correlation/index.tsx +68 -14
  205. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  206. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  207. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  208. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  209. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  210. package/src/plugins/builtin/correlation/settings.ts +1 -1
  211. package/src/plugins/builtin/cot/headless.ts +6 -3
  212. package/src/plugins/builtin/cot/index.tsx +3 -3
  213. package/src/plugins/builtin/cot/model.ts +36 -3
  214. package/src/plugins/builtin/cpi/headless.ts +4 -0
  215. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  216. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  217. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  218. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  219. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  220. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  221. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  222. package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
  223. package/src/plugins/builtin/dividend-yield/client.ts +4 -2
  224. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  225. package/src/plugins/builtin/doe/headless.ts +7 -0
  226. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  227. package/src/plugins/builtin/earnings/client.ts +2 -2
  228. package/src/plugins/builtin/earnings/headless.ts +5 -0
  229. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  230. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  231. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  232. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  233. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  234. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  235. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  236. package/src/plugins/builtin/econ/index.tsx +1 -0
  237. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  238. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  239. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  240. package/src/plugins/builtin/executives/index.tsx +1 -0
  241. package/src/plugins/builtin/exposure/headless.ts +3 -1
  242. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  243. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  244. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  245. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  246. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  247. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  248. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  249. package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
  250. package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
  251. package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
  252. package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
  253. package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
  254. package/src/plugins/builtin/gpu/headless.ts +7 -3
  255. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  256. package/src/plugins/builtin/gpu/model.ts +27 -1
  257. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  258. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  259. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  260. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  261. package/src/plugins/builtin/holders/headless.ts +139 -5
  262. package/src/plugins/builtin/holders/index.tsx +10 -3
  263. package/src/plugins/builtin/holders/pane.tsx +20 -3
  264. package/src/plugins/builtin/holders/report-header.ts +95 -0
  265. package/src/plugins/builtin/holders/table-model.ts +20 -5
  266. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  267. package/src/plugins/builtin/holders/types.ts +2 -1
  268. package/src/plugins/builtin/insider/headless.ts +2 -0
  269. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  270. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  271. package/src/plugins/builtin/jobs/headless.ts +1 -0
  272. package/src/plugins/builtin/jobs/index.tsx +1 -0
  273. package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
  274. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  275. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  276. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  277. package/src/plugins/builtin/market-heatmap/data.ts +30 -2
  278. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  279. package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
  280. package/src/plugins/builtin/market-heatmap/live.ts +88 -0
  281. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  282. package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
  283. package/src/plugins/builtin/market-movers/client.ts +3 -2
  284. package/src/plugins/builtin/market-movers/headless.ts +10 -1
  285. package/src/plugins/builtin/market-movers/screener.ts +18 -5
  286. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  287. package/src/plugins/builtin/members/client.ts +53 -0
  288. package/src/plugins/builtin/members/headless.ts +35 -0
  289. package/src/plugins/builtin/members/index.tsx +20 -0
  290. package/src/plugins/builtin/members/model.ts +68 -0
  291. package/src/plugins/builtin/members/pane.tsx +175 -0
  292. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  293. package/src/plugins/builtin/mna/headless.ts +1 -0
  294. package/src/plugins/builtin/mna/index.tsx +2 -1
  295. package/src/plugins/builtin/mna/pane.tsx +5 -2
  296. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  297. package/src/plugins/builtin/news/headless.ts +2 -0
  298. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  299. package/src/plugins/builtin/notes/cli.ts +14 -6
  300. package/src/plugins/builtin/notes/index.tsx +1 -0
  301. package/src/plugins/builtin/openfda/index.tsx +1 -0
  302. package/src/plugins/builtin/options/index.tsx +2 -1
  303. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  304. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  305. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  306. package/src/plugins/builtin/pe-band/client.ts +74 -2
  307. package/src/plugins/builtin/pe-band/headless.ts +26 -8
  308. package/src/plugins/builtin/pe-band/model.ts +102 -22
  309. package/src/plugins/builtin/pe-band/pane.tsx +34 -16
  310. package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
  311. package/src/plugins/builtin/perps/client.ts +66 -5
  312. package/src/plugins/builtin/perps/equity-identity.ts +16 -0
  313. package/src/plugins/builtin/perps/equity-row.tsx +6 -4
  314. package/src/plugins/builtin/perps/headless.ts +144 -16
  315. package/src/plugins/builtin/perps/index.tsx +6 -6
  316. package/src/plugins/builtin/perps/model.ts +189 -12
  317. package/src/plugins/builtin/perps/pane.tsx +248 -47
  318. package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
  319. package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
  320. package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
  321. package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
  322. package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
  323. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  324. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  325. package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
  326. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  327. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  328. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  329. package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
  330. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  331. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  332. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  333. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  334. package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
  335. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
  336. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
  337. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  338. package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
  339. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  340. package/src/plugins/builtin/power/headless.ts +3 -1
  341. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  342. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  343. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  344. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  345. package/src/plugins/builtin/research/events-headless.ts +2 -0
  346. package/src/plugins/builtin/research/headless.ts +2 -0
  347. package/src/plugins/builtin/research/index.tsx +1 -0
  348. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  349. package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
  350. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  351. package/src/plugins/builtin/research-search/index.tsx +1 -0
  352. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  353. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  354. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  355. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  356. package/src/plugins/builtin/scanner/headless.ts +14 -0
  357. package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
  358. package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
  359. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  360. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  361. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  362. package/src/plugins/builtin/sec/forms.ts +12 -0
  363. package/src/plugins/builtin/sec/headless.ts +2 -0
  364. package/src/plugins/builtin/sectors/client.ts +1 -0
  365. package/src/plugins/builtin/sectors/headless.ts +9 -1
  366. package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
  367. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  368. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  369. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  370. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  371. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  372. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  373. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  374. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  375. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  376. package/src/plugins/builtin/social-mentions/index.tsx +1 -1
  377. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  378. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  379. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  380. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  381. package/src/plugins/builtin/themes/headless.ts +3 -0
  382. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  383. package/src/plugins/builtin/thirteenf/index.tsx +2 -1
  384. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  385. package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
  386. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  387. package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
  388. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
  389. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
  390. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
  391. package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
  392. package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
  393. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
  394. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
  395. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  396. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  397. package/src/plugins/builtin/vol-surface/index.tsx +1 -1
  398. package/src/plugins/builtin/volatility/headless.ts +6 -1
  399. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  400. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
  401. package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
  402. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  403. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  404. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  405. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  406. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  407. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  408. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  409. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
  410. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  411. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  412. package/src/plugins/builtin/world-venue-map/index.ts +67 -4
  413. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
  414. package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
  415. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  416. package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
  417. package/src/plugins/builtin/world-venue-map/model.ts +7 -4
  418. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  564. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  565. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  566. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  567. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  568. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  569. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  570. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  571. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  572. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  573. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  574. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  575. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  576. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  577. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  578. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  579. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  580. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  581. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  582. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  583. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  584. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  585. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  586. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  587. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  588. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  589. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  590. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  591. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  592. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  593. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  594. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  595. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  596. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  597. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  598. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  599. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  600. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  601. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  602. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  603. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  604. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  605. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  606. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  607. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  608. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  609. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  610. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  611. package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
  612. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  613. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  614. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  615. package/src/plugins/catalog-browser.ts +2 -0
  616. package/src/plugins/catalog-manifest.ts +1 -0
  617. package/src/plugins/catalog-ui.ts +3 -1
  618. package/src/plugins/catalog.ts +1 -1
  619. package/src/plugins/host-link.ts +33 -1
  620. package/src/plugins/installer.ts +48 -12
  621. package/src/plugins/loader.ts +30 -3
  622. package/src/plugins/manager-node.ts +15 -5
  623. package/src/plugins/registry/index.ts +1 -1
  624. package/src/plugins/registry/pane-settings.ts +26 -7
  625. package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
  626. package/src/renderers/dom/build-assets.ts +81 -3
  627. package/src/renderers/dom/data-table/row.tsx +52 -16
  628. package/src/renderers/dom/desktop/controls.tsx +7 -3
  629. package/src/renderers/dom/desktop/icons.tsx +1 -0
  630. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  631. package/src/renderers/dom/desktop/popover.tsx +73 -14
  632. package/src/renderers/dom/host/box.tsx +69 -26
  633. package/src/renderers/dom/host/input.tsx +14 -3
  634. package/src/renderers/dom/host/tabs.tsx +37 -1
  635. package/src/renderers/dom/styles.css +41 -7
  636. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
  638. package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
  639. package/src/renderers/electrobun/bun/index.ts +73 -6
  640. package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
  641. package/src/renderers/electrobun/shared/protocol.ts +3 -0
  642. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  643. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
  644. package/src/renderers/electrobun/view/main.tsx +7 -1
  645. package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
  646. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  647. package/src/renderers/electrobun/view/update-host.ts +45 -21
  648. package/src/renderers/opentui/host.tsx +5 -0
  649. package/src/sources/gloomberb-cloud/index.ts +25 -4
  650. package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
  651. package/src/sources/provider-router/cached-routes.ts +4 -1
  652. package/src/sources/provider-router/financials.ts +11 -8
  653. package/src/sources/provider-router/history.ts +15 -10
  654. package/src/sources/sec-registrant.ts +75 -0
  655. package/src/state/app/context/index.tsx +24 -8
  656. package/src/state/hooks/quote-streaming.ts +41 -26
  657. package/src/sync/core-contributors.ts +4 -0
  658. package/src/telemetry/benign-window-error.ts +7 -0
  659. package/src/telemetry/crash-reports-dom.ts +2 -0
  660. package/src/telemetry/crash-reports.ts +4 -1
  661. package/src/test-support/cli-context.ts +10 -2
  662. package/src/test-support/daily-nav.ts +25 -0
  663. package/src/theme/heat-colors.ts +357 -2
  664. package/src/tickers/instrument-kind.ts +34 -7
  665. package/src/tickers/search/asset-classes.ts +24 -9
  666. package/src/tickers/search/index.ts +44 -11
  667. package/src/tickers/search/ranking.ts +23 -3
  668. package/src/time-series/resolve.ts +1 -1
  669. package/src/time-series/use-chart-resolution.ts +1 -1
  670. package/src/types/context-menu.ts +6 -0
  671. package/src/types/data-provider.ts +2 -0
  672. package/src/types/financials.ts +5 -0
  673. package/src/types/headless.ts +79 -2
  674. package/src/types/plugin.ts +38 -6
  675. package/src/types/ticker.ts +15 -0
  676. package/src/ui/context-menu.tsx +1 -0
  677. package/src/ui/host.tsx +16 -0
  678. package/src/updater/index.ts +38 -13
  679. package/src/utils/async-deadline.ts +21 -0
  680. package/src/utils/cli-output.ts +5 -1
  681. package/src/utils/crypto-pair.ts +41 -0
  682. package/src/utils/currency-units.ts +14 -0
  683. package/src/utils/depositary-receipt.ts +26 -0
  684. package/src/utils/exchanges.ts +72 -0
  685. package/src/utils/fire-and-forget.ts +24 -0
  686. package/src/utils/format.ts +13 -0
  687. package/src/utils/price-earnings.ts +70 -3
  688. package/src/utils/price-history.ts +58 -13
  689. package/src/utils/rpc-timeout-error.ts +27 -0
  690. package/src/utils/sec.ts +13 -1
  691. package/src/utils/utc-time.ts +79 -0
@@ -0,0 +1,7 @@
1
+ const RESIZE_OBSERVER_LOOP = /resizeobserver loop/i;
2
+
3
+ /** Chromium reports this when a resize callback changes layout in the same frame. It is a notice, not a crashed renderer. */
4
+ export function isBenignWindowError(error: unknown): boolean {
5
+ const message = error instanceof Error ? error.message : String(error ?? "");
6
+ return RESIZE_OBSERVER_LOOP.test(message);
7
+ }
@@ -1,4 +1,5 @@
1
1
  import type { StorageLike } from "../data/json-storage";
2
+ import { isBenignWindowError } from "./benign-window-error";
2
3
  import { flushCrashReports, reportCrash } from "./crash-reports";
3
4
 
4
5
  /** The desktop view and the web terminal: window-level errors and the browser's install id. */
@@ -55,6 +56,7 @@ export function describeBrowserOs(): string {
55
56
  */
56
57
  export function installWindowCrashListeners(target: Window = window): () => void {
57
58
  const onError = (event: ErrorEvent) => {
59
+ if (isBenignWindowError(event.error) || isBenignWindowError(event.message)) return;
58
60
  reportCrash(event.error ?? event.message, { kind: "uncaught" });
59
61
  };
60
62
  const onRejection = (event: PromiseRejectionEvent) => {
@@ -6,6 +6,7 @@ import {
6
6
  type CrashReportsPayload,
7
7
  } from "../api-client";
8
8
  import type { TelemetryConfig } from "../types/config";
9
+ import { isSleepRpcTimeout } from "../utils/rpc-timeout-error";
9
10
  import { VERSION } from "../version";
10
11
 
11
12
  /**
@@ -172,10 +173,12 @@ function toReportError(error: unknown, context: CrashReportContext): PendingErro
172
173
  /**
173
174
  * Queues one error. Safe to call from any error handler: it never throws,
174
175
  * never awaits, and drops the error when reporting is off, already seen this
175
- * session, or over the session cap.
176
+ * session, or over the session cap. A desktop request timeout that fired
177
+ * after the machine slept is not an error at all and is dropped too.
176
178
  */
177
179
  export function reportCrash(error: unknown, context: CrashReportContext): void {
178
180
  try {
181
+ if (isSleepRpcTimeout(error)) return;
179
182
  if (host && !host.isEnabled()) return;
180
183
  if (accepted >= MAX_ERRORS_PER_SESSION) return;
181
184
  const entry = toReportError(error, context);
@@ -8,7 +8,8 @@ export interface PrintedCliResult {
8
8
  }
9
9
 
10
10
  /**
11
- * A command context whose `initMarketData` resolves to `market` (config, store, dataProvider, ...).
11
+ * A command context whose `initMarketData` and `initConfigData` resolve to `market` (config, store, dataProvider, ...),
12
+ * with an empty ticker store unless `market` brings one.
12
13
  * `fail` throws, every printResult call is kept in `printed`, and `closeCount` reports how many
13
14
  * times the command closed its persistence.
14
15
  */
@@ -18,9 +19,16 @@ export function createTestCliContext(
18
19
  ): { context: CliCommandContext; printed: PrintedCliResult[]; closeCount: () => number } {
19
20
  const printed: PrintedCliResult[] = [];
20
21
  let closed = 0;
22
+ const init = async () => ({
23
+ persistence: { close: () => { closed += 1; } },
24
+ // Commands look up the saved listing of every symbol they are given.
25
+ store: { loadTicker: async () => null, loadAllTickers: async () => [] },
26
+ ...market,
27
+ });
21
28
  const context = {
22
29
  cliOptions: { ...DEFAULT_CLI_OPTIONS, ...cliOptions },
23
- initMarketData: async () => ({ persistence: { close: () => { closed += 1; } }, ...market }),
30
+ initMarketData: init,
31
+ initConfigData: init,
24
32
  printResult: (result: CliResult<any>, options?: CliResultRenderOptions<any, any>) => { printed.push({ result, options }); },
25
33
  fail: (message: string): never => { throw new Error(message); },
26
34
  } as unknown as CliCommandContext;
@@ -0,0 +1,25 @@
1
+ import type { Quote } from "../types/financials";
2
+
3
+ /** Daily fund observation supplied by the standard quote and financials routes. */
4
+ export function createDailyNavQuote(overrides: Partial<Quote> = {}): Quote {
5
+ return {
6
+ symbol: "VFIAX",
7
+ name: "Vanguard 500 Index Fund Admiral Shares",
8
+ instrumentType: "MUTUALFUND",
9
+ priceObservation: "nav",
10
+ priceBasis: "per-unit",
11
+ price: 721.63,
12
+ previousClose: 718.5,
13
+ change: 3.13,
14
+ changePercent: 3.13 / 718.5 * 100,
15
+ currency: "USD",
16
+ changeSessionDate: "2026-10-06",
17
+ lastUpdated: 1791259200000,
18
+ listingExchangeName: "NASDAQ",
19
+ exchangeName: "NMS",
20
+ dataSource: "delayed",
21
+ stale: false,
22
+ sessionConfidence: "unknown",
23
+ ...overrides,
24
+ };
25
+ }
@@ -1,5 +1,5 @@
1
- import { colors } from "./colors";
2
- import { blendHex, contrastRatio } 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;
@@ -98,3 +98,358 @@ export function resolveHeatCellColors(
98
98
  foreground: readableForeground(baseBackground),
99
99
  };
100
100
  }
101
+
102
+ /**
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.
111
+ */
112
+ const HEATMAP_TILE_FULL_SCALE_PERCENT = 3;
113
+ /** How fast colour builds from flat: below 1 a small move already leans to its side. */
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;
117
+ const HEATMAP_TILE_TEXT_MIN_CONTRAST = 4.5;
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,
145
+ } as const;
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;
149
+ const HEATMAP_STEPS = 64;
150
+ const HEATMAP_SCALE_CACHE_LIMIT = 32;
151
+
152
+ export interface HeatmapTileColors {
153
+ background: string;
154
+ foreground: string;
155
+ }
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
+
163
+ type Oklab = readonly [number, number, number];
164
+
165
+ function srgbToLinear(channel: number): number {
166
+ const value = channel / 255;
167
+ return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
168
+ }
169
+
170
+ function linearToSrgb(channel: number): number {
171
+ const value = channel <= 0.0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - 0.055;
172
+ return Math.round(Math.max(0, Math.min(1, value)) * 255);
173
+ }
174
+
175
+ /** OKLab, so equal steps of the scale look like equal steps of colour. */
176
+ export function hexToOklab(hex: string): Oklab {
177
+ const h = hex.replace("#", "");
178
+ const r = srgbToLinear(parseInt(h.slice(0, 2), 16));
179
+ const g = srgbToLinear(parseInt(h.slice(2, 4), 16));
180
+ const b = srgbToLinear(parseInt(h.slice(4, 6), 16));
181
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
182
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
183
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
184
+ return [
185
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
186
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
187
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
188
+ ];
189
+ }
190
+
191
+ function oklabToLinear([lightness, a, b]: Oklab): [number, number, number] {
192
+ const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;
193
+ const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;
194
+ const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;
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]);
230
+ }
231
+
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]);
254
+ }
255
+
256
+ interface HeatmapInks {
257
+ light: string;
258
+ dark: string;
259
+ }
260
+
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);
269
+ return {
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"),
272
+ };
273
+ }
274
+
275
+ function heatmapTextColor(background: string, inks: HeatmapInks): string {
276
+ const best = higherContrast(inks.light, inks.dark, background);
277
+ if (contrastRatio(best, background) >= HEATMAP_TILE_TEXT_MIN_CONTRAST) return best;
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;
325
+ }
326
+
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
+ }
342
+
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[] = [];
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
+ }
359
+ const strength = (Math.abs(step) / HEATMAP_STEPS) ** HEATMAP_TILE_EASING;
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
+ ])));
366
+ }
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
+ };
380
+ }
381
+
382
+ const heatmapScaleCache = new Map<string, HeatmapScale>();
383
+
384
+ /**
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.
388
+ */
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);
396
+ }
397
+ return scale;
398
+ }
399
+
400
+ function heatmapStep(changePercent: number): number {
401
+ const ratio = Math.max(-1, Math.min(1, changePercent / HEATMAP_TILE_FULL_SCALE_PERCENT));
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);
407
+ }
408
+
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
+ }
421
+
422
+ /**
423
+ * The selected tile on a cell grid, which cannot draw an outline: the same
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.
426
+ */
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;
438
+ }
439
+
440
+ const oklabCache = new Map<string, Oklab>();
441
+
442
+ /** Perceptual distance between two tile colours; about 0.02 is the smallest step the eye notices. */
443
+ export function heatmapColorDistance(left: string, right: string): number {
444
+ if (left === right) return 0;
445
+ const read = (hex: string) => {
446
+ let value = oklabCache.get(hex);
447
+ if (!value) {
448
+ value = hexToOklab(hex);
449
+ if (oklabCache.size > 2048) oklabCache.clear();
450
+ oklabCache.set(hex, value);
451
+ }
452
+ return value;
453
+ };
454
+ return oklabDistance(read(left), read(right));
455
+ }
@@ -56,9 +56,13 @@ const KIND_BY_TYPE: Record<string, TickerInstrumentKind> = {
56
56
  CMDTY: "other",
57
57
  };
58
58
 
59
+ function normalizeInstrumentType(type: string | null | undefined): string {
60
+ return (type ?? "").trim().toUpperCase().replace(/[\s_-]+/g, "");
61
+ }
62
+
59
63
  /** A provider or broker type string, or null when it names nothing known. */
60
64
  export function classifyInstrumentType(type: string | null | undefined): TickerInstrumentKind | null {
61
- const normalized = (type ?? "").trim().toUpperCase().replace(/[\s_-]+/g, "");
65
+ const normalized = normalizeInstrumentType(type);
62
66
  if (!normalized) return null;
63
67
  const exact = KIND_BY_TYPE[normalized];
64
68
  if (exact) return exact;
@@ -82,6 +86,34 @@ function kindFromListing(ticker: TickerRecord | null | undefined): TickerInstrum
82
86
  return ticker ? kindFromListingSyntax(ticker.metadata.ticker, ticker.metadata.exchange) : null;
83
87
  }
84
88
 
89
+ function instrumentTypes(
90
+ ticker: TickerRecord | null | undefined,
91
+ financials?: Pick<TickerFinancials, "quote" | "quoteMetadata"> | null,
92
+ ) {
93
+ return [
94
+ financials?.quote?.instrumentType,
95
+ financials?.quoteMetadata?.instrumentType,
96
+ ticker?.metadata.broker_contracts?.[0]?.secType,
97
+ ticker?.metadata.assetCategory,
98
+ ];
99
+ }
100
+
101
+ /**
102
+ * Explicit mutual-fund and money-market shares have neither listed options nor
103
+ * 13F-reportable ownership. Use the kind resolver's type precedence; generic
104
+ * funds, ETFs and closed-end funds stay eligible.
105
+ */
106
+ export function isKnownMutualFund(
107
+ ticker: TickerRecord | null | undefined,
108
+ financials?: Pick<TickerFinancials, "quote" | "quoteMetadata"> | null,
109
+ ): boolean {
110
+ const type = instrumentTypes(ticker, financials).find((candidate) => {
111
+ const kind = classifyInstrumentType(candidate);
112
+ return kind !== null && kind !== "equity";
113
+ });
114
+ return ["MUTUALFUND", "MONEYMARKET", "MONEYMARKETFUND"].includes(normalizeInstrumentType(type));
115
+ }
116
+
85
117
  /**
86
118
  * The ticker's instrument kind from its quote, broker contract, saved type and
87
119
  * listing syntax. Brokers file funds and stocks under one generic type (`STK`),
@@ -93,12 +125,7 @@ export function resolveTickerInstrumentKind(
93
125
  ticker: TickerRecord | null | undefined,
94
126
  financials?: Pick<TickerFinancials, "quote" | "quoteMetadata"> | null,
95
127
  ): TickerInstrumentKind {
96
- const typed = [
97
- financials?.quote?.instrumentType,
98
- financials?.quoteMetadata?.instrumentType,
99
- ticker?.metadata.broker_contracts?.[0]?.secType,
100
- ticker?.metadata.assetCategory,
101
- ].map(classifyInstrumentType);
128
+ const typed = instrumentTypes(ticker, financials).map(classifyInstrumentType);
102
129
  return typed.find((kind) => kind !== null && kind !== "equity")
103
130
  ?? kindFromListing(ticker)
104
131
  ?? "equity";
@@ -3,15 +3,27 @@ import type { TickerSearchInstrumentClass } from "./types";
3
3
 
4
4
  /**
5
5
  * Class codes typed after a symbol or name, the way a terminal's market
6
- * sector key follows a ticker: `ES FUT`, `EURUSD CUR`, `SPY ETF`. The same
7
- * letters are the badge on a matching search row, so the list teaches them.
8
- * A code on its own is never a filter: `EQ` is still Equillium, and `FUT` and
9
- * `ETF` still open their panes.
6
+ * sector key follows a ticker: `ES FUT`, `EURUSD CUR`, `BTC CRYP`, `SPY ETF`.
7
+ * The same letters are the badge on a matching search row, so the list teaches
8
+ * them. A code on its own is never a filter: `EQ` is still Equillium, and
9
+ * `FUT`, `ETF` and `CRYP` still open their panes.
10
10
  */
11
- const ASSET_CLASS_CODES = ["EQ", "CUR", "OPT", "FUT", "IDX", "ETF"] as const;
11
+ const ASSET_CLASS_CODES = ["EQ", "CUR", "CRYP", "OPT", "FUT", "IDX", "ETF", "FUND"] as const;
12
12
 
13
13
  export type AssetClassCode = (typeof ASSET_CLASS_CODES)[number];
14
14
 
15
+ /**
16
+ * Whether a query's code keeps a row badged `rowCode`. CUR keeps coins and
17
+ * FUND keeps exchange-traded funds as well: `BTC CUR` is the coin, as the
18
+ * market sector key files it, and a fund name typed in full ends in "Fund"
19
+ * whether or not the fund trades on an exchange (Technology Select Sector
20
+ * SPDR Fund is XLK).
21
+ */
22
+ export function assetClassKeeps(code: AssetClassCode, rowCode: AssetClassCode | null): boolean {
23
+ if (rowCode === code) return true;
24
+ return (code === "CUR" && rowCode === "CRYP") || (code === "FUND" && rowCode === "ETF");
25
+ }
26
+
15
27
  export interface AssetClassQuery {
16
28
  code: AssetClassCode;
17
29
  /** The symbol or name typed before the code. */
@@ -45,6 +57,8 @@ export function assetClassMarketSymbol(query: AssetClassQuery): string | null {
45
57
  return `^${symbol}`;
46
58
  case "CUR":
47
59
  return /^[A-Z]{6}$/.test(symbol) ? `${symbol}=X` : `${symbol}-USD`;
60
+ case "CRYP":
61
+ return `${symbol}-USD`;
48
62
  default:
49
63
  return null;
50
64
  }
@@ -57,8 +71,8 @@ function isExchangeTradedType(type: string): boolean {
57
71
 
58
72
  /**
59
73
  * The class code of a search row: its type when the type names one, else its
60
- * listing syntax (`=F`, `=X`, `^`, the crypto venue). Coins count as currency.
61
- * A fund is ETF only when it trades on an exchange.
74
+ * listing syntax (`=F`, `=X`, `^`, the crypto venue). A fund is ETF when it
75
+ * trades on an exchange and FUND otherwise.
62
76
  */
63
77
  export function instrumentClassCode(item: {
64
78
  instrumentClass?: TickerSearchInstrumentClass;
@@ -72,8 +86,9 @@ export function instrumentClassCode(item: {
72
86
  case "equity":
73
87
  return "EQ";
74
88
  case "currency":
75
- case "crypto":
76
89
  return "CUR";
90
+ case "crypto":
91
+ return "CRYP";
77
92
  case "option":
78
93
  return "OPT";
79
94
  case "future":
@@ -81,7 +96,7 @@ export function instrumentClassCode(item: {
81
96
  case "index":
82
97
  return "IDX";
83
98
  case "fund":
84
- return isExchangeTradedType(type) ? "ETF" : null;
99
+ return isExchangeTradedType(type) ? "ETF" : "FUND";
85
100
  case "bond":
86
101
  case "other":
87
102
  return null;