gloomberb 0.16.3 → 0.16.5

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 (820) hide show
  1. package/README.md +14 -91
  2. package/package.json +7 -1
  3. package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
  4. package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
  5. package/src/account/billing.ts +57 -0
  6. package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
  7. package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
  8. package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
  9. package/src/account/session.ts +16 -0
  10. package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
  11. package/src/account/upgrade-personalization.ts +57 -0
  12. package/src/account/upgrade-tickers.ts +124 -0
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/askg.ts +43 -0
  15. package/src/api-client/auth.ts +15 -0
  16. package/src/api-client/beneficial-owners.ts +4 -0
  17. package/src/api-client/chat.ts +19 -0
  18. package/src/api-client/company-kpis.ts +14 -2
  19. package/src/api-client/data.ts +58 -18
  20. package/src/api-client/earnings.ts +6 -0
  21. package/src/api-client/futures-curve.ts +56 -0
  22. package/src/api-client/index.ts +16 -1
  23. package/src/api-client/market-discovery.ts +10 -1
  24. package/src/api-client/normalizers.ts +27 -0
  25. package/src/api-client/paths.ts +95 -23
  26. package/src/api-client/request.ts +2 -1
  27. package/src/api-client/research-activity.ts +46 -10
  28. package/src/api-client/socket.ts +39 -8
  29. package/src/api-client/types.ts +74 -2
  30. package/src/api-client/upgrade-experiment.ts +90 -0
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +26 -2
  33. package/src/app/keybindings/actions.ts +10 -0
  34. package/src/app/pane-runtime/index.tsx +8 -0
  35. package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
  36. package/src/app/pane-runtime/plugin-bindings.ts +65 -25
  37. package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
  38. package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
  39. package/src/app/runtime/desktop-deeplink.ts +5 -0
  40. package/src/app/star-prompt/model.ts +98 -0
  41. package/src/app/star-prompt/runtime.ts +41 -0
  42. package/src/app/star-prompt/status-line.tsx +190 -0
  43. package/src/app.tsx +13 -7
  44. package/src/architecture/core-builtin-allowlist.json +61 -0
  45. package/src/brokers/signed-in/adapter.ts +33 -2
  46. package/src/brokers/signed-in/client.ts +10 -0
  47. package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
  48. package/src/brokers/signed-in/sign-in.ts +62 -5
  49. package/src/capabilities/chart-series.ts +11 -1
  50. package/src/capabilities/registry.ts +8 -1
  51. package/src/capabilities/types.ts +2 -0
  52. package/src/cli/commands/crypto-hints.ts +19 -4
  53. package/src/cli/commands/fred-series.ts +61 -0
  54. package/src/cli/commands/market.ts +744 -181
  55. package/src/cli/commands/news-hints.ts +62 -0
  56. package/src/cli/commands/news-search.ts +53 -0
  57. package/src/cli/commands/options-chain.ts +172 -0
  58. package/src/cli/commands/options-leaps.ts +425 -0
  59. package/src/cli/commands/overview.ts +251 -40
  60. package/src/cli/commands/remote.ts +2 -1
  61. package/src/cli/commands/search.ts +109 -15
  62. package/src/cli/commands/system.ts +151 -24
  63. package/src/cli/commands/themes.ts +64 -0
  64. package/src/cli/commands/ticker.ts +149 -40
  65. package/src/cli/context.ts +45 -14
  66. package/src/cli/desktop-pane-shot.ts +150 -17
  67. package/src/cli/earnings-calendar.ts +71 -0
  68. package/src/cli/errors.ts +25 -2
  69. package/src/cli/freshness.ts +22 -8
  70. package/src/cli/fx-pair.ts +57 -0
  71. package/src/cli/glossary.ts +429 -0
  72. package/src/cli/help.ts +14 -1
  73. package/src/cli/history-rows.ts +48 -7
  74. package/src/cli/index-roots.ts +58 -0
  75. package/src/cli/index.ts +29 -12
  76. package/src/cli/known-gaps.ts +27 -0
  77. package/src/cli/listing-arg.ts +595 -26
  78. package/src/cli/not-a-ticker.ts +44 -0
  79. package/src/cli/options.ts +50 -6
  80. package/src/cli/pane-functions/access-gate.ts +5 -0
  81. package/src/cli/pane-functions/capabilities.ts +11 -4
  82. package/src/cli/pane-functions/catalog.ts +48 -7
  83. package/src/cli/pane-functions/data.ts +48 -13
  84. package/src/cli/pane-functions/discovery.ts +1 -0
  85. package/src/cli/pane-functions/dom.ts +41 -19
  86. package/src/cli/pane-functions/freshness.ts +531 -32
  87. package/src/cli/pane-functions/function-help.ts +77 -25
  88. package/src/cli/pane-functions/headless.ts +50 -21
  89. package/src/cli/pane-functions/index.ts +66 -10
  90. package/src/cli/pane-functions/market-session.ts +147 -0
  91. package/src/cli/pane-functions/options.ts +77 -25
  92. package/src/cli/pane-functions/report-notices.ts +81 -0
  93. package/src/cli/pane-functions/report.ts +19 -8
  94. package/src/cli/pane-functions/resolver.ts +53 -18
  95. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  96. package/src/cli/pane-functions/screenshot.ts +199 -30
  97. package/src/cli/registry.ts +2 -1
  98. package/src/cli/report-tables.ts +3 -0
  99. package/src/cli/result.ts +53 -13
  100. package/src/cli/row-window.ts +76 -0
  101. package/src/cli/scroll-truncation.ts +34 -0
  102. package/src/cli/staged-tickers.ts +52 -0
  103. package/src/cli/symbol-args.ts +9 -0
  104. package/src/cli/symbol-list.ts +172 -0
  105. package/src/cli/ticker-resolution.ts +223 -30
  106. package/src/cli/types.ts +5 -0
  107. package/src/components/chart/composite/axis-overlays.tsx +6 -2
  108. package/src/components/chart/composite/composite-chart.tsx +83 -10
  109. package/src/components/chart/composite/legend.tsx +88 -8
  110. package/src/components/chart/composite/panel-surface.tsx +44 -17
  111. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  112. package/src/components/chart/composite/rasterizer.ts +64 -4
  113. package/src/components/chart/composite/series-cues.ts +71 -0
  114. package/src/components/chart/composite/text-renderer.ts +16 -8
  115. package/src/components/chart/composite/types.ts +3 -0
  116. package/src/components/command-bar/commands/direct/index.ts +9 -1
  117. package/src/components/command-bar/commands/plugin/items.ts +3 -1
  118. package/src/components/command-bar/commands/registry.ts +7 -0
  119. package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
  120. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  121. package/src/components/command-bar/panel/index.tsx +11 -3
  122. package/src/components/command-bar/panel/runtime.ts +3 -0
  123. package/src/components/command-bar/panel/types.ts +2 -0
  124. package/src/components/command-bar/routes/root/command-items.ts +2 -0
  125. package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
  126. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  127. package/src/components/command-bar/routes/root/results.ts +40 -10
  128. package/src/components/command-bar/routes/root/runtime.ts +8 -0
  129. package/src/components/command-bar/routes/root/search-providers.ts +97 -14
  130. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  131. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  132. package/src/components/command-bar/surface/index.tsx +18 -4
  133. package/src/components/command-bar/theme-picker.tsx +48 -13
  134. package/src/components/command-bar/workflow/ops.ts +5 -3
  135. package/src/components/command-bar/workflow/tickers.ts +23 -4
  136. package/src/components/data-table/view.tsx +28 -9
  137. package/src/components/layout/detached-pane-shell.tsx +9 -0
  138. package/src/components/layout/floating-pane.tsx +9 -2
  139. package/src/components/layout/header.tsx +20 -5
  140. package/src/components/layout/market-summary.ts +23 -9
  141. package/src/components/layout/pane/content.tsx +40 -29
  142. package/src/components/layout/pane/cycle-order.ts +2 -11
  143. package/src/components/layout/pane/footer/index.tsx +6 -2
  144. package/src/components/layout/pane/footer/model.ts +35 -1
  145. package/src/components/layout/pane/header.tsx +26 -2
  146. package/src/components/layout/pane/index.tsx +12 -2
  147. package/src/components/layout/pane/sidebar.tsx +78 -10
  148. package/src/components/layout/pane/title.ts +1 -1
  149. package/src/components/layout/presentation.ts +22 -0
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/drag/index.ts +43 -9
  152. package/src/components/layout/shell/drag/live.ts +87 -6
  153. package/src/components/layout/shell/drag/runtime.ts +62 -20
  154. package/src/components/layout/shell/index.tsx +71 -12
  155. package/src/components/layout/shell/layout-state.ts +5 -11
  156. package/src/components/layout/shell/menu.ts +33 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +2 -1
  159. package/src/components/layout/shell/pane/layers.tsx +216 -28
  160. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  161. package/src/components/layout/shell/pane/new-layout.ts +116 -0
  162. package/src/components/layout/shell/shortcuts.ts +5 -2
  163. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  164. package/src/components/layout/shell/visible-layout.ts +44 -1
  165. package/src/components/layout/status-bar.tsx +4 -1
  166. package/src/components/markdown-text.tsx +69 -23
  167. package/src/components/metric-treemap/heat-surface.tsx +37 -9
  168. package/src/components/metric-treemap/heat-tiles.ts +48 -17
  169. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/index.tsx +1 -1
  171. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  172. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  173. package/src/components/onboarding/onboarding-frame.tsx +33 -10
  174. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  175. package/src/components/onboarding/onboarding-wizard.tsx +50 -41
  176. package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
  177. package/src/components/onboarding/pro-step-layout.ts +86 -0
  178. package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
  179. package/src/components/onboarding/wizard-account.ts +2 -2
  180. package/src/components/pane-template-wizard.tsx +9 -1
  181. package/src/components/price-selector-dialog.tsx +11 -2
  182. package/src/components/sign-in-gate.tsx +3 -3
  183. package/src/components/ticker/list-table-view.tsx +24 -1
  184. package/src/components/ui/action-row.tsx +2 -1
  185. package/src/components/ui/button.tsx +17 -1
  186. package/src/components/ui/choice-dialog.tsx +6 -4
  187. package/src/components/ui/confirm-dialog.tsx +28 -18
  188. package/src/components/ui/data-table/index.tsx +49 -0
  189. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  190. package/src/components/ui/data-table/types.ts +20 -1
  191. package/src/components/ui/data-table/visible-range.ts +2 -0
  192. package/src/components/ui/dialog-actions.tsx +64 -0
  193. package/src/components/ui/display.tsx +17 -3
  194. package/src/components/ui/frame.tsx +35 -2
  195. package/src/components/ui/icon.tsx +13 -2
  196. package/src/components/ui/index.ts +1 -1
  197. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  198. package/src/core/connection-health.ts +1 -1
  199. package/src/core/state/app/layout-reducer.ts +89 -3
  200. package/src/core/state/app/state.ts +8 -5
  201. package/src/core/state/app/types.ts +13 -2
  202. package/src/data/cached-query.ts +2 -0
  203. package/src/data/config/layout.ts +55 -21
  204. package/src/data/config/store/fold-panes.ts +149 -0
  205. package/src/data/config/store/migrations.ts +7 -0
  206. package/src/data/config/store/node.ts +27 -6
  207. package/src/data/config/store/normalize.ts +44 -5
  208. package/src/data/ticker-repository.ts +5 -0
  209. package/src/data/ticker-store.ts +15 -0
  210. package/src/docs/content.ts +215 -0
  211. package/src/docs/load.ts +139 -0
  212. package/src/docs/requests.ts +39 -0
  213. package/src/docs/snapshot.chunk.ts +8 -0
  214. package/src/docs/snapshot.json +7416 -0
  215. package/src/docs/topics.ts +216 -0
  216. package/src/i18n/es.ts +75 -5
  217. package/src/i18n/ja.ts +75 -5
  218. package/src/i18n/ko.ts +75 -5
  219. package/src/i18n/zh-cn.ts +75 -5
  220. package/src/i18n/zh-tw.ts +75 -5
  221. package/src/layout/desks.ts +2 -3
  222. package/src/layout/pane-layout-move.ts +264 -0
  223. package/src/layout/pane-manager/dock-tree.ts +18 -0
  224. package/src/layout/pane-manager/hidden-panes.ts +160 -0
  225. package/src/layout/pane-manager/index.ts +2 -0
  226. package/src/market-data/coordinator/chart.ts +10 -4
  227. package/src/market-data/coordinator/entries.ts +7 -1
  228. package/src/market-data/coordinator/index.ts +6 -3
  229. package/src/market-data/coordinator/quotes.ts +2 -2
  230. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  231. package/src/market-data/futures-contract.ts +151 -0
  232. package/src/market-data/hooks.tsx +10 -2
  233. package/src/market-data/market/format.ts +39 -21
  234. package/src/market-data/market/freshness.ts +193 -30
  235. package/src/market-data/market/status.ts +59 -23
  236. package/src/market-data/options-alternatives.ts +69 -0
  237. package/src/market-data/published-apac-sessions.ts +23 -1
  238. package/src/market-data/quotes/contributions.ts +22 -2
  239. package/src/market-data/quotes/metadata.ts +8 -9
  240. package/src/market-data/quotes/resolution.ts +2 -0
  241. package/src/market-data/quotes/screener-live-quotes.ts +61 -9
  242. package/src/market-data/result-types.ts +2 -0
  243. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  244. package/src/plugins/builtin/account-management/model.ts +2 -56
  245. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  246. package/src/plugins/builtin/account-management/pane.tsx +37 -8
  247. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  248. package/src/plugins/builtin/alerts/cli.ts +313 -47
  249. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  250. package/src/plugins/builtin/alerts/events.ts +23 -2
  251. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  252. package/src/plugins/builtin/alerts/history.ts +2 -0
  253. package/src/plugins/builtin/alerts/index.tsx +41 -9
  254. package/src/plugins/builtin/alerts/pane.tsx +8 -0
  255. package/src/plugins/builtin/alerts/quotes.ts +3 -0
  256. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  257. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  258. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  259. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  260. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  261. package/src/plugins/builtin/alerts/targets.ts +92 -0
  262. package/src/plugins/builtin/analytics/index.tsx +4 -2
  263. package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
  264. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  265. package/src/plugins/builtin/analytics/risk-model.ts +71 -12
  266. package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
  267. package/src/plugins/builtin/attention/index.tsx +2 -0
  268. package/src/plugins/builtin/attention/pane.tsx +3 -1
  269. package/src/plugins/builtin/attention/series.ts +26 -0
  270. package/src/plugins/builtin/awards/index.tsx +2 -0
  271. package/src/plugins/builtin/awards/pane.tsx +3 -1
  272. package/src/plugins/builtin/awards/series.ts +29 -0
  273. package/src/plugins/builtin/backtest/pane.tsx +1 -1
  274. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  275. package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
  276. package/src/plugins/builtin/broker-manager/index.tsx +7 -3
  277. package/src/plugins/builtin/broker-manager/model.ts +8 -0
  278. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
  279. package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
  280. package/src/plugins/builtin/broker-manager/table.ts +5 -0
  281. package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
  282. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  283. package/src/plugins/builtin/cds/client.ts +70 -13
  284. package/src/plugins/builtin/cds/headless.ts +116 -19
  285. package/src/plugins/builtin/cds/index.tsx +3 -1
  286. package/src/plugins/builtin/cds/model.ts +193 -31
  287. package/src/plugins/builtin/cds/pane.tsx +56 -14
  288. package/src/plugins/builtin/cds/series.ts +19 -0
  289. package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
  290. package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
  291. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
  292. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  293. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  294. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  295. package/src/plugins/builtin/chart-composer/headless.ts +8 -3
  296. package/src/plugins/builtin/chart-composer/index.tsx +9 -2
  297. package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
  298. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  299. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  300. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  301. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  302. package/src/plugins/builtin/chat/channels.ts +34 -36
  303. package/src/plugins/builtin/chat/command-bar.ts +138 -0
  304. package/src/plugins/builtin/chat/composer-commands.ts +21 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
  306. package/src/plugins/builtin/chat/content/footer.tsx +5 -3
  307. package/src/plugins/builtin/chat/content/index.tsx +21 -1
  308. package/src/plugins/builtin/chat/content/mentions.ts +2 -1
  309. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  310. package/src/plugins/builtin/chat/content/user-map.ts +3 -1
  311. package/src/plugins/builtin/chat/controller/index.ts +50 -0
  312. package/src/plugins/builtin/chat/conversations.ts +256 -0
  313. package/src/plugins/builtin/chat/discord-command.ts +91 -0
  314. package/src/plugins/builtin/chat/edit-window.ts +12 -6
  315. package/src/plugins/builtin/chat/ghost-user.ts +14 -0
  316. package/src/plugins/builtin/chat/index.tsx +40 -2
  317. package/src/plugins/builtin/chat/layout.ts +2 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
  319. package/src/plugins/builtin/chat/message/header.tsx +24 -15
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
  321. package/src/plugins/builtin/chat/message/render-state.ts +3 -0
  322. package/src/plugins/builtin/chat/pane-requests.ts +60 -0
  323. package/src/plugins/builtin/chat/pane-state.ts +32 -2
  324. package/src/plugins/builtin/chat/pane.tsx +8 -0
  325. package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
  326. package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
  327. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  328. package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
  329. package/src/plugins/builtin/cloud/askg/model.ts +156 -78
  330. package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
  331. package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
  332. package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
  333. package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
  334. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  335. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  336. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  337. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  338. package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
  339. package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
  340. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
  341. package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
  342. package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
  343. package/src/plugins/builtin/cloud/plugin.tsx +36 -1
  344. package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
  345. package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
  346. package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
  347. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
  348. package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
  349. package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
  350. package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
  351. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
  352. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
  353. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
  355. package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
  356. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/comment-letters/client.ts +1 -3
  359. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  360. package/src/plugins/builtin/company-attention/headless.ts +19 -5
  361. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  362. package/src/plugins/builtin/company-attention/model.ts +26 -7
  363. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  364. package/src/plugins/builtin/company-attention/series.ts +52 -0
  365. package/src/plugins/builtin/company-kpis/client.ts +23 -8
  366. package/src/plugins/builtin/company-kpis/headless.ts +3 -1
  367. package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
  368. package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
  369. package/src/plugins/builtin/composite-plugins.ts +116 -67
  370. package/src/plugins/builtin/cot/index.tsx +3 -1
  371. package/src/plugins/builtin/cot/model.ts +40 -11
  372. package/src/plugins/builtin/cot/series.ts +27 -0
  373. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
  374. package/src/plugins/builtin/credit-boards/index.tsx +23 -21
  375. package/src/plugins/builtin/credit-boards/model.ts +0 -1
  376. package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
  377. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  378. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
  379. package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
  380. package/src/plugins/builtin/credit-conditions/series.ts +26 -0
  381. package/src/plugins/builtin/credit-documents/headless.ts +31 -1
  382. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  383. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  384. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  385. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  386. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  387. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  388. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  389. package/src/plugins/builtin/debt-maturities/client.ts +37 -9
  390. package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
  391. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  392. package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
  393. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  394. package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
  395. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  396. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  397. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  398. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  399. package/src/plugins/builtin/docs/index.tsx +68 -0
  400. package/src/plugins/builtin/docs/pane.tsx +426 -0
  401. package/src/plugins/builtin/docs/targets.ts +72 -0
  402. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  403. package/src/plugins/builtin/doe/index.tsx +2 -0
  404. package/src/plugins/builtin/doe/series.ts +62 -0
  405. package/src/plugins/builtin/earnings/client.ts +3 -2
  406. package/src/plugins/builtin/earnings/format.ts +1 -5
  407. package/src/plugins/builtin/earnings/headless.ts +58 -6
  408. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  409. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  410. package/src/plugins/builtin/earnings/history.tsx +7 -3
  411. package/src/plugins/builtin/earnings-calls/data.ts +28 -7
  412. package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
  413. package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
  414. package/src/plugins/builtin/econ/calendar-model.ts +42 -17
  415. package/src/plugins/builtin/econ/detail-view.tsx +2 -2
  416. package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
  417. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  418. package/src/plugins/builtin/econ/index.tsx +70 -22
  419. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  420. package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
  421. package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
  422. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  423. package/src/plugins/builtin/econ-statistics/view.ts +17 -0
  424. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  425. package/src/plugins/builtin/executives/data.ts +17 -6
  426. package/src/plugins/builtin/executives/pane.tsx +16 -7
  427. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  428. package/src/plugins/builtin/exposure/pane.tsx +3 -1
  429. package/src/plugins/builtin/fear-greed/index.tsx +4 -0
  430. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  431. package/src/plugins/builtin/filing-events/pane.tsx +22 -5
  432. package/src/plugins/builtin/futures/index.tsx +43 -3
  433. package/src/plugins/builtin/futures/model.ts +1 -1
  434. package/src/plugins/builtin/futures/returns.ts +1 -1
  435. package/src/plugins/builtin/futures/series.ts +13 -0
  436. package/src/plugins/builtin/futures/table.tsx +1 -1
  437. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  438. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  439. package/src/plugins/builtin/futures-curve/headless.ts +70 -9
  440. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  441. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  442. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  443. package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
  444. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
  445. package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
  446. package/src/plugins/builtin/gpu/board.tsx +13 -10
  447. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  448. package/src/plugins/builtin/gpu/client.ts +19 -1
  449. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  450. package/src/plugins/builtin/gpu/headless.ts +64 -27
  451. package/src/plugins/builtin/gpu/history.tsx +3 -3
  452. package/src/plugins/builtin/gpu/index.tsx +2 -0
  453. package/src/plugins/builtin/gpu/model.ts +114 -20
  454. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  455. package/src/plugins/builtin/gpu/series.ts +38 -0
  456. package/src/plugins/builtin/help/function-card.tsx +25 -6
  457. package/src/plugins/builtin/help/index.tsx +18 -8
  458. package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
  459. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  460. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  461. package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
  462. package/src/plugins/builtin/holders/client.ts +22 -3
  463. package/src/plugins/builtin/holders/format.ts +18 -3
  464. package/src/plugins/builtin/holders/headless.ts +42 -134
  465. package/src/plugins/builtin/holders/pane.tsx +14 -4
  466. package/src/plugins/builtin/holders/report-header.ts +40 -5
  467. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  468. package/src/plugins/builtin/insider/client.ts +35 -20
  469. package/src/plugins/builtin/insider/headless.ts +41 -11
  470. package/src/plugins/builtin/insider/index.tsx +27 -10
  471. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  472. package/src/plugins/builtin/insider/issuer.ts +49 -0
  473. package/src/plugins/builtin/insider/model.ts +3 -0
  474. package/src/plugins/builtin/iv-history/charts.tsx +21 -7
  475. package/src/plugins/builtin/iv-history/client.ts +26 -6
  476. package/src/plugins/builtin/iv-history/format.ts +33 -2
  477. package/src/plugins/builtin/iv-history/headless.ts +27 -12
  478. package/src/plugins/builtin/iv-history/index.tsx +5 -3
  479. package/src/plugins/builtin/iv-history/model.ts +172 -20
  480. package/src/plugins/builtin/iv-history/pane.tsx +11 -3
  481. package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
  482. package/src/plugins/builtin/iv-history/series.ts +29 -0
  483. package/src/plugins/builtin/jobs/headless.ts +28 -3
  484. package/src/plugins/builtin/jobs/index.tsx +3 -1
  485. package/src/plugins/builtin/jobs/pane.tsx +1 -1
  486. package/src/plugins/builtin/jobs/series.ts +19 -0
  487. package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
  488. package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
  489. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  490. package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
  491. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  492. package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
  493. package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
  494. package/src/plugins/builtin/layout-manager/index.tsx +9 -1
  495. package/src/plugins/builtin/macro-day/client.ts +68 -3
  496. package/src/plugins/builtin/macro-day/headless.ts +18 -12
  497. package/src/plugins/builtin/macro-day/index.tsx +3 -0
  498. package/src/plugins/builtin/macro-day/model.ts +66 -15
  499. package/src/plugins/builtin/macro-day/pane.tsx +34 -20
  500. package/src/plugins/builtin/macro-day/release-table.ts +40 -0
  501. package/src/plugins/builtin/macro-day/releases.ts +62 -44
  502. package/src/plugins/builtin/market-heatmap/data.ts +25 -5
  503. package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
  504. package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
  505. package/src/plugins/builtin/market-heatmap/model.ts +102 -3
  506. package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
  507. package/src/plugins/builtin/market-movers/client.ts +7 -5
  508. package/src/plugins/builtin/market-movers/headless.ts +31 -4
  509. package/src/plugins/builtin/market-movers/index.tsx +11 -3
  510. package/src/plugins/builtin/market-movers/model.ts +101 -17
  511. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  512. package/src/plugins/builtin/market-movers/table.ts +50 -23
  513. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  514. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  515. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  516. package/src/plugins/builtin/members/headless.ts +7 -2
  517. package/src/plugins/builtin/members/model.ts +31 -3
  518. package/src/plugins/builtin/members/pane.tsx +3 -6
  519. package/src/plugins/builtin/mna/headless.ts +15 -3
  520. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  521. package/src/plugins/builtin/money-markets/series.ts +41 -0
  522. package/src/plugins/builtin/news/headless.ts +9 -2
  523. package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
  524. package/src/plugins/builtin/notes/cli.ts +12 -7
  525. package/src/plugins/builtin/openfda/client.ts +1 -1
  526. package/src/plugins/builtin/options/carry.ts +95 -0
  527. package/src/plugins/builtin/options/index.tsx +58 -5
  528. package/src/plugins/builtin/options/strike-window.ts +183 -0
  529. package/src/plugins/builtin/options/table.ts +55 -3
  530. package/src/plugins/builtin/options/types.ts +8 -1
  531. package/src/plugins/builtin/options/view.tsx +162 -13
  532. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  533. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  534. package/src/plugins/builtin/options-positioning/headless.ts +5 -2
  535. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  536. package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
  537. package/src/plugins/builtin/options-scenario/client.ts +75 -18
  538. package/src/plugins/builtin/options-scenario/headless.ts +72 -24
  539. package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
  540. package/src/plugins/builtin/options-scenario/index.tsx +9 -2
  541. package/src/plugins/builtin/options-scenario/model.ts +33 -0
  542. package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
  543. package/src/plugins/builtin/pe-band/model.ts +2 -2
  544. package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
  545. package/src/plugins/builtin/perps/client.ts +40 -6
  546. package/src/plugins/builtin/perps/equity-row.tsx +33 -8
  547. package/src/plugins/builtin/perps/freshness.ts +66 -0
  548. package/src/plugins/builtin/perps/headless.ts +45 -30
  549. package/src/plugins/builtin/perps/index.tsx +18 -1
  550. package/src/plugins/builtin/perps/model.ts +32 -6
  551. package/src/plugins/builtin/perps/pane.tsx +76 -20
  552. package/src/plugins/builtin/perps/series.ts +76 -0
  553. package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
  554. package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
  555. package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
  556. package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
  557. package/src/plugins/builtin/plugin-module.ts +90 -4
  558. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  559. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
  560. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  561. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
  562. package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
  563. package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
  564. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
  565. package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
  566. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  567. package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
  568. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  569. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  570. package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
  571. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
  572. package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
  573. package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
  574. package/src/plugins/builtin/power/client.ts +16 -0
  575. package/src/plugins/builtin/power/evidence.ts +6 -2
  576. package/src/plugins/builtin/power/headless.ts +71 -7
  577. package/src/plugins/builtin/power/index.tsx +4 -1
  578. package/src/plugins/builtin/power/model.ts +72 -1
  579. package/src/plugins/builtin/power/pane.tsx +32 -9
  580. package/src/plugins/builtin/rate-path/headless.ts +11 -3
  581. package/src/plugins/builtin/realized-vol/headless.ts +8 -0
  582. package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
  583. package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
  584. package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
  585. package/src/plugins/builtin/research/event-model.ts +68 -24
  586. package/src/plugins/builtin/research/events-headless.ts +2 -1
  587. package/src/plugins/builtin/research/headless.ts +2 -1
  588. package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
  589. package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
  590. package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
  591. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
  592. package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
  593. package/src/plugins/builtin/risk-factors/data.ts +23 -9
  594. package/src/plugins/builtin/risk-factors/headless.ts +5 -2
  595. package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
  596. package/src/plugins/builtin/seasonality/client.ts +15 -7
  597. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  598. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  599. package/src/plugins/builtin/seasonality/model.ts +119 -0
  600. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  601. package/src/plugins/builtin/sec/index.tsx +5 -5
  602. package/src/plugins/builtin/sectors/client.ts +10 -2
  603. package/src/plugins/builtin/sectors/headless.ts +35 -6
  604. package/src/plugins/builtin/sectors/index.tsx +18 -1
  605. package/src/plugins/builtin/sectors/sector-model.ts +150 -41
  606. package/src/plugins/builtin/series-inventory.ts +91 -0
  607. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  608. package/src/plugins/builtin/shared/command-tab.ts +69 -0
  609. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  610. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  611. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  612. package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
  613. package/src/plugins/builtin/shared/members-menu.tsx +4 -4
  614. package/src/plugins/builtin/shared/open-description.ts +29 -0
  615. package/src/plugins/builtin/shared/report-freshness.ts +59 -2
  616. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  617. package/src/plugins/builtin/shared/ticker-request.ts +25 -1
  618. package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
  619. package/src/plugins/builtin/shared/volatility/options.ts +1 -46
  620. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  621. package/src/plugins/builtin/short-interest/index.tsx +21 -4
  622. package/src/plugins/builtin/short-interest/series.ts +36 -0
  623. package/src/plugins/builtin/short-interest/surface.tsx +4 -4
  624. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  625. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  626. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  627. package/src/plugins/builtin/short-volume/index.tsx +3 -10
  628. package/src/plugins/builtin/short-volume/series.ts +23 -0
  629. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  630. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  631. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  632. package/src/plugins/builtin/supply-chain/model.ts +1 -1
  633. package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
  634. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  635. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  636. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  637. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  638. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  639. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  640. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  641. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
  643. package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
  644. package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
  645. package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
  646. package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
  647. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
  648. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
  649. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
  650. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
  651. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  652. package/src/plugins/builtin/time-sales/headless.ts +1 -0
  653. package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
  654. package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
  655. package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
  656. package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
  657. package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
  658. package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
  659. package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
  660. package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
  661. package/src/plugins/builtin/vol-surface/client.ts +6 -2
  662. package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
  663. package/src/plugins/builtin/vol-surface/headless.ts +125 -20
  664. package/src/plugins/builtin/vol-surface/model.ts +23 -11
  665. package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
  666. package/src/plugins/builtin/vol-surface/tables.ts +124 -0
  667. package/src/plugins/builtin/volatility/index.tsx +2 -0
  668. package/src/plugins/builtin/volatility/series.ts +84 -0
  669. package/src/plugins/builtin/world-indices/client.ts +22 -4
  670. package/src/plugins/builtin/world-indices/headless.ts +54 -27
  671. package/src/plugins/builtin/world-indices/model.ts +4 -2
  672. package/src/plugins/builtin/world-indices/table.tsx +13 -2
  673. package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
  674. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  675. package/src/plugins/builtin/world-venue-map/index.ts +3 -2
  676. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
  677. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  678. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  679. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  680. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  681. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  682. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  683. package/src/plugins/builtin-editorial.ts +126 -0
  684. package/src/plugins/catalog-backend.ts +16 -9
  685. package/src/plugins/catalog-browser.ts +129 -64
  686. package/src/plugins/catalog-manifest.ts +73 -40
  687. package/src/plugins/catalog-ui.ts +26 -6
  688. package/src/plugins/extracted-plugins.ts +7 -1
  689. package/src/plugins/ownership.ts +150 -7
  690. package/src/plugins/plugin-functions.ts +54 -0
  691. package/src/plugins/plugin-off.ts +36 -0
  692. package/src/plugins/registry/host-actions.ts +16 -0
  693. package/src/plugins/registry/index.ts +173 -28
  694. package/src/plugins/registry/plugin-state.ts +25 -1
  695. package/src/plugins/runtime/context.tsx +29 -0
  696. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  697. package/src/portfolio/position-value.ts +40 -0
  698. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  699. package/src/public/time-series.ts +17 -0
  700. package/src/react/auto-refresh.ts +13 -3
  701. package/src/react/input.ts +48 -1
  702. package/src/remote/app-host.tsx +25 -4
  703. package/src/remote/confirm-change.tsx +85 -0
  704. package/src/remote/controller-utils.ts +8 -1
  705. package/src/remote/controller.ts +126 -59
  706. package/src/remote/matching.ts +69 -0
  707. package/src/remote/pane-screenshot.ts +47 -0
  708. package/src/remote/schema.ts +63 -1
  709. package/src/remote/semantic-tree.tsx +14 -0
  710. package/src/remote/types.ts +32 -0
  711. package/src/remote/watchlist.ts +306 -0
  712. package/src/renderers/browser/main.tsx +3 -2
  713. package/src/renderers/cloudflare/worker.ts +1 -1
  714. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  715. package/src/renderers/dom/data-table/index.tsx +33 -6
  716. package/src/renderers/dom/data-table/row.tsx +27 -1
  717. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  718. package/src/renderers/dom/desktop/controls.tsx +30 -23
  719. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  720. package/src/renderers/dom/desktop/icons.tsx +21 -0
  721. package/src/renderers/dom/desktop/query-bar.tsx +59 -32
  722. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  723. package/src/renderers/dom/host/box.tsx +4 -1
  724. package/src/renderers/dom/host/chart-surface.tsx +6 -2
  725. package/src/renderers/dom/host/drag-shield.ts +17 -6
  726. package/src/renderers/dom/host/live-frame.ts +14 -2
  727. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  728. package/src/renderers/dom/host/size-observer.ts +26 -0
  729. package/src/renderers/dom/host/surface-3d.tsx +7 -2
  730. package/src/renderers/dom/host/text.tsx +1 -1
  731. package/src/renderers/dom/input-host.tsx +6 -1
  732. package/src/renderers/dom/styles.css +74 -0
  733. package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
  734. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
  735. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
  736. package/src/renderers/electrobun/shared/protocol.ts +2 -0
  737. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
  738. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
  739. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  740. package/src/renderers/electrobun/view/main.tsx +6 -1
  741. package/src/renderers/opentui/input-host.tsx +6 -1
  742. package/src/renderers/opentui/start.tsx +9 -0
  743. package/src/series/capability.ts +75 -0
  744. package/src/series/csv.ts +160 -0
  745. package/src/series/files.ts +107 -0
  746. package/src/series/registry.ts +198 -0
  747. package/src/series/resolve.ts +107 -0
  748. package/src/series/standalone.ts +48 -0
  749. package/src/series/types.ts +145 -0
  750. package/src/series/validate.ts +171 -0
  751. package/src/shares/portable-layout.ts +16 -6
  752. package/src/sources/gloomberb-cloud/index.ts +26 -17
  753. package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
  754. package/src/sources/history-result.ts +1 -0
  755. package/src/sources/listing-symbols.ts +14 -5
  756. package/src/sources/provider-errors.ts +88 -3
  757. package/src/sources/provider-router/batches.ts +4 -1
  758. package/src/sources/provider-router/cache.ts +4 -2
  759. package/src/sources/provider-router/cached-routes.ts +9 -5
  760. package/src/sources/provider-router/financial-routes.ts +12 -5
  761. package/src/sources/provider-router/financials.ts +55 -15
  762. package/src/sources/provider-router/history.ts +68 -34
  763. package/src/sources/provider-router/index.ts +1 -1
  764. package/src/sources/provider-router/primary.ts +23 -5
  765. package/src/sources/provider-router/search.ts +1 -0
  766. package/src/sources/sec-edgar.ts +68 -8
  767. package/src/sync/core-contributors.ts +5 -3
  768. package/src/test-support/cli-context.ts +2 -1
  769. package/src/test-support/data-provider.ts +34 -0
  770. package/src/test-support/shell-pane-keys.tsx +1 -0
  771. package/src/theme/series-colors.ts +46 -0
  772. package/src/theme/themes.ts +149 -0
  773. package/src/tickers/company-name.ts +75 -0
  774. package/src/tickers/instrument-kind.ts +25 -0
  775. package/src/tickers/open-target.ts +3 -2
  776. package/src/tickers/search/index.ts +67 -9
  777. package/src/tickers/search/ranking.ts +78 -18
  778. package/src/tickers/search/types.ts +10 -2
  779. package/src/tickers/starter-symbols.ts +8 -0
  780. package/src/tickers/us-listing.ts +34 -0
  781. package/src/time-series/hooks.ts +9 -0
  782. package/src/time-series/resolve.ts +96 -30
  783. package/src/time-series/types.ts +4 -2
  784. package/src/time-series/use-chart-resolution.ts +32 -0
  785. package/src/types/config.ts +67 -1
  786. package/src/types/data-provider.ts +5 -0
  787. package/src/types/financials.ts +52 -1
  788. package/src/types/headless.ts +72 -0
  789. package/src/types/instrument.ts +8 -0
  790. package/src/types/plugin.ts +68 -3
  791. package/src/types/price-history.ts +7 -0
  792. package/src/types/ticker.ts +14 -0
  793. package/src/ui/host.tsx +26 -4
  794. package/src/ui/index.tsx +2 -0
  795. package/src/ui/live-resize.ts +81 -0
  796. package/src/ui/live-stretch.ts +121 -0
  797. package/src/ui/measured-cells.ts +58 -0
  798. package/src/ui/pane-fill.ts +11 -0
  799. package/src/utils/basis-points.ts +17 -0
  800. package/src/utils/cli-output.ts +21 -2
  801. package/src/utils/concurrency.ts +25 -0
  802. package/src/utils/crypto-pair.ts +20 -0
  803. package/src/utils/currency-pair.ts +19 -0
  804. package/src/utils/decimal-comma.ts +19 -0
  805. package/src/utils/dom-screenshot-css.ts +265 -0
  806. package/src/utils/dom-screenshot-rasters.ts +276 -0
  807. package/src/utils/dom-screenshot.ts +437 -52
  808. package/src/utils/exchange-rate-snapshot.ts +6 -2
  809. package/src/utils/exchanges.ts +120 -1
  810. package/src/utils/format.ts +17 -3
  811. package/src/utils/fundamentals.ts +66 -0
  812. package/src/utils/futures-generic.ts +6 -12
  813. package/src/utils/fx-market-hours.ts +44 -0
  814. package/src/utils/option-expiry.ts +126 -0
  815. package/src/utils/price-history.ts +130 -40
  816. package/src/utils/rpc-timeout-error.ts +6 -2
  817. package/src/utils/sec-eps-basis.ts +178 -36
  818. package/src/utils/sec.ts +98 -40
  819. package/src/utils/throttled-fetch.ts +51 -22
  820. package/src/utils/utc-time.ts +51 -4
@@ -3,7 +3,12 @@ import type { MarketHeatmapAsset, MarketHeatmapUniverseId } from "../../../api-c
3
3
  import { useAppSelector, usePaneStateValue } from "../../../state/app/context";
4
4
  import type { ColumnConfig } from "../../../types/config";
5
5
  import type { TickerFinancials } from "../../../types/financials";
6
- import { getSessionMoveDisplay, type ExtendedSession } from "../../../market-data/market/status";
6
+ import {
7
+ getRegularSessionMoveDisplay,
8
+ getTradedSessionMoveDisplay,
9
+ type ActiveQuoteDisplay,
10
+ type ExtendedSession,
11
+ } from "../../../market-data/market/status";
7
12
  import type { TickerRecord } from "../../../types/ticker";
8
13
  import { getSortValue, type ColumnContext } from "../portfolio-list/metrics";
9
14
 
@@ -195,6 +200,7 @@ export function buildPortfolioHeatmapAssets({
195
200
  currency,
196
201
  exchangeRates,
197
202
  sizeBy = "sqrt-market-cap",
203
+ regularSession = false,
198
204
  }: {
199
205
  tickers: readonly TickerRecord[];
200
206
  financials: ReadonlyMap<string, TickerFinancials>;
@@ -204,6 +210,8 @@ export function buildPortfolioHeatmapAssets({
204
210
  currency: string;
205
211
  exchangeRates: Map<string, number>;
206
212
  sizeBy?: HeatmapSizeBy;
213
+ /** Color by the regular session alone, never an extended print (`getRegularSessionMoveDisplay`). */
214
+ regularSession?: boolean;
207
215
  }): { assets: HeatmapBoardAsset[]; omitted: number } {
208
216
  const context: ColumnContext = {
209
217
  activeTab: kind === "portfolio" ? collectionId : undefined,
@@ -217,7 +225,9 @@ export function buildPortfolioHeatmapAssets({
217
225
  const snapshot = financials.get(symbol);
218
226
  const quote = snapshot?.quote;
219
227
  // Colored like the market boards: an open extended session's move, else the regular session's.
220
- const display = getSessionMoveDisplay(quote);
228
+ const display: (ActiveQuoteDisplay & { session?: ExtendedSession }) | null = regularSession
229
+ ? getRegularSessionMoveDisplay(quote)
230
+ : getTradedSessionMoveDisplay(quote);
221
231
  const price = display != null && Number.isFinite(display.price) ? display.price : null;
222
232
  const size = positiveNumber(getSortValue(sizeColumn, ticker, snapshot, context));
223
233
  const hasChange = display?.changePercent != null && Number.isFinite(display.changePercent);
@@ -5,18 +5,19 @@ import type {
5
5
  CloudSessionMoversSide,
6
6
  } from "../../../api-client/market-movers";
7
7
  import type { DataProvider } from "../../../types/data-provider";
8
- import { CATEGORY_MAP, screenerQuoteFromQuote, type ScreenerTabId } from "./model";
8
+ import { CATEGORY_MAP, moverRegularSession, screenerQuoteFromQuote, type MoverQuote, type ScreenerTabId } from "./model";
9
9
  import {
10
10
  fetchPreferredMarketMovers,
11
11
  fetchTrending,
12
12
  type MarketMoversResult,
13
13
  type PreferredMoversOptions,
14
- type ScreenerQuote,
15
14
  type TrendingSymbol,
16
15
  } from "./screener";
17
16
 
18
17
  export interface MarketMoverTabResult extends MarketMoversResult {
19
18
  tab: ScreenerTabId;
19
+ /** In the list's order; Last and Chg% the regular session, as `ticker` reads them. */
20
+ quotes: MoverQuote[];
20
21
  }
21
22
 
22
23
  export interface MarketMoverTabDependencies {
@@ -36,9 +37,9 @@ const defaultDependencies: MarketMoverTabDependencies = {
36
37
  async function hydrateTrending(
37
38
  trending: readonly TrendingSymbol[],
38
39
  provider: DataProvider | null,
39
- ): Promise<ScreenerQuote[]> {
40
+ ): Promise<MoverQuote[]> {
40
41
  const symbols = trending.slice(0, 25).map(({ symbol }) => symbol);
41
- const bySymbol = new Map<string, ScreenerQuote>();
42
+ const bySymbol = new Map<string, MoverQuote>();
42
43
  if (!provider) return [];
43
44
  if (provider.getQuotesBatch) {
44
45
  const results = await provider.getQuotesBatch(
@@ -79,7 +80,8 @@ export async function loadMarketMoverTab(
79
80
  };
80
81
  }
81
82
  const result = await dependencies.fetchPreferred(CATEGORY_MAP[tab], 25, options);
82
- return { ...result, tab };
83
+ // Ranked by the live print first, so reading each row's regular session keeps its place.
84
+ return { ...result, quotes: result.quotes.map(moverRegularSession), tab };
83
85
  }
84
86
 
85
87
  /** The server refused the list for the account's plan. */
@@ -10,14 +10,18 @@ import type {
10
10
  CloudSessionMoversSide,
11
11
  } from "../../../api-client/market-movers";
12
12
  import { loadMarketMoverTab, loadSessionMovers, type MarketMoverTabResult } from "./client";
13
- import { createRows, fiftyTwoWeekPositionPercent, formatMoverPrice, moverReferencePrice, type MarketMoverRow, type ScreenerTabId, type TabId } from "./model";
13
+ import { createRows, fiftyTwoWeekPositionPercent, formatMoverPrice, moverExtendedSessions, moverReferencePrice, type MarketMoverRow, type ScreenerTabId, type TabId } from "./model";
14
+ import { EXTENDED_SESSION_LABELS, type ExtendedSession } from "../../../market-data/market/status";
15
+ import type { HeadlessPaneColumn } from "../../../types/headless";
14
16
  import { isSessionTab, resolveSide } from "./session";
15
17
 
16
- const COLUMNS = [
18
+ const rowPrice = (value: unknown, row: Record<string, unknown>) => formatMoverPrice(typeof value === "number" ? value : null, typeof row.currency === "string" ? row.currency : "", moverReferencePrice(row as unknown as MarketMoverRow));
19
+
20
+ const COLUMNS: HeadlessPaneColumn[] = [
17
21
  { key: "rank", header: "Rank", align: "right" as const },
18
22
  { key: "symbol", header: "Symbol" },
19
23
  { key: "name", header: "Name" },
20
- { key: "price", header: "Last", align: "right" as const, format: (value: unknown, row: Record<string, unknown>) => formatMoverPrice(typeof value === "number" ? value : null, typeof row.currency === "string" ? row.currency : "", moverReferencePrice(row as unknown as MarketMoverRow)) },
24
+ { key: "price", header: "Last", align: "right" as const, format: rowPrice },
21
25
  { key: "changePercent", header: "Change %", align: "right" as const, format: (value: unknown) => value == null ? "—" : formatPercentRaw(Number(value)) },
22
26
  { key: "volume", header: "Volume", align: "right" as const, format: (value: unknown) => value == null ? "—" : formatCompact(Number(value), { fixedDecimals: true }) },
23
27
  { key: "volumeRatio", header: "Vol / Avg", align: "right" as const, format: (value: unknown) => value == null ? "—" : formatNumber(Number(value), 1) },
@@ -30,6 +34,19 @@ const percent = (value: unknown) => value == null ? "—" : formatPercentRaw(Num
30
34
  const ratio = (value: unknown) => value == null ? "—" : `${formatNumber(Number(value), 1)}x`;
31
35
  const compact = (value: unknown) => value == null ? "—" : formatCompact(Number(value), { fixedDecimals: true });
32
36
  const CATALYST_LABEL: Record<string, string> = { halt: "Halt", filing: "8-K", news: "News" };
37
+
38
+ /** The pre-market or after-hours print and its move from the regular close, for the rows that have one. */
39
+ function extendedColumn(session: ExtendedSession): HeadlessPaneColumn {
40
+ return {
41
+ key: "extendedPrice",
42
+ header: EXTENDED_SESSION_LABELS[session],
43
+ align: "right",
44
+ format: (value, row) => row.extendedSession === session && typeof value === "number"
45
+ ? `${rowPrice(value, row)} ${percent(row.extendedChangePercent)}`
46
+ : "—",
47
+ };
48
+ }
49
+
33
50
  const SESSION_VOLUME: Record<CloudSessionMoversCategory, string> = {
34
51
  premarket: "Pre-market volume",
35
52
  afterhours: "After-hours volume",
@@ -131,8 +148,15 @@ export function createMarketMoversHeadless(
131
148
  };
132
149
  }
133
150
  const result = await dependencies.load(args, tab, ctx.marketData);
134
- const rows = createRows(result.quotes).map((row) => ({
151
+ const ranked = createRows(result.quotes);
152
+ // Last and Change % are the regular session; an extended print is a column of its own.
153
+ const extendedSessions = moverExtendedSessions(ranked);
154
+ const rows = ranked.map(({ extended, ...row }) => ({
135
155
  ...row,
156
+ extendedSession: extended?.session ?? null,
157
+ extendedPrice: extended?.price ?? null,
158
+ extendedChange: extended?.change ?? null,
159
+ extendedChangePercent: extended?.changePercent ?? null,
136
160
  rangePositionPercent: fiftyTwoWeekPositionPercent(
137
161
  row.price,
138
162
  row.fiftyTwoWeekLow,
@@ -140,6 +164,9 @@ export function createMarketMoversHeadless(
140
164
  ),
141
165
  }));
142
166
  return {
167
+ ...(extendedSessions.length > 0
168
+ ? { columns: [...COLUMNS.slice(0, 5), ...extendedSessions.map(extendedColumn), ...COLUMNS.slice(5)] }
169
+ : {}),
143
170
  rows,
144
171
  metadata: { list: tab, source: result.source, stale: result.stale },
145
172
  };
@@ -25,6 +25,7 @@ import {
25
25
  INDEX_SHORT,
26
26
  TABS,
27
27
  createRows,
28
+ moverExtendedSessions,
28
29
  overlayMarketMoverQuotes,
29
30
  resolveSummarySymbols,
30
31
  resolveTabs,
@@ -33,6 +34,7 @@ import {
33
34
  type MarketMoverColumn,
34
35
  type MarketMoverRow,
35
36
  type MarketMoverSortPreference,
37
+ type MoverQuote,
36
38
  type ScreenerTabId,
37
39
  type TabId,
38
40
  } from "./model";
@@ -42,6 +44,7 @@ import { isSessionTab, resolveActiveTab, usSessionAt, type UsSession } from "./s
42
44
  import { SessionMoversBody } from "./session-body";
43
45
  import { marketMoversHeadless } from "./headless";
44
46
  import { buildMarketMoverColumns, renderMarketMoverCell } from "./table";
47
+ import type { ExtendedSession } from "../../../market-data/market/status";
45
48
  import {
46
49
  LIVE_STREAMING_QUICK_SETTING,
47
50
  useLiveStreamingSetting,
@@ -56,7 +59,7 @@ import {
56
59
  /** Stable identity: a fresh literal here would reload the board every render. */
57
60
  const NO_SAVED_SELECTION: string[] = [];
58
61
  const SESSION_CHECK_MS = 30_000;
59
- const NO_QUOTES: ScreenerQuote[] = [];
62
+ const NO_QUOTES: MoverQuote[] = [];
60
63
  const moverKey = (row: Pick<ScreenerQuote, "symbol" | "exchange">) => publicTickerKey(row.symbol, row.exchange);
61
64
 
62
65
  /** What is trading in New York, re-read every half minute so the pane follows 04:00, 09:30 and 16:00. */
@@ -152,7 +155,7 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
152
155
  }) {
153
156
  const dataProvider = useAssetData();
154
157
  const { pinTicker } = usePluginTickerActions();
155
- const [quotes, setQuotes] = useState<ScreenerQuote[]>([]);
158
+ const [quotes, setQuotes] = useState<MoverQuote[]>([]);
156
159
  const [loadedTab, setLoadedTab] = useState<TabId | null>(null);
157
160
  const visibleQuotes = loadedTab === activeTab ? quotes : NO_QUOTES;
158
161
  // The first load starts before the effect runs; an empty board is not "no data".
@@ -188,8 +191,13 @@ function ScreenerMoversBody({ activeTab, focused, width, summaryQuotes, liveStre
188
191
  }),
189
192
  [freshnessNow, liveQuoteEntries, quoteTargets, subscriptionStartedAt],
190
193
  );
191
- const columns = useMemo(() => buildMarketMoverColumns(width), [width]);
192
194
  const rankedRows = useMemo(() => createRows(resolvedQuotes), [resolvedQuotes]);
195
+ // A pre-market or after-hours column only while a row has such a print.
196
+ const extendedSessionsKey = moverExtendedSessions(rankedRows).join(",");
197
+ const columns = useMemo(
198
+ () => buildMarketMoverColumns(width, extendedSessionsKey ? extendedSessionsKey.split(",") as ExtendedSession[] : []),
199
+ [extendedSessionsKey, width],
200
+ );
193
201
  const rows = useMemo(() => sortRows(rankedRows, sortPreference), [rankedRows, sortPreference]);
194
202
  const selectedIdx = selectedSymbol
195
203
  ? rows.findIndex((row) => moverKey(row) === selectedSymbol)
@@ -1,5 +1,13 @@
1
1
  import { resolveCurrencyUnit } from "../../../utils/currency-units";
2
2
  import { overlayScreenerQuoteEntries } from "../../../market-data/quotes/screener-live-quotes";
3
+ import {
4
+ getExtendedSessionDisplay,
5
+ getRegularSessionDisplay,
6
+ type ExtendedSession,
7
+ type ExtendedSessionDisplay,
8
+ } from "../../../market-data/market/status";
9
+ import { buildQuoteKey, resolveEntryData } from "../../../market-data/selectors";
10
+ import { isFiniteNumber } from "../../../utils/guards";
3
11
  import type { Quote } from "../../../types/financials";
4
12
  import type { CloudSessionMoversCategory } from "../../../api-client/market-movers";
5
13
  import type { QueryEntry } from "../../../market-data/result-types";
@@ -37,12 +45,20 @@ type MarketMoverColumnId =
37
45
  | "name"
38
46
  | "price"
39
47
  | "changePercent"
48
+ | "preMarket"
49
+ | "afterHours"
40
50
  | "volume"
41
51
  | "volumeRatio"
42
52
  | "range"
43
53
  | "marketCap";
44
54
  export type MarketMoverColumn = DataTableColumn & { id: MarketMoverColumnId };
45
- export type MarketMoverRow = ScreenerQuote & { rank: number };
55
+ /**
56
+ * A list row. Price and change are the regular session's, as `ticker` reads
57
+ * them; a row whose quote has a pre-market or after-hours print carries it in
58
+ * `extended`, measured from that session's close.
59
+ */
60
+ export type MoverQuote = ScreenerQuote & { extended?: ExtendedSessionDisplay | null };
61
+ export type MarketMoverRow = MoverQuote & { rank: number };
46
62
 
47
63
  export interface MarketMoverSortPreference {
48
64
  columnId: MarketMoverColumnId | null;
@@ -96,6 +112,9 @@ function getSortValue(
96
112
  return row.price;
97
113
  case "changePercent":
98
114
  return row.changePercent;
115
+ case "preMarket":
116
+ case "afterHours":
117
+ return moverExtendedMove(row, columnId === "preMarket" ? "PRE" : "POST");
99
118
  case "volume":
100
119
  return row.volume;
101
120
  case "volumeRatio":
@@ -123,7 +142,17 @@ export function sortRows(
123
142
  /** A row is rebuilt only when its quote or rank moved, so unchanged rows skip the render. */
124
143
  const moverRows = new WeakMap<ScreenerQuote, MarketMoverRow>();
125
144
 
126
- export function createRows(quotes: ScreenerQuote[]): MarketMoverRow[] {
145
+ /** The extended print's move from the close, when the row has one for `session`. */
146
+ export function moverExtendedMove(row: MoverQuote, session: ExtendedSession): number | null {
147
+ return row.extended?.session === session && isFiniteNumber(row.extended.changePercent) ? row.extended.changePercent : null;
148
+ }
149
+
150
+ /** The extended sessions some row has a print for, in the order their columns go. */
151
+ export function moverExtendedSessions(rows: readonly MoverQuote[]): ExtendedSession[] {
152
+ return (["PRE", "POST"] as const).filter((session) => rows.some((row) => row.extended?.session === session));
153
+ }
154
+
155
+ export function createRows(quotes: readonly MoverQuote[]): MarketMoverRow[] {
127
156
  return quotes.map((quote, index) => {
128
157
  const cached = moverRows.get(quote);
129
158
  if (cached?.rank === index + 1) return cached;
@@ -137,26 +166,66 @@ export function createRows(quotes: ScreenerQuote[]): MarketMoverRow[] {
137
166
  });
138
167
  }
139
168
 
140
- export function summaryQuoteFromQuote(
141
- symbol: string,
142
- quote: { name?: string; price: number; change: number; changePercent: number },
143
- ): MarketSummaryQuote {
169
+ /** An index in the summary strip, at its regular session's level and move. */
170
+ export function summaryQuoteFromQuote(symbol: string, quote: Quote): MarketSummaryQuote {
171
+ const headline = getRegularSessionDisplay(quote)!;
144
172
  return {
145
173
  symbol,
146
174
  name: quote.name ?? symbol,
147
- price: quote.price,
148
- change: quote.change,
149
- changePercent: quote.changePercent,
175
+ price: headline.price,
176
+ change: headline.change ?? Number.NaN,
177
+ changePercent: headline.changePercent ?? Number.NaN,
178
+ };
179
+ }
180
+
181
+ /** The extended print beside a quote's regular session, or null; a non-finite price is none. */
182
+ function moverExtended(quote: Quote): ExtendedSessionDisplay | null {
183
+ const extended = getExtendedSessionDisplay(quote);
184
+ return extended && isFiniteNumber(extended.price) ? extended : null;
185
+ }
186
+
187
+ /**
188
+ * A listed row as `ticker` reads its quote: Last and Chg% are the regular
189
+ * session's close and move, and a pre-market or after-hours print is its
190
+ * `extended`, measured from that close. The list ranked it by its live print
191
+ * first, so its place stays. A row without its quote's sessions (an older
192
+ * server) reads as it came.
193
+ */
194
+ export function moverRegularSession({ sessions, ...row }: ScreenerQuote): MoverQuote {
195
+ if (!sessions || row.price == null) return row;
196
+ const quote: Quote = {
197
+ symbol: row.symbol,
198
+ price: row.price,
199
+ change: row.change ?? Number.NaN,
200
+ changePercent: row.changePercent ?? Number.NaN,
201
+ previousClose: row.previousClose,
202
+ currency: row.currency,
203
+ lastUpdated: row.lastUpdated ?? Number.NaN,
204
+ listingExchangeName: row.exchange || undefined,
205
+ ...sessions,
206
+ };
207
+ const headline = getRegularSessionDisplay(quote)!;
208
+ return {
209
+ ...row,
210
+ price: screenerNumber(headline.price),
211
+ change: screenerNumber(headline.change),
212
+ changePercent: screenerNumber(headline.changePercent),
213
+ extended: moverExtended(quote),
150
214
  };
151
215
  }
152
216
 
153
- export function screenerQuoteFromQuote(symbol: string, quote: { name?: string; price?: number; change?: number; changePercent?: number; volume?: number; currency?: string; exchangeName?: string; listingExchangeName?: string; lastUpdated?: number; previousClose?: number }): ScreenerQuote {
217
+ /**
218
+ * A trending row from its quote: Last and Chg% are the regular session, as
219
+ * `ticker` reads it, and a pre-market or after-hours print rides beside them.
220
+ */
221
+ export function screenerQuoteFromQuote(symbol: string, quote: Quote): MoverQuote {
222
+ const headline = getRegularSessionDisplay(quote)!;
154
223
  return {
155
224
  symbol,
156
225
  name: quote.name ?? symbol,
157
- price: screenerNumber(quote.price),
158
- change: screenerNumber(quote.change),
159
- changePercent: screenerNumber(quote.changePercent),
226
+ price: screenerNumber(headline.price),
227
+ change: screenerNumber(headline.change),
228
+ changePercent: screenerNumber(headline.changePercent),
160
229
  volume: screenerVolume(quote.volume),
161
230
  avgVolume: null,
162
231
  volumeRatio: null,
@@ -169,6 +238,7 @@ export function screenerQuoteFromQuote(symbol: string, quote: { name?: string; p
169
238
  exchange: quote.listingExchangeName ?? quote.exchangeName ?? "",
170
239
  lastUpdated: quote.lastUpdated,
171
240
  previousClose: screenerNumber(quote.previousClose) ?? undefined,
241
+ extended: moverExtended(quote),
172
242
  };
173
243
  }
174
244
 
@@ -198,21 +268,35 @@ export function formatMoverPrice(price: number | null, currency: string, referen
198
268
  }
199
269
 
200
270
  /** Keyed by the overlaid row, which the shared overlay keeps while its quote holds. */
201
- const convertedOverlays = new WeakMap<ScreenerQuote, ScreenerQuote>();
271
+ const convertedOverlays = new WeakMap<ScreenerQuote, MoverQuote>();
202
272
 
203
- /** Range endpoints and the previous close belong to the original screener price denomination. */
273
+ /**
274
+ * Live quotes on the list's rows, which keep the list's order. Price and
275
+ * change are the regular session's, as `ticker` reads them, so after the
276
+ * close they hold at it and a pre-market or after-hours print is the row's
277
+ * `extended`. Range endpoints and the previous close belong to the original
278
+ * screener price denomination.
279
+ */
204
280
  export function overlayMarketMoverQuotes(
205
- rows: readonly ScreenerQuote[],
281
+ rows: readonly MoverQuote[],
206
282
  entries: ReadonlyMap<string, QueryEntry<Quote>>,
207
- ): ScreenerQuote[] {
283
+ ): MoverQuote[] {
208
284
  return overlayScreenerQuoteEntries(rows, entries).map((row, index) => {
209
285
  const original = rows[index]!;
210
286
  if (row === original) return row;
211
287
  const cached = convertedOverlays.get(row);
212
288
  if (cached) return cached;
213
289
  const convert = (value: number | undefined) => convertScreenerPriceUnit(value, original.currency, row.currency);
290
+ const quote = resolveEntryData(entries.get(buildQuoteKey({ symbol: row.symbol, exchange: row.exchange })));
291
+ const headline = quote ? getRegularSessionDisplay(quote) : null;
214
292
  const converted = {
215
293
  ...row,
294
+ ...(quote && headline ? {
295
+ price: headline.price,
296
+ change: isFiniteNumber(headline.change) ? headline.change : null,
297
+ changePercent: isFiniteNumber(headline.changePercent) ? headline.changePercent : null,
298
+ extended: moverExtended(quote),
299
+ } : {}),
216
300
  fiftyTwoWeekLow: convert(original.fiftyTwoWeekLow),
217
301
  fiftyTwoWeekHigh: convert(original.fiftyTwoWeekHigh),
218
302
  dayLow: convert(original.dayLow),
@@ -8,7 +8,9 @@ import type {
8
8
  CloudMarketScreenerCategory,
9
9
  CloudMarketScreenerItem,
10
10
  CloudMarketScreenerPayload,
11
+ CloudMoverSessionFields,
11
12
  } from "../../../api-client/types";
13
+ import type { MarketState } from "../../../types/financials";
12
14
  import { hasProAccess } from "../../../api-client/plan-access";
13
15
 
14
16
  const CACHE_KIND = "market-screener";
@@ -184,6 +186,32 @@ export function convertScreenerPriceUnit(value: number | undefined, from: string
184
186
  ? value / source.divisor * target.divisor : undefined;
185
187
  }
186
188
 
189
+ const MARKET_STATES = new Set<string>(["PRE", "REGULAR", "POST", "PREPRE", "POSTPOST", "CLOSED"] satisfies MarketState[]);
190
+ const SESSION_NUMBERS = [
191
+ "regularClose", "regularChange", "regularChangePercent",
192
+ "preMarketPrice", "preMarketChange", "preMarketChangePercent",
193
+ "postMarketPrice", "postMarketChange", "postMarketChangePercent",
194
+ ] as const;
195
+ const isSessionDate = (value: unknown): value is string => typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value);
196
+
197
+ /**
198
+ * A row's quote sessions as the server sends them beside its live print, or
199
+ * undefined when it sends none (an older server), so the row reads as it came.
200
+ */
201
+ function parseScreenerSessions(row: Record<string, unknown>): CloudMoverSessionFields | undefined {
202
+ if (typeof row.marketState !== "string" || !MARKET_STATES.has(row.marketState)) return undefined;
203
+ const sessions: CloudMoverSessionFields = { marketState: row.marketState as MarketState };
204
+ if (isSessionDate(row.changeSessionDate)) sessions.changeSessionDate = row.changeSessionDate;
205
+ for (const key of SESSION_NUMBERS) {
206
+ const value = screenerNumber(row[key]);
207
+ if (value != null) sessions[key] = value;
208
+ }
209
+ if (sessions.regularClose != null && isSessionDate(row.regularCloseSessionDate)) {
210
+ sessions.regularCloseSessionDate = row.regularCloseSessionDate;
211
+ }
212
+ return sessions;
213
+ }
214
+
187
215
  /** Validate numeric fields at the API boundary so absent values stay unavailable. */
188
216
  export function parseScreenerResponse(data: unknown): ScreenerQuote[] {
189
217
  if (!data || typeof data !== "object" || !("quotes" in data) || !Array.isArray(data.quotes)) {
@@ -202,6 +230,7 @@ export function parseScreenerResponse(data: unknown): ScreenerQuote[] {
202
230
  dayHigh: screenerNumber(q.dayHigh) ?? undefined, dayLow: screenerNumber(q.dayLow) ?? undefined,
203
231
  previousClose: screenerNumber(q.previousClose) ?? undefined, exchange: typeof q.exchange === "string" ? q.exchange : "",
204
232
  lastUpdated: typeof q.lastUpdated === "number" && Number.isFinite(q.lastUpdated) && q.lastUpdated > 0 ? q.lastUpdated : undefined,
233
+ sessions: parseScreenerSessions(q),
205
234
  }];
206
235
  });
207
236
  }
@@ -274,6 +303,8 @@ function mergeCloudScreenerItem(
274
303
  dayLow: screenerNumber(item.dayLow) ?? metadataPrice(metadata?.dayLow),
275
304
  exchange: item.exchange || metadata?.exchange || "",
276
305
  lastUpdated: item.lastUpdated,
306
+ previousClose: screenerNumber(item.previousClose) ?? undefined,
307
+ sessions: parseScreenerSessions(item as unknown as Record<string, unknown>),
277
308
  };
278
309
  }
279
310
 
@@ -1,9 +1,11 @@
1
1
  import type { DataTableCell } from "../../../components";
2
+ import { getTableWidth } from "../../../components/ui/table-layout";
2
3
  import { TextAttributes } from "../../../ui";
3
4
  import { colors, priceColor } from "../../../theme/colors";
4
5
  import { formatCompact, formatPercentRaw } from "../../../utils/format";
6
+ import { marketStateLabel, type ExtendedSession } from "../../../market-data/market/status";
5
7
  import type { MarketMoverColumn, MarketMoverRow } from "./model";
6
- import { fiftyTwoWeekPositionPercent, formatMoverPrice, moverReferencePrice } from "./model";
8
+ import { fiftyTwoWeekPositionPercent, formatMoverPrice, moverExtendedMove, moverReferencePrice } from "./model";
7
9
 
8
10
  export function formatVolRatio(ratio: number | null): string {
9
11
  if (ratio == null || !Number.isFinite(ratio) || ratio < 0) return "—";
@@ -22,30 +24,45 @@ function fiftyTwoWeekPosition(price: number | null, low: number | undefined, hig
22
24
  return pct == null ? "—" : `${Math.round(pct)}%`;
23
25
  }
24
26
 
25
- export function buildMarketMoverColumns(width: number): MarketMoverColumn[] {
26
- const rankWidth = 3;
27
- const tickerWidth = 8;
28
- const priceWidth = 11;
29
- const chgWidth = 9;
30
- const volWidth = 8;
31
- const volRatioWidth = 6;
32
- const rangeWidth = 6;
33
- const mcapWidth = 8;
34
- const columnCount = 9;
35
- const fixedWidth = rankWidth + tickerWidth + priceWidth + chgWidth + volWidth + volRatioWidth + rangeWidth + mcapWidth;
36
- const nameWidth = Math.max(6, width - 2 - columnCount - fixedWidth);
27
+ const EXTENDED_COLUMN_WIDTH = 9;
28
+ /** With an extended column, a narrow pane drops MCAP, then 52W%, before the name gets narrower than this. */
29
+ const EXTENDED_MIN_NAME_WIDTH = 12;
37
30
 
38
- return [
39
- { id: "rank", label: "#", width: rankWidth, align: "left" },
40
- { id: "symbol", label: "TICKER", width: tickerWidth, align: "left" },
41
- { id: "name", label: "NAME", width: nameWidth, align: "left" },
42
- { id: "price", label: "LAST", width: priceWidth, align: "right" },
43
- { id: "changePercent", label: "CHG%", width: chgWidth, align: "right" },
44
- { id: "volume", label: "VOL", width: volWidth, align: "right" },
45
- { id: "volumeRatio", label: "V/AVG", width: volRatioWidth, align: "right" },
46
- { id: "range", label: "52W%", width: rangeWidth, align: "right" },
47
- { id: "marketCap", label: "MCAP", width: mcapWidth, align: "right" },
31
+ /**
32
+ * The list's columns at `width`. A pre-market or after-hours column follows
33
+ * CHG% for each session in `extendedSessions`; to make room for it a narrow
34
+ * pane gives up MCAP, then 52W%, before it cuts the names short.
35
+ */
36
+ export function buildMarketMoverColumns(width: number, extendedSessions: readonly ExtendedSession[] = []): MarketMoverColumn[] {
37
+ const lead: MarketMoverColumn[] = [
38
+ { id: "rank", label: "#", width: 3, align: "left" },
39
+ { id: "symbol", label: "TICKER", width: 8, align: "left" },
48
40
  ];
41
+ const quote: MarketMoverColumn[] = [
42
+ { id: "price", label: "LAST", width: 11, align: "right" },
43
+ { id: "changePercent", label: "CHG%", width: 9, align: "right" },
44
+ ...extendedSessions.map((session): MarketMoverColumn => ({
45
+ id: session === "PRE" ? "preMarket" : "afterHours",
46
+ // Named for the session it trades in, as the header labels it.
47
+ label: marketStateLabel(session),
48
+ width: EXTENDED_COLUMN_WIDTH,
49
+ align: "right",
50
+ })),
51
+ ];
52
+ const trailing: MarketMoverColumn[] = [
53
+ { id: "volume", label: "VOL", width: 8, align: "right" },
54
+ { id: "volumeRatio", label: "V/AVG", width: 6, align: "right" },
55
+ { id: "range", label: "52W%", width: 6, align: "right" },
56
+ { id: "marketCap", label: "MCAP", width: 8, align: "right" },
57
+ ];
58
+ // Measured the way the table draws them (a header and its sort mark widen a
59
+ // column, gaps between them); the name adds its own width and a gap.
60
+ const nameRoom = () => width - getTableWidth([...lead, ...quote, ...trailing]) - 1;
61
+ for (const id of ["marketCap", "range"] as const) {
62
+ if (extendedSessions.length === 0 || nameRoom() >= EXTENDED_MIN_NAME_WIDTH) break;
63
+ trailing.splice(trailing.findIndex((column) => column.id === id), 1);
64
+ }
65
+ return [...lead, { id: "name", label: "NAME", width: Math.max(6, nameRoom()), align: "left" }, ...quote, ...trailing];
49
66
  }
50
67
 
51
68
  export function renderMarketMoverCell(
@@ -71,6 +88,16 @@ export function renderMarketMoverCell(
71
88
  value: row.changePercent,
72
89
  color: priceColor(row.changePercent ?? 0),
73
90
  };
91
+ case "preMarket":
92
+ case "afterHours": {
93
+ // The extended print's move from the close in LAST.
94
+ const move = moverExtendedMove(row, column.id === "preMarket" ? "PRE" : "POST");
95
+ return {
96
+ text: formatPercentRaw(move ?? undefined),
97
+ value: move,
98
+ color: move == null ? colors.textDim : priceColor(move),
99
+ };
100
+ }
74
101
  case "volume":
75
102
  return { text: formatCompact(row.volume ?? undefined, { fixedDecimals: true }), value: row.volume, color: colors.textDim };
76
103
  case "volumeRatio":