gloomberb 0.18.2 → 0.18.4

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 (954) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/patches/electrobun@1.18.1.patch +106 -5
  6. package/src/account/checkout-handoff.tsx +225 -0
  7. package/src/account/device-signin-dialog.tsx +2 -2
  8. package/src/account/device-signin.ts +2 -2
  9. package/src/account/upgrade-dialog.tsx +1 -1
  10. package/src/api-client/askg.ts +2 -2
  11. package/src/api-client/auth.ts +2 -2
  12. package/src/api-client/central-bank-rates.ts +6 -0
  13. package/src/api-client/collections.ts +5 -1
  14. package/src/api-client/cot.ts +2 -0
  15. package/src/api-client/crypto-etf-flows.ts +37 -0
  16. package/src/api-client/crypto-markets.ts +60 -0
  17. package/src/api-client/data.ts +99 -5
  18. package/src/api-client/doe.ts +15 -0
  19. package/src/api-client/equity-screener.ts +28 -0
  20. package/src/api-client/exchange-announcements.ts +38 -0
  21. package/src/api-client/fund-facts.ts +39 -0
  22. package/src/api-client/futures-curve.ts +9 -1
  23. package/src/api-client/hiring.ts +301 -0
  24. package/src/api-client/index.ts +24 -5
  25. package/src/api-client/market-discovery.ts +14 -0
  26. package/src/api-client/members.ts +6 -0
  27. package/src/api-client/mna.ts +6 -0
  28. package/src/api-client/paths.ts +18 -1
  29. package/src/api-client/request.ts +26 -7
  30. package/src/api-client/short-side-publications.ts +37 -0
  31. package/src/api-client/socket.ts +64 -4
  32. package/src/api-client/swap-curve.ts +35 -0
  33. package/src/api-client/telemetry.ts +17 -0
  34. package/src/api-client/themes.ts +7 -1
  35. package/src/api-client/types.ts +90 -2
  36. package/src/app/global-shortcuts.ts +1 -16
  37. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  38. package/src/app/runtime/desktop-deeplink.ts +5 -5
  39. package/src/app/runtime/plugin-bindings.ts +2 -2
  40. package/src/app/runtime/startup.ts +13 -0
  41. package/src/app/runtime/update.ts +28 -8
  42. package/src/app/star-prompt/status-line.tsx +2 -2
  43. package/src/architecture/core-builtin-allowlist.json +5 -2
  44. package/src/architecture/pane-tabs-allowlist.json +65 -0
  45. package/src/architecture/ui-literals-allowlist.json +3 -3
  46. package/src/architecture/ui-tokens-allowlist.json +1 -1
  47. package/src/brokers/broker-portfolio-sync.ts +37 -0
  48. package/src/brokers/directory.ts +11 -0
  49. package/src/brokers/logos.ts +3 -1
  50. package/src/brokers/signed-in/adapter.ts +304 -26
  51. package/src/brokers/signed-in/client.ts +14 -2
  52. package/src/brokers/signed-in/connect.ts +10 -2
  53. package/src/brokers/sync-broker-instance.ts +9 -1
  54. package/src/capabilities/chart-series.ts +22 -6
  55. package/src/cli/bank-section.ts +1 -1
  56. package/src/cli/base-converter.ts +23 -14
  57. package/src/cli/central-bank-events.ts +1 -1
  58. package/src/cli/command-options.ts +59 -4
  59. package/src/cli/commands/api.ts +9 -6
  60. package/src/cli/commands/broker.ts +2 -2
  61. package/src/cli/commands/command-utils.ts +2 -2
  62. package/src/cli/commands/crypto-hints.ts +7 -20
  63. package/src/cli/commands/fred-series.ts +4 -2
  64. package/src/cli/commands/keybindings.ts +2 -2
  65. package/src/cli/commands/market.ts +1189 -296
  66. package/src/cli/commands/news-hints.ts +2 -2
  67. package/src/cli/commands/news-search.ts +59 -6
  68. package/src/cli/commands/options-leaps.ts +41 -26
  69. package/src/cli/commands/overview.ts +121 -48
  70. package/src/cli/commands/plugins.ts +9 -9
  71. package/src/cli/commands/remote.ts +13 -10
  72. package/src/cli/commands/search.ts +64 -44
  73. package/src/cli/commands/system.ts +27 -19
  74. package/src/cli/commands/themes.ts +1 -1
  75. package/src/cli/commands/ticker.ts +272 -70
  76. package/src/cli/context.ts +3 -2
  77. package/src/cli/desktop-pane-shot-view.ts +2 -2
  78. package/src/cli/desktop-pane-shot.ts +1 -1
  79. package/src/cli/earnings-calendar.ts +4 -4
  80. package/src/cli/entry.ts +18 -1
  81. package/src/cli/errors.ts +20 -2
  82. package/src/cli/exit-codes.ts +1 -1
  83. package/src/cli/export-source.ts +10 -4
  84. package/src/cli/freshness.ts +2 -8
  85. package/src/cli/fx-forward.ts +130 -0
  86. package/src/cli/fx-pair.ts +10 -9
  87. package/src/cli/glossary.ts +64 -20
  88. package/src/cli/help.ts +20 -14
  89. package/src/cli/history-export.ts +126 -0
  90. package/src/cli/history-rows.ts +196 -43
  91. package/src/cli/index-roots.ts +5 -45
  92. package/src/cli/index.ts +32 -18
  93. package/src/cli/issuer-membership.ts +103 -0
  94. package/src/cli/known-gaps.ts +118 -25
  95. package/src/cli/listing-arg.ts +315 -43
  96. package/src/cli/name-entries.ts +73 -22
  97. package/src/cli/native-smoke.ts +2 -0
  98. package/src/cli/not-a-ticker.ts +19 -9
  99. package/src/cli/opentui-libc.ts +5 -0
  100. package/src/cli/options.ts +12 -0
  101. package/src/cli/pane-functions/capabilities.ts +77 -20
  102. package/src/cli/pane-functions/catalog.ts +40 -23
  103. package/src/cli/pane-functions/discovery.ts +1 -1
  104. package/src/cli/pane-functions/dom.ts +12 -8
  105. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  106. package/src/cli/pane-functions/freshness.ts +174 -23
  107. package/src/cli/pane-functions/function-help.ts +66 -27
  108. package/src/cli/pane-functions/headless.ts +48 -16
  109. package/src/cli/pane-functions/index.ts +82 -21
  110. package/src/cli/pane-functions/options.ts +22 -2
  111. package/src/cli/pane-functions/report-notices.ts +12 -4
  112. package/src/cli/pane-functions/report.ts +5 -5
  113. package/src/cli/pane-functions/resolver.ts +65 -14
  114. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  115. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  116. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  117. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  118. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  119. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  120. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  121. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  122. package/src/cli/pane-functions/shot-options.ts +8 -3
  123. package/src/cli/peso-dollar-rates.ts +79 -0
  124. package/src/cli/quote-answer.ts +38 -3
  125. package/src/cli/report-tables.ts +190 -27
  126. package/src/cli/restore-plugins.ts +29 -14
  127. package/src/cli/result.ts +122 -25
  128. package/src/cli/series-search.ts +5 -5
  129. package/src/cli/statement-filings.ts +19 -0
  130. package/src/cli/suffixed-listing-rows.ts +49 -0
  131. package/src/cli/symbol-args.ts +50 -15
  132. package/src/cli/symbol-cells.ts +120 -0
  133. package/src/cli/symbol-list.ts +226 -60
  134. package/src/cli/symbol-rows.ts +131 -25
  135. package/src/cli/ticker-resolution.ts +108 -11
  136. package/src/cli/treasury-yields.ts +5 -5
  137. package/src/cli/types.ts +2 -0
  138. package/src/cli/uncovered-instrument.ts +3 -3
  139. package/src/cli/unknown-command.ts +6 -6
  140. package/src/components/chart/composite/chart-layout.ts +131 -0
  141. package/src/components/chart/composite/composite-chart.tsx +387 -21
  142. package/src/components/chart/composite/drawing-store.ts +26 -6
  143. package/src/components/chart/composite/interactions.ts +9 -3
  144. package/src/components/chart/composite/legend.tsx +75 -3
  145. package/src/components/chart/composite/levels.ts +5 -0
  146. package/src/components/chart/composite/panel-gestures.ts +41 -0
  147. package/src/components/chart/composite/panel-labels.ts +2 -1
  148. package/src/components/chart/composite/panel-surface.tsx +316 -11
  149. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  150. package/src/components/chart/composite/rasterizer.ts +44 -19
  151. package/src/components/chart/composite/scene.ts +16 -4
  152. package/src/components/chart/composite/text-renderer.ts +48 -21
  153. package/src/components/chart/composite/toolbar.tsx +52 -5
  154. package/src/components/chart/composite/types.ts +19 -0
  155. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  156. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  157. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  158. package/src/components/chart/composite/value-scale.ts +149 -0
  159. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  160. package/src/components/chart/core/pointer.ts +2 -0
  161. package/src/components/chart-table/index.ts +2 -0
  162. package/src/components/chart-table/read.tsx +74 -0
  163. package/src/components/command-bar/commands/collection-list.ts +41 -19
  164. package/src/components/command-bar/commands/collection.ts +9 -3
  165. package/src/components/command-bar/commands/direct/index.ts +1 -1
  166. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  167. package/src/components/command-bar/pane-templates/items.ts +59 -6
  168. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  169. package/src/components/command-bar/routes/root/command-items.ts +32 -6
  170. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  171. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  172. package/src/components/command-bar/routes/root/results.ts +18 -4
  173. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  174. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  175. package/src/components/command-bar/routes/root/selection.ts +6 -1
  176. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  177. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  178. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  179. package/src/components/command-bar/selection-runtime.ts +50 -10
  180. package/src/components/command-bar/surface/index.tsx +24 -2
  181. package/src/components/command-bar/view-model.ts +7 -0
  182. package/src/components/command-bar/workflow/broker.ts +2 -2
  183. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  184. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  185. package/src/components/command-bar/workflow/fields.ts +8 -2
  186. package/src/components/command-bar/workflow/ops.ts +18 -4
  187. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  188. package/src/components/command-bar/workflow/submit.ts +3 -2
  189. package/src/components/command-bar/workflow/tickers.ts +5 -1
  190. package/src/components/company-logo.tsx +39 -0
  191. package/src/components/data-table/sections.ts +4 -2
  192. package/src/components/data-table/view.tsx +23 -3
  193. package/src/components/form-modal/confirm.tsx +2 -1
  194. package/src/components/form-modal/request.ts +5 -0
  195. package/src/components/form-modal/routes.ts +4 -1
  196. package/src/components/index.ts +13 -6
  197. package/src/components/layout/detached-pane-shell.tsx +1 -0
  198. package/src/components/layout/floating-pane.tsx +1 -0
  199. package/src/components/layout/header.tsx +234 -60
  200. package/src/components/layout/market-summary.ts +9 -6
  201. package/src/components/layout/pane/capture-status.ts +1 -1
  202. package/src/components/layout/pane/footer/model.ts +11 -5
  203. package/src/components/layout/pane/header.tsx +10 -3
  204. package/src/components/layout/pane/index.tsx +1 -0
  205. package/src/components/layout/pane/pane-tabs.tsx +9 -1
  206. package/src/components/layout/shell/chrome.ts +19 -6
  207. package/src/components/layout/shell/index.tsx +2 -1
  208. package/src/components/layout/shell/pane/layers.tsx +19 -1
  209. package/src/components/layout/status-bar.tsx +2 -2
  210. package/src/components/market-board/index.tsx +11 -3
  211. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  212. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  213. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  214. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  215. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  216. package/src/components/pane-settings-dialog/value.ts +8 -1
  217. package/src/components/pane-settings-dialog.tsx +44 -13
  218. package/src/components/sign-in-code-panel.tsx +27 -19
  219. package/src/components/ui/column-grid.tsx +48 -4
  220. package/src/components/ui/country-flag-art.tsx +180 -0
  221. package/src/components/ui/country-flag.tsx +118 -12
  222. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  223. package/src/components/ui/data-table/opentui/model.ts +109 -2
  224. package/src/components/ui/data-table/types.ts +1 -1
  225. package/src/components/ui/display.tsx +5 -1
  226. package/src/components/ui/index.ts +3 -1
  227. package/src/components/ui/logo-mark.tsx +11 -2
  228. package/src/components/ui/query-bar.tsx +1 -1
  229. package/src/components/ui/row-notes.ts +79 -0
  230. package/src/components/ui/stat-grid.tsx +28 -3
  231. package/src/components/ui/status.tsx +3 -1
  232. package/src/core/app-services.ts +4 -0
  233. package/src/core/state/app/layout.ts +4 -4
  234. package/src/data/cached-query.ts +8 -1
  235. package/src/data/config/chart-settings.ts +3 -3
  236. package/src/data/config/home.ts +10 -2
  237. package/src/data/config/layout.ts +4 -1
  238. package/src/data/config/store/node.ts +4 -0
  239. package/src/data/config/store/normalize.ts +13 -3
  240. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  241. package/src/data/json-storage.ts +2 -0
  242. package/src/data/saved-copies.ts +84 -0
  243. package/src/docs/snapshot.json +65 -32
  244. package/src/i18n/es.ts +51 -12
  245. package/src/i18n/ja.ts +51 -12
  246. package/src/i18n/ko.ts +51 -12
  247. package/src/i18n/zh-cn.ts +51 -12
  248. package/src/i18n/zh-tw.ts +51 -12
  249. package/src/layout/desks.ts +1 -1
  250. package/src/layout/launch-layout.ts +1 -1
  251. package/src/layout/pane-manager/floating-actions.ts +5 -3
  252. package/src/layout/pane-manager/floating.ts +43 -1
  253. package/src/layout/pane-manager/index.ts +2 -0
  254. package/src/layout/selected-ticker.ts +74 -0
  255. package/src/market-data/depositary-pair.ts +251 -0
  256. package/src/market-data/futures-board.ts +1 -1
  257. package/src/market-data/futures-contract.ts +124 -40
  258. package/src/market-data/fx-closes.ts +17 -2
  259. package/src/market-data/hooks.tsx +19 -11
  260. package/src/market-data/market/change-basis.ts +49 -7
  261. package/src/market-data/market/freshness.ts +34 -5
  262. package/src/market-data/market/period-return.ts +163 -0
  263. package/src/market-data/market/trading-sessions.ts +13 -0
  264. package/src/market-data/market/year-to-date.ts +8 -13
  265. package/src/market-data/performance.ts +20 -14
  266. package/src/market-data/perpetual-premium.ts +32 -0
  267. package/src/market-data/published-apac-sessions.ts +2 -1
  268. package/src/market-data/published-futures-sessions.ts +69 -0
  269. package/src/market-data/quotes/contributions.ts +5 -1
  270. package/src/market-data/quotes/freshness.ts +42 -0
  271. package/src/market-data/quotes/intraday-bar.ts +37 -0
  272. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  273. package/src/market-data/quotes/resolution.ts +4 -2
  274. package/src/market-data/tax-equivalent.ts +1 -1
  275. package/src/market-data/ticker-price-returns.ts +3 -1
  276. package/src/news/aggregator.ts +5 -1
  277. package/src/news/news-model.ts +4 -0
  278. package/src/news/types.ts +11 -0
  279. package/src/notifications/app-notifier.ts +1 -1
  280. package/src/plugins/auto-update.ts +2 -2
  281. package/src/plugins/builtin/account-management/index.tsx +1 -0
  282. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  283. package/src/plugins/builtin/alerts/alert-engine.ts +30 -18
  284. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  285. package/src/plugins/builtin/alerts/cli.ts +485 -76
  286. package/src/plugins/builtin/alerts/command.ts +5 -10
  287. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  288. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  289. package/src/plugins/builtin/alerts/events.ts +108 -5
  290. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  291. package/src/plugins/builtin/alerts/format.ts +2 -1
  292. package/src/plugins/builtin/alerts/headless.ts +100 -39
  293. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  294. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  295. package/src/plugins/builtin/alerts/index.tsx +45 -18
  296. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  297. package/src/plugins/builtin/alerts/levels.ts +3 -3
  298. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  299. package/src/plugins/builtin/alerts/price.ts +35 -0
  300. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  301. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  302. package/src/plugins/builtin/alerts/research-rules.ts +77 -3
  303. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  304. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  305. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  306. package/src/plugins/builtin/alerts/storage.ts +13 -10
  307. package/src/plugins/builtin/alerts/targets.ts +12 -3
  308. package/src/plugins/builtin/analytics/index.tsx +8 -2
  309. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  310. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  311. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  312. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  313. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  314. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  315. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  316. package/src/plugins/builtin/analytics/risk-pane.tsx +107 -43
  317. package/src/plugins/builtin/attention/pane.tsx +22 -16
  318. package/src/plugins/builtin/awards/headless.ts +7 -3
  319. package/src/plugins/builtin/awards/model.ts +18 -0
  320. package/src/plugins/builtin/awards/pane.tsx +12 -9
  321. package/src/plugins/builtin/backtest/export.ts +1 -1
  322. package/src/plugins/builtin/backtest/headless.ts +3 -3
  323. package/src/plugins/builtin/backtest/rules.ts +41 -5
  324. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  325. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  326. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  327. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  328. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  329. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  330. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  331. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  332. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  333. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  334. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  335. package/src/plugins/builtin/broker-trading/dock.tsx +24 -4
  336. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  337. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  338. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  339. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  340. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  341. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  342. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  343. package/src/plugins/builtin/broker-trading/pane.tsx +115 -26
  344. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  345. package/src/plugins/builtin/broker-trading/ticket.tsx +122 -36
  346. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  347. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  348. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  349. package/src/plugins/builtin/buildout/pane/index.tsx +34 -18
  350. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  351. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  352. package/src/plugins/builtin/catalysts/client.ts +2 -2
  353. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  354. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  355. package/src/plugins/builtin/catalysts/model.ts +49 -4
  356. package/src/plugins/builtin/catalysts/pane.tsx +9 -11
  357. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  358. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  359. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  360. package/src/plugins/builtin/changelog/index.tsx +1 -0
  361. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  362. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  363. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  364. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  365. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  366. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  367. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  368. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  369. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  370. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  371. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  372. package/src/plugins/builtin/chart-composer/pane.tsx +128 -28
  373. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  374. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  375. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  376. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  377. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  378. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  379. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  380. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  381. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  382. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  383. package/src/plugins/builtin/chat/people.ts +1 -1
  384. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  385. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  386. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  387. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  388. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  389. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  390. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  391. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  392. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  393. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  394. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  395. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  396. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  397. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  398. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  399. package/src/plugins/builtin/commodity-balances/pane.tsx +14 -8
  400. package/src/plugins/builtin/company-attention/app-rank.tsx +11 -10
  401. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  402. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  403. package/src/plugins/builtin/company-attention/client.ts +117 -1
  404. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  405. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  406. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  407. package/src/plugins/builtin/company-attention/model.ts +33 -7
  408. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  409. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  410. package/src/plugins/builtin/company-attention/pane.tsx +89 -31
  411. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  412. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  413. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  414. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  415. package/src/plugins/builtin/company-kpis/pane.tsx +5 -4
  416. package/src/plugins/builtin/composite-plugins.ts +2 -1
  417. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  418. package/src/plugins/builtin/connections/index.ts +1 -0
  419. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  420. package/src/plugins/builtin/correlation/headless.ts +7 -4
  421. package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
  422. package/src/plugins/builtin/correlation/settings.ts +1 -0
  423. package/src/plugins/builtin/cot/headless.ts +28 -6
  424. package/src/plugins/builtin/cot/model.ts +12 -0
  425. package/src/plugins/builtin/cot/pane.tsx +7 -5
  426. package/src/plugins/builtin/cpi/headless.ts +5 -1
  427. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  428. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  429. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  430. package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
  431. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  432. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  433. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  434. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  435. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  436. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  437. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  438. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  439. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  440. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  441. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  442. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  443. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  444. package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
  445. package/src/plugins/builtin/debug/index.tsx +1 -0
  446. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  447. package/src/plugins/builtin/docs/index.tsx +1 -1
  448. package/src/plugins/builtin/docs/pane.tsx +2 -2
  449. package/src/plugins/builtin/docs/targets.ts +1 -1
  450. package/src/plugins/builtin/doe/client.ts +5 -1
  451. package/src/plugins/builtin/doe/headless.ts +12 -6
  452. package/src/plugins/builtin/doe/model.ts +43 -6
  453. package/src/plugins/builtin/doe/pane.tsx +19 -12
  454. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  455. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  456. package/src/plugins/builtin/earnings/board.tsx +253 -50
  457. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  458. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  459. package/src/plugins/builtin/earnings/client.ts +4 -3
  460. package/src/plugins/builtin/earnings/headless.ts +53 -15
  461. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  462. package/src/plugins/builtin/earnings/index.tsx +15 -22
  463. package/src/plugins/builtin/earnings/model.ts +17 -12
  464. package/src/plugins/builtin/earnings/scope.ts +89 -0
  465. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  466. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  467. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  468. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  469. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  470. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  471. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  472. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  473. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  474. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  475. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  476. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  477. package/src/plugins/builtin/econ/index.tsx +112 -25
  478. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  479. package/src/plugins/builtin/econ/types.ts +32 -1
  480. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  481. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  482. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  483. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  484. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  485. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  486. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  487. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  488. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  489. package/src/plugins/builtin/equity-screener/headless.ts +77 -5
  490. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  491. package/src/plugins/builtin/equity-screener/model.ts +34 -0
  492. package/src/plugins/builtin/equity-screener/pane.tsx +148 -106
  493. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  494. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  495. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  496. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  497. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  498. package/src/plugins/builtin/exposure/headless.ts +51 -6
  499. package/src/plugins/builtin/exposure/index.tsx +28 -2
  500. package/src/plugins/builtin/exposure/model.ts +7 -0
  501. package/src/plugins/builtin/exposure/pane.tsx +16 -10
  502. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  503. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  504. package/src/plugins/builtin/futures/model.ts +10 -9
  505. package/src/plugins/builtin/futures/returns.ts +8 -36
  506. package/src/plugins/builtin/futures/table.tsx +1 -1
  507. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  508. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  509. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  510. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  511. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  512. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  513. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  514. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  515. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  516. package/src/plugins/builtin/gpu/board.tsx +4 -1
  517. package/src/plugins/builtin/gpu/changes.tsx +10 -10
  518. package/src/plugins/builtin/gpu/equities.tsx +4 -1
  519. package/src/plugins/builtin/gpu/headless.ts +9 -4
  520. package/src/plugins/builtin/gpu/history.tsx +4 -2
  521. package/src/plugins/builtin/gpu/pane.tsx +5 -3
  522. package/src/plugins/builtin/help/index.tsx +13 -3
  523. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  524. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  525. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  526. package/src/plugins/builtin/holders/client.ts +15 -2
  527. package/src/plugins/builtin/holders/format.ts +28 -17
  528. package/src/plugins/builtin/holders/headless.ts +48 -8
  529. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  530. package/src/plugins/builtin/holders/pane.tsx +79 -15
  531. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  532. package/src/plugins/builtin/holders/table-model.ts +2 -1
  533. package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
  534. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  535. package/src/plugins/builtin/insider/base-values.ts +11 -7
  536. package/src/plugins/builtin/insider/client.ts +3 -0
  537. package/src/plugins/builtin/insider/headless.ts +20 -7
  538. package/src/plugins/builtin/insider/index.tsx +17 -8
  539. package/src/plugins/builtin/insider/issuer.ts +34 -4
  540. package/src/plugins/builtin/insider/signals-client.ts +3 -3
  541. package/src/plugins/builtin/insider/signals.tsx +1 -1
  542. package/src/plugins/builtin/insider/table-model.ts +35 -13
  543. package/src/plugins/builtin/insider/table.tsx +5 -2
  544. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  545. package/src/plugins/builtin/iv-history/client.ts +20 -0
  546. package/src/plugins/builtin/iv-history/events.ts +145 -0
  547. package/src/plugins/builtin/iv-history/format.ts +3 -0
  548. package/src/plugins/builtin/iv-history/headless.ts +91 -7
  549. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  550. package/src/plugins/builtin/iv-history/model.ts +13 -4
  551. package/src/plugins/builtin/iv-history/series.ts +3 -1
  552. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  553. package/src/plugins/builtin/jobs/model.ts +4 -15
  554. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  555. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  556. package/src/plugins/builtin/jodi/pane.tsx +14 -8
  557. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  558. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  559. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  560. package/src/plugins/builtin/macro-day/model.ts +29 -8
  561. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  562. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  563. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  564. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  565. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  566. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  567. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  568. package/src/plugins/builtin/market-movers/client.ts +36 -21
  569. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  570. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  571. package/src/plugins/builtin/market-movers/screener.ts +33 -11
  572. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  573. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  574. package/src/plugins/builtin/market-movers/table.ts +4 -1
  575. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  576. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  577. package/src/plugins/builtin/members/headless.ts +6 -5
  578. package/src/plugins/builtin/members/pane.tsx +11 -4
  579. package/src/plugins/builtin/mna/client.ts +1 -0
  580. package/src/plugins/builtin/mna/detail.tsx +20 -32
  581. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  582. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  583. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  584. package/src/plugins/builtin/mna/headless.ts +6 -13
  585. package/src/plugins/builtin/mna/model.ts +93 -15
  586. package/src/plugins/builtin/mna/pane.tsx +5 -4
  587. package/src/plugins/builtin/news/headless.ts +12 -6
  588. package/src/plugins/builtin/news/index.tsx +10 -1
  589. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  590. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  591. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  592. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  593. package/src/plugins/builtin/notes/cli.ts +50 -15
  594. package/src/plugins/builtin/notes/export.ts +17 -6
  595. package/src/plugins/builtin/notes/files.ts +16 -5
  596. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  597. package/src/plugins/builtin/options/carry.ts +2 -2
  598. package/src/plugins/builtin/options/enrichment-model.ts +10 -9
  599. package/src/plugins/builtin/options/index.tsx +1 -1
  600. package/src/plugins/builtin/options/model-spot.ts +70 -4
  601. package/src/plugins/builtin/options/view.tsx +51 -23
  602. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  603. package/src/plugins/builtin/options-calculator/pane.tsx +3 -2
  604. package/src/plugins/builtin/options-positioning/headless.ts +11 -3
  605. package/src/plugins/builtin/options-positioning/model.ts +24 -0
  606. package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
  607. package/src/plugins/builtin/options-scenario/client.ts +142 -29
  608. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  609. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  610. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  611. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  612. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  613. package/src/plugins/builtin/options-scenario/headless.ts +49 -21
  614. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  615. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  616. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  617. package/src/plugins/builtin/options-scenario/pane.tsx +22 -10
  618. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  619. package/src/plugins/builtin/perps/freshness.ts +8 -5
  620. package/src/plugins/builtin/perps/headless.ts +3 -1
  621. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  622. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  623. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  624. package/src/plugins/builtin/perps/pane.tsx +36 -17
  625. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  626. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  627. package/src/plugins/builtin/plugin-marketplace/pane.tsx +145 -60
  628. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +78 -27
  629. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  630. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  631. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  632. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  633. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  634. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  635. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  636. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  637. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  638. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  639. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  640. package/src/plugins/builtin/power/client.ts +6 -3
  641. package/src/plugins/builtin/power/evidence.ts +22 -7
  642. package/src/plugins/builtin/power/gas.tsx +5 -1
  643. package/src/plugins/builtin/power/pane.tsx +44 -32
  644. package/src/plugins/builtin/power/prices.tsx +10 -3
  645. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  646. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  647. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  648. package/src/plugins/builtin/research/event-model.ts +3 -1
  649. package/src/plugins/builtin/research/event-sources.ts +12 -4
  650. package/src/plugins/builtin/research/index.tsx +2 -1
  651. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  652. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  653. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  654. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  655. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  656. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  657. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  658. package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
  659. package/src/plugins/builtin/reverse-dcf/model.ts +10 -5
  660. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  661. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  662. package/src/plugins/builtin/seasonality/client.ts +2 -1
  663. package/src/plugins/builtin/sec/forms.ts +13 -0
  664. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  665. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  666. package/src/plugins/builtin/sec/headless.ts +85 -8
  667. package/src/plugins/builtin/sec/index.tsx +58 -12
  668. package/src/plugins/builtin/sectors/client.ts +6 -4
  669. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  670. package/src/plugins/builtin/series-inventory.ts +2 -0
  671. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  672. package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
  673. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  674. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  675. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  676. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  677. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  678. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  679. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  680. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  681. package/src/plugins/builtin/shared/research-trading.tsx +23 -0
  682. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  683. package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
  684. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  685. package/src/plugins/builtin/shared/volatility/options.ts +2 -1
  686. package/src/plugins/builtin/short-interest/client.ts +2 -0
  687. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  688. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  689. package/src/plugins/builtin/short-interest/model.ts +70 -19
  690. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  691. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  692. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  693. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  694. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  695. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  696. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  697. package/src/plugins/builtin/short-interest/types.ts +9 -0
  698. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  699. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  700. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  701. package/src/plugins/builtin/social-mentions/client.ts +2 -1
  702. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  703. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  704. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  705. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  706. package/src/plugins/builtin/themes/headless.ts +8 -5
  707. package/src/plugins/builtin/themes/model.ts +14 -4
  708. package/src/plugins/builtin/themes/pane.tsx +24 -5
  709. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  710. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  711. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  712. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  713. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  714. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  715. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  716. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  717. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  718. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  719. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  720. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  721. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  722. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  723. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  724. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  725. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  726. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  727. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  728. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  729. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  730. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  731. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  732. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  733. package/src/plugins/builtin/vol-surface/client.ts +28 -7
  734. package/src/plugins/builtin/vol-surface/headless.ts +43 -15
  735. package/src/plugins/builtin/vol-surface/model.ts +34 -12
  736. package/src/plugins/builtin/vol-surface/pane.tsx +33 -13
  737. package/src/plugins/builtin/vol-surface/stored.ts +34 -3
  738. package/src/plugins/builtin/vol-surface/tables.ts +14 -0
  739. package/src/plugins/builtin/volatility/model.ts +5 -10
  740. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  741. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  742. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  743. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  744. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  745. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  746. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  747. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  748. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  749. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  750. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  751. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  752. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  753. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  754. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  755. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  756. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  757. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  758. package/src/plugins/bundle.ts +1 -1
  759. package/src/plugins/catalog-browser.ts +2 -1
  760. package/src/plugins/compat.ts +3 -3
  761. package/src/plugins/dependencies.ts +75 -14
  762. package/src/plugins/extracted-plugins.ts +132 -34
  763. package/src/plugins/host-link.ts +149 -34
  764. package/src/plugins/installer.ts +35 -10
  765. package/src/plugins/loader.ts +206 -38
  766. package/src/plugins/manager-node.ts +2 -2
  767. package/src/plugins/marketplace/deactivation.ts +22 -0
  768. package/src/plugins/marketplace/model.ts +2 -2
  769. package/src/plugins/marketplace/packs.ts +1 -1
  770. package/src/plugins/ownership.ts +1 -1
  771. package/src/plugins/peer-retry.ts +155 -0
  772. package/src/plugins/registry/contributions.ts +3 -1
  773. package/src/plugins/registry/index.ts +4 -3
  774. package/src/plugins/registry/plugin-state.ts +3 -0
  775. package/src/plugins/seed-notice.ts +20 -0
  776. package/src/plugins/shortcut-argument.ts +39 -0
  777. package/src/portfolio/allocation.ts +1 -1
  778. package/src/portfolio/collection-name.ts +31 -0
  779. package/src/portfolio/column-values.ts +10 -8
  780. package/src/portfolio/cost-fx.ts +296 -19
  781. package/src/portfolio/manual-lots.ts +75 -0
  782. package/src/portfolio/mutations.ts +60 -22
  783. package/src/portfolio/suffixed-listings.ts +209 -0
  784. package/src/portfolio/totals-currency.ts +24 -0
  785. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  786. package/src/public/time-series.ts +11 -8
  787. package/src/remote/schema.ts +1 -1
  788. package/src/renderers/browser/config-host.ts +3 -0
  789. package/src/renderers/browser/main.tsx +23 -3
  790. package/src/renderers/dom/boot-frame-page.ts +187 -0
  791. package/src/renderers/dom/boot-frame.ts +237 -0
  792. package/src/renderers/dom/build-assets.ts +46 -8
  793. package/src/renderers/dom/desktop/controls.tsx +1 -1
  794. package/src/renderers/dom/desktop/query-bar.tsx +2 -0
  795. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  796. package/src/renderers/dom/host/ascii-text.ts +16 -2
  797. package/src/renderers/dom/host/box.tsx +43 -2
  798. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  799. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  800. package/src/renderers/dom/host/image-surface.tsx +49 -0
  801. package/src/renderers/dom/host/media-surface.tsx +24 -18
  802. package/src/renderers/dom/host/mouse.ts +30 -0
  803. package/src/renderers/dom/host/size-observer.ts +1 -1
  804. package/src/renderers/dom/host/style.ts +1 -1
  805. package/src/renderers/dom/host/tabs.tsx +16 -5
  806. package/src/renderers/dom/host/top-surface.ts +127 -0
  807. package/src/renderers/dom/styles.css +115 -0
  808. package/src/renderers/dom/test-utils.tsx +2 -1
  809. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  810. package/src/renderers/electrobun/bun/core-capabilities.ts +9 -1
  811. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  812. package/src/renderers/electrobun/bun/desktop/backend.ts +56 -3
  813. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  814. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  815. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  816. package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
  817. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  818. package/src/renderers/electrobun/bun/index.ts +11 -1
  819. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  820. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  821. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  822. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  823. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  824. package/src/renderers/electrobun/view/config-host.ts +3 -0
  825. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  826. package/src/renderers/electrobun/view/main.tsx +30 -4
  827. package/src/renderers/electrobun/view/news-source.ts +9 -7
  828. package/src/renderers/electrobun/view/remote/asset-data-client.ts +9 -2
  829. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  830. package/src/renderers/opentui/browser-open.ts +88 -0
  831. package/src/renderers/opentui/host.tsx +5 -14
  832. package/src/renderers/opentui/image/loader.ts +3 -2
  833. package/src/renderers/opentui/native-smoke.ts +10 -1
  834. package/src/renderers/opentui/pane-image/index.ts +2 -1
  835. package/src/renderers/opentui/render-lib.ts +253 -0
  836. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  837. package/src/renderers/opentui/start.tsx +8 -1
  838. package/src/renderers/share/layout-view.tsx +2 -2
  839. package/src/renderers/share/main.tsx +4 -4
  840. package/src/renderers/share/view.tsx +1 -1
  841. package/src/series/resolve.ts +22 -6
  842. package/src/series/standalone.ts +30 -2
  843. package/src/series/types.ts +8 -1
  844. package/src/shares/api.ts +4 -1
  845. package/src/shares/pane.ts +1 -1
  846. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  847. package/src/sources/gloomberb-cloud/index.ts +39 -16
  848. package/src/sources/gloomberb-cloud/news.ts +39 -0
  849. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  850. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  851. package/src/sources/listing-symbols.ts +37 -0
  852. package/src/sources/provider-errors.ts +16 -2
  853. package/src/sources/provider-router/financial-routes.ts +21 -3
  854. package/src/sources/provider-router/financials.ts +15 -2
  855. package/src/sources/provider-router/history.ts +30 -8
  856. package/src/sources/provider-router/index.ts +16 -0
  857. package/src/sources/provider-router/primary.ts +1 -1
  858. package/src/state/app/bootstrap.ts +23 -0
  859. package/src/state/hooks/inline-tickers.ts +30 -5
  860. package/src/sync/controller.ts +1 -1
  861. package/src/sync/core-contributors.ts +46 -14
  862. package/src/team/collections-sync.ts +2 -1
  863. package/src/team/collections.ts +178 -17
  864. package/src/telemetry/crash-reports.ts +21 -4
  865. package/src/telemetry/update-failures-node.ts +59 -0
  866. package/src/telemetry/update-failures.ts +307 -0
  867. package/src/test-support/builtin-panes.ts +1 -1
  868. package/src/theme/colors.ts +3 -30
  869. package/src/theme/ui-tokens.ts +37 -1
  870. package/src/tickers/company-name-listing.ts +215 -36
  871. package/src/tickers/company-name.ts +43 -0
  872. package/src/tickers/index-roots.ts +47 -0
  873. package/src/tickers/instrument-label.ts +5 -1
  874. package/src/tickers/listing-fate.ts +30 -0
  875. package/src/tickers/metadata.ts +10 -0
  876. package/src/tickers/perpetual-listing.ts +5 -2
  877. package/src/tickers/search/home-listing.ts +75 -0
  878. package/src/tickers/search/index.ts +76 -27
  879. package/src/tickers/search/ranking.ts +54 -4
  880. package/src/tickers/search/upsert.ts +29 -0
  881. package/src/tickers/terminal-codes.ts +416 -40
  882. package/src/time-series/bar-aggregation.ts +243 -0
  883. package/src/time-series/base-series.ts +307 -0
  884. package/src/time-series/chart-bounds.ts +349 -0
  885. package/src/time-series/chart-seed.ts +142 -0
  886. package/src/time-series/economic.ts +5 -0
  887. package/src/time-series/fundamentals.ts +18 -3
  888. package/src/time-series/history-acquisition.ts +499 -0
  889. package/src/time-series/leverage.ts +100 -0
  890. package/src/time-series/market-resolution.ts +4 -2
  891. package/src/time-series/market.ts +2 -1
  892. package/src/time-series/price-comparison.ts +175 -30
  893. package/src/time-series/range.ts +9 -1
  894. package/src/time-series/resolution.ts +174 -16
  895. package/src/time-series/resolve-context.ts +157 -0
  896. package/src/time-series/resolve.ts +126 -1577
  897. package/src/time-series/series-name.ts +38 -0
  898. package/src/time-series/series-presentation.ts +208 -0
  899. package/src/time-series/spec.ts +11 -6
  900. package/src/time-series/studies.ts +109 -12
  901. package/src/time-series/tail-reconcile.ts +121 -0
  902. package/src/time-series/types.ts +29 -2
  903. package/src/time-series/use-chart-resolution.ts +4 -5
  904. package/src/types/broker.ts +10 -0
  905. package/src/types/config.ts +14 -0
  906. package/src/types/data-provider.ts +20 -0
  907. package/src/types/exchange-rate.ts +6 -0
  908. package/src/types/financials.ts +104 -7
  909. package/src/types/headless.ts +83 -6
  910. package/src/types/instrument.ts +3 -0
  911. package/src/types/issuer-listings.ts +28 -0
  912. package/src/types/plugin.ts +65 -8
  913. package/src/types/price-history.ts +2 -0
  914. package/src/types/ticker.ts +13 -0
  915. package/src/types/trading.ts +59 -1
  916. package/src/ui/ascii-font.ts +13 -1
  917. package/src/ui/host.tsx +6 -1
  918. package/src/updater/command-names.ts +175 -0
  919. package/src/updater/failure.ts +163 -0
  920. package/src/updater/index.ts +97 -28
  921. package/src/utils/calendar-date.ts +32 -15
  922. package/src/utils/cash-runway.ts +241 -0
  923. package/src/utils/central-banks.ts +42 -0
  924. package/src/utils/cli-output.ts +259 -80
  925. package/src/utils/contract-month.ts +16 -0
  926. package/src/utils/crypto-pair.ts +61 -3
  927. package/src/utils/currency-pair.ts +26 -0
  928. package/src/utils/currency-units.ts +29 -0
  929. package/src/utils/datetime-format.ts +10 -0
  930. package/src/utils/debug-log.ts +1 -1
  931. package/src/utils/decimal-comma.ts +39 -6
  932. package/src/utils/exchange-announcements.ts +71 -0
  933. package/src/utils/exchange-rate-snapshot.ts +10 -0
  934. package/src/utils/financial-statements.ts +83 -4
  935. package/src/utils/format.ts +34 -16
  936. package/src/utils/fundamentals.ts +150 -34
  937. package/src/utils/fx-market-hours.ts +10 -1
  938. package/src/utils/latest-financial-period.ts +8 -0
  939. package/src/utils/linux-libc.ts +54 -0
  940. package/src/utils/market-capitalization.ts +111 -15
  941. package/src/utils/max-drawdown.ts +64 -0
  942. package/src/utils/network-failure.ts +83 -0
  943. package/src/utils/option-expiry.ts +139 -7
  944. package/src/utils/price-earnings.ts +11 -5
  945. package/src/utils/price-history.ts +18 -8
  946. package/src/utils/price-window.ts +131 -0
  947. package/src/utils/release-date.ts +47 -0
  948. package/src/utils/sec.ts +71 -0
  949. package/src/utils/throttled-fetch.ts +11 -4
  950. package/src/utils/trailing-eps.ts +67 -0
  951. package/src/utils/typed-text.ts +21 -0
  952. package/src/utils/utc-time.ts +24 -1
  953. package/src/version.ts +6 -0
  954. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -8,13 +8,16 @@ import {
8
8
  DataTableStackView,
9
9
  EmptyState,
10
10
  PaneStatusBody, QueryBar,
11
+ StatGrid,
11
12
  usePaneFooter,
12
13
  useQueryBarSearch,
13
14
  useTableLoadMore,
14
15
  type DataTableCell,
15
16
  type DataTableKeyEvent,
16
17
  type DataTableRootKeyContext,
17
- type PaneFooterSegment
18
+ type PaneFooterSegment,
19
+ type QueryBarView,
20
+ type StatItem,
18
21
  } from "../../../components";
19
22
  import { handleRefreshKey } from "../../../components/data-table/table-pane";
20
23
  import { AudioPlayer, useCanPlayAudio } from "../../../components/ui";
@@ -35,7 +38,9 @@ import { usePluginPaneState } from "../../runtime";
35
38
  import { ProWall, SignInWall } from "../cloud/auth-actions";
36
39
  import { usePlanAccess } from "../../../api-client/plan-access";
37
40
  import { listingAbroad } from "../../../api-client/paths";
41
+ import { useAgeClock } from "../../../react/auto-refresh";
38
42
  import { useBoundTicker as useSymbolBinding } from "../shared/ticker-request";
43
+ import { CALLS_VIEWS, UpcomingCallsView, type CallsView } from "./calendar";
39
44
  import {
40
45
  cachedEarningsCalls,
41
46
  callStatusLabel,
@@ -48,6 +53,7 @@ import { callTitle, formatCallDate, formatDuration, formatPeriod, formatSentimen
48
53
  import { findCallForQuarter, findInLines, MIN_FIND_LENGTH, turnParagraphs } from "./model";
49
54
  import { READER_TABS, TranscriptView, type ReaderTab, type TranscriptPlayback } from "./transcript-view";
50
55
  import { PLAYBACK_RATES, SEEK_STEP_SECONDS, useCallPlayback } from "./use-call-playback";
56
+ import { callAway, callCountdown, callStartText, isUpcomingCall, nextCall } from "./upcoming";
51
57
 
52
58
  export const EARNINGS_CALLS_PANE_ID = "earnings-calls";
53
59
 
@@ -86,7 +92,7 @@ function buildColumns(width: number, showTicker: boolean): CallColumn[] {
86
92
  return columns;
87
93
  }
88
94
 
89
- function renderCell(call: CloudEarningsCallPayload, column: CallColumn): DataTableCell {
95
+ function renderCell(call: CloudEarningsCallPayload, column: CallColumn, now: number): DataTableCell {
90
96
  switch (column.id) {
91
97
  case "ticker":
92
98
  return { text: call.ticker };
@@ -99,7 +105,9 @@ function renderCell(call: CloudEarningsCallPayload, column: CallColumn): DataTab
99
105
  case "length":
100
106
  return { text: formatDuration(call.durationSeconds), color: colors.textDim };
101
107
  case "sentiment": {
102
- if (!call.hasTranscript) return { text: callStatusLabel(call), color: colors.textDim };
108
+ // A call still to come says how far away it is, not that it is queued.
109
+ if (isUpcomingCall(call, now)) return { text: callCountdown(call, now), color: colors.text };
110
+ if (!call.hasTranscript) return { text: callStatusLabel(call, now), color: colors.textDim };
103
111
  const tone =
104
112
  call.sentiment === null
105
113
  ? colors.textDim
@@ -180,13 +188,86 @@ interface EarningsCallsViewProps {
180
188
  height: number;
181
189
  }
182
190
 
191
+ /** The next call's own line: when it starts here and in New York, and how far away it is. */
192
+ function nextCallFigure(call: CloudEarningsCallPayload, now: number): StatItem {
193
+ const { start, newYork } = callStartText(call, now);
194
+ // A countdown that is a day's name repeats the start's; it says something within a day.
195
+ const away = callAway(call, now);
196
+ const detail = [newYork, away].filter(Boolean).join(" · ");
197
+ return {
198
+ id: "next-call",
199
+ label: "Next call",
200
+ value: start,
201
+ ...(detail ? { detail, detailVariants: [away ?? newYork ?? ""] } : {}),
202
+ tone: "accent",
203
+ };
204
+ }
205
+
206
+ /**
207
+ * CALLS: with a ticker, that company's calls, its next one on its own line;
208
+ * alone, the calendar of every company's calls this week, or the shelf of
209
+ * transcripts.
210
+ */
183
211
  export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewProps) {
184
212
  const { symbol, exchange, ticker: boundTicker } = useSymbolBinding();
213
+ // `shot CALLS --view transcripts` (a pane setting) opens on the shelf; a choice made in the pane wins.
214
+ const [requestedView] = usePaneSettingValue<string>("view", "");
215
+ const [chosenView, setView] = usePluginPaneState<CallsView | null>("view", null);
216
+ const view: CallsView = chosenView ?? (CALLS_VIEWS.some((option) => option.value === requestedView) ? requestedView as CallsView : "upcoming");
217
+ const viewChoice = useMemo<QueryBarView<CallsView>>(() => ({ value: view, options: CALLS_VIEWS, onChange: setView }), [setView, view]);
218
+
219
+ if (symbol) {
220
+ return (
221
+ <CallsListView
222
+ focused={focused} width={width} height={height}
223
+ symbol={symbol} exchange={exchange} listingName={boundTicker?.metadata.name}
224
+ />
225
+ );
226
+ }
227
+ if (view === "transcripts") {
228
+ return <CallsListView focused={focused} width={width} height={height} symbol={null} view={viewChoice} />;
229
+ }
230
+ return (
231
+ <UpcomingCallsView
232
+ focused={focused} width={width} height={height} view={viewChoice}
233
+ renderCompany={({ ticker, focused: companyFocused, height: companyHeight, onHoldsKeys }) => (
234
+ <CallsListView
235
+ key={ticker}
236
+ focused={companyFocused} width={width} height={companyHeight}
237
+ symbol={ticker} stateKey="company:" footerId={`${EARNINGS_CALLS_PANE_ID}:company`}
238
+ openFromSettings={false} onHoldsKeys={onHoldsKeys}
239
+ />
240
+ )}
241
+ />
242
+ );
243
+ }
244
+
245
+ interface CallsListProps extends EarningsCallsViewProps {
246
+ /** The company whose calls these are; null for the shelf of every company's transcripts. */
247
+ symbol: string | null;
248
+ exchange?: string;
249
+ /** The listing's company name, so a listing abroad reads its own calls. */
250
+ listingName?: string;
251
+ /** Prefix of the pane state this view keeps, so a company opened from the calendar keeps its own. */
252
+ stateKey?: string;
253
+ footerId?: string;
254
+ /** The calendar or the shelf, chosen in the query bar of CALLS alone. */
255
+ view?: QueryBarView<CallsView>;
256
+ /** Whether the pane's `quarter` and `reader` settings open a call here (a layout or a shot). */
257
+ openFromSettings?: boolean;
258
+ /** Told when this view holds the keys a stack around it would take: a call open, or its search focused. */
259
+ onHoldsKeys?: (holds: boolean) => void;
260
+ }
261
+
262
+ function CallsListView({
263
+ focused, width, height, symbol, exchange, listingName: boundName, stateKey = "", footerId = EARNINGS_CALLS_PANE_ID,
264
+ view, openFromSettings = true, onHoldsKeys,
265
+ }: CallsListProps) {
185
266
  const access = usePlanAccess();
186
267
  // Read once per mount: a binding change reads the cache again in its own effect.
187
268
  const [initialShelf] = useState(() => {
188
269
  const initialTicker = symbol ? symbol.toUpperCase() : null;
189
- const initialAbroad = initialTicker ? listingAbroad(initialTicker, exchange, boundTicker?.metadata.name) : null;
270
+ const initialAbroad = initialTicker ? listingAbroad(initialTicker, exchange, boundName) : null;
190
271
  return cachedEarningsCalls(initialTicker, {
191
272
  limit: CALL_PAGE_SIZE, exchange: initialAbroad?.exchange, name: initialAbroad?.name,
192
273
  });
@@ -206,8 +287,8 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
206
287
  const [nextOffset, setNextOffset] = useState(initialShelf?.calls.length ?? 0);
207
288
  const tableScrollRef = useRef<ScrollBoxRenderable | null>(null);
208
289
 
209
- const [selectedId, setSelectedId] = usePluginPaneState<string | null>("selectedId", null);
210
- const [detailOpen, setDetailOpen] = usePluginPaneState<boolean>("detailOpen", false);
290
+ const [selectedId, setSelectedId] = usePluginPaneState<string | null>(`${stateKey}selectedId`, null);
291
+ const [detailOpen, setDetailOpen] = usePluginPaneState<boolean>(`${stateKey}detailOpen`, false);
211
292
  const [transcript, setTranscript] = useState<CloudEarningsTranscriptPayload | null>(null);
212
293
  useEffect(() => {
213
294
  if (focused && transcript && detailOpen) recordResearchActivity("pro_feature_used", "transcripts");
@@ -217,13 +298,15 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
217
298
  message: string;
218
299
  status?: number;
219
300
  } | null>(null);
220
- const [readerTab, setReaderTab] = usePluginPaneState<ReaderTab>("readerTab", "summary");
221
- // A layout or `gloomberb shot CALLS NVDA --quarter latest --reader summary`
301
+ const [readerTab, setReaderTab] = usePluginPaneState<ReaderTab>(`${stateKey}readerTab`, "summary");
302
+ // A layout or `gloom shot CALLS NVDA --quarter latest --reader summary`
222
303
  // can land straight on a transcript instead of the shelf. `quarter` takes
223
304
  // the same tokens as the headless option; only transcribed calls qualify,
224
305
  // since opening a call without one asks the server to produce it.
225
- const [openQuarter] = usePaneSettingValue<string>("quarter", "");
226
- const [openReader] = usePaneSettingValue<string>("reader", "");
306
+ const [quarterSetting] = usePaneSettingValue<string>("quarter", "");
307
+ const [readerSetting] = usePaneSettingValue<string>("reader", "");
308
+ const openQuarter = openFromSettings ? quarterSetting : "";
309
+ const openReader = openFromSettings ? readerSetting : "";
227
310
  const openedQuarter = useRef<string | null>(null);
228
311
  const [sort, setSort] = useState<CallSort>(DEFAULT_SORT);
229
312
  const [searchQuery, setSearchQuery] = useState("");
@@ -240,7 +323,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
240
323
 
241
324
  const ticker = symbol ? symbol.toUpperCase() : null;
242
325
  // A listing abroad asks for its own calls by venue and company, never a US namesake's.
243
- const abroad = ticker ? listingAbroad(ticker, exchange, boundTicker?.metadata.name) : null;
326
+ const abroad = ticker ? listingAbroad(ticker, exchange, boundName) : null;
244
327
  const listingVenue = abroad?.exchange;
245
328
  const listingName = abroad?.name;
246
329
 
@@ -429,10 +512,16 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
429
512
  ];
430
513
  }, [calls, lookup, listFetchedAt]);
431
514
 
515
+ // Countdowns move on a coarse clock that rests while the pane is hidden.
516
+ const now = useAgeClock(listFetchedAt || null);
517
+ // A company's next call is its own line above its calls, not one of the rows.
518
+ const next = useMemo(() => (ticker ? nextCall(allCalls, now) : null), [allCalls, now, ticker]);
519
+ const listedCalls = useMemo(() => (next ? allCalls.filter((call) => call.id !== next.id) : allCalls), [allCalls, next]);
520
+
432
521
  const rows = useMemo(() => {
433
522
  const query = searchQuery.trim().toLowerCase();
434
523
  const matched = query
435
- ? allCalls.filter((call) =>
524
+ ? listedCalls.filter((call) =>
436
525
  [
437
526
  call.ticker,
438
527
  call.companyName ?? "",
@@ -443,7 +532,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
443
532
  .toLowerCase()
444
533
  .includes(query),
445
534
  )
446
- : allCalls;
535
+ : listedCalls;
447
536
  const sorted = [...matched].sort((a, b) => {
448
537
  const left = sortValue(a, sort.columnId);
449
538
  const right = sortValue(b, sort.columnId);
@@ -452,7 +541,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
452
541
  return sort.direction === "asc" ? order : -order;
453
542
  });
454
543
  return sorted;
455
- }, [allCalls, sort, searchQuery]);
544
+ }, [listedCalls, sort, searchQuery]);
456
545
 
457
546
  useEffect(() => {
458
547
  const quarter = openQuarter.trim();
@@ -474,6 +563,9 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
474
563
  );
475
564
  const selectedCallId = selected?.id ?? null;
476
565
  const selectedHasTranscript = selected?.hasTranscript ?? false;
566
+ // A call still to come has nothing to read, and asking for its transcript
567
+ // would ask the server to produce one before the call has happened.
568
+ const selectedUpcoming = !!selected && isUpcomingCall(selected, now);
477
569
  // The reader shows only a call the pane can find. A restored call that is not
478
570
  // on the reloaded shelf (a lookup result, or one that aged off) closes once
479
571
  // the shelf has loaded, rather than leave the keys pointing at a reader that
@@ -544,7 +636,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
544
636
  // a call that has none asks the server to produce it, then checks back
545
637
  // until it arrives.
546
638
  useEffect(() => {
547
- if (!detailOpen || !selectedCallId || !access.emailVerified || !access.hasProAccess) return;
639
+ if (!detailOpen || !selectedCallId || selectedUpcoming || !access.emailVerified || !access.hasProAccess) return;
548
640
  // A binding change clears selection in an effect; do not start a request
549
641
  // for that previous selection during the same render's effect pass.
550
642
  if (ticker && selected?.ticker.toUpperCase() !== ticker) return;
@@ -592,7 +684,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
592
684
  };
593
685
  // The call's identity is what matters; list refreshes must not restart this.
594
686
  // eslint-disable-next-line react-hooks/exhaustive-deps
595
- }, [detailOpen, selectedCallId, ticker, access.emailVerified, access.hasProAccess]);
687
+ }, [detailOpen, selectedCallId, selectedUpcoming, ticker, access.emailVerified, access.hasProAccess]);
596
688
 
597
689
  const scrollTranscriptBy = useCallback((delta: number) => {
598
690
  if (transcriptScrollRef.current) scrollByLines(transcriptScrollRef.current, delta);
@@ -629,6 +721,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
629
721
  const transcriptProRequired = transcriptError?.status === 402;
630
722
 
631
723
  const columns = useMemo(() => buildColumns(width, !ticker), [width, ticker]);
724
+ const renderRow = useCallback((call: CloudEarningsCallPayload, column: CallColumn) => renderCell(call, column, now), [now]);
632
725
 
633
726
  const handleRootKey = useCallback(
634
727
  (event: DataTableKeyEvent, context: DataTableRootKeyContext) => {
@@ -664,6 +757,13 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
664
757
  // Only a loaded transcript has a find field; a wall, an upsell or a first
665
758
  // load has no list or reader for the search keys to reach.
666
759
  const readerSearchable = readerOpen && !!selectedTranscript && !transcriptProRequired;
760
+ // A calendar around this view gives it Back, Esc and Backspace while a call
761
+ // is open here or the search has the keys.
762
+ const holdsKeys = readerOpen || searchFocused;
763
+ useEffect(() => {
764
+ onHoldsKeys?.(holdsKeys);
765
+ }, [holdsKeys, onHoldsKeys]);
766
+ useEffect(() => () => onHoldsKeys?.(false), [onHoldsKeys]);
667
767
  // Mirrors the bodies below: the list renders unless a wall, an upsell, or an
668
768
  // empty shelf's loading, failed or research-tab state takes its place.
669
769
  const listShown = !signInRequired && !verificationRequired && !proRequired
@@ -717,7 +817,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
717
817
  );
718
818
 
719
819
  usePaneFooter(
720
- EARNINGS_CALLS_PANE_ID,
820
+ footerId,
721
821
  () => {
722
822
  const info: PaneFooterSegment[] = [];
723
823
  if (listStatus === "loading") {
@@ -847,7 +947,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
847
947
  placement="calls-wall"
848
948
  width={width} height={height} symbol={symbol} exchange={exchange}
849
949
  title="Earnings call transcripts are part of Gloom Cloud Pro."
850
- message="Gloomberb transcribes the calls itself: full transcripts with speaker attribution, analyst Q&A, and extracted guidance, risks and tone."
950
+ message="Full transcripts of each earnings call with speaker attribution, analyst Q&A, and extracted guidance, risks and tone."
851
951
  />
852
952
  );
853
953
  }
@@ -884,6 +984,8 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
884
984
  title="Earnings call transcripts are part of Gloom Cloud Pro."
885
985
  message="Full transcripts with speaker attribution, analyst Q&A, guidance and risk extraction, transcribed from the call itself."
886
986
  />
987
+ ) : selected && selectedUpcoming ? (
988
+ <UpcomingCallState call={selected} now={now} />
887
989
  ) : selected && !selectedTranscript && (producing || (!selected.hasTranscript && !transcriptError)) ? (
888
990
  <PaneStatusBody loading loadingLabel="Producing the transcript. This usually takes two to three minutes." />
889
991
  ) : (
@@ -945,17 +1047,21 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
945
1047
  detailContent={detailContent}
946
1048
  detailTitle={selected ? callTitle(selected) : undefined}
947
1049
  rootBefore={
948
- <QueryBar
949
- width={width}
950
- search={{
951
- value: searchQuery,
952
- onChange: setSearchQuery,
953
- placeholder: "ticker, company, or period",
954
- focused: focused && !readerOpen,
955
- ...searchProps,
956
- debounceMs: 80,
957
- }}
958
- />
1050
+ <Box flexDirection="column" flexShrink={0}>
1051
+ <QueryBar
1052
+ width={width}
1053
+ search={{
1054
+ value: searchQuery,
1055
+ onChange: setSearchQuery,
1056
+ placeholder: "ticker, company, or period",
1057
+ focused: focused && !readerOpen,
1058
+ ...searchProps,
1059
+ debounceMs: 80,
1060
+ }}
1061
+ view={view}
1062
+ />
1063
+ {next ? <StatGrid items={[nextCallFigure(next, now)]} width={width} /> : null}
1064
+ </Box>
959
1065
  }
960
1066
  onRootKeyDown={handleRootKey}
961
1067
  onDetailKeyDown={handleDetailKey}
@@ -986,7 +1092,7 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
986
1092
  setSort((current) => nextHeaderSort(current, columnId, { firstDirection: "desc" }))
987
1093
  }
988
1094
  getItemKey={(call) => call.id}
989
- renderCell={renderCell}
1095
+ renderCell={renderRow}
990
1096
  emptyStateTitle={
991
1097
  lookupTicker && lookupState
992
1098
  ? lookupState === "unknown"
@@ -998,9 +1104,21 @@ export function EarningsCallsPane({ focused, width, height }: EarningsCallsViewP
998
1104
  : `Looking up ${lookupTicker}...`
999
1105
  : searchQuery.trim()
1000
1106
  ? "No matching calls."
1001
- : "No calls yet."
1107
+ : next ? "No calls before this one yet." : "No calls yet."
1002
1108
  }
1003
1109
  emptyStateHint={searchQuery.trim() ? "Clear the search to see all calls." : undefined}
1004
1110
  />
1005
1111
  );
1006
1112
  }
1113
+
1114
+ /** An open call still to come: when it starts, here and in New York, and how far away. */
1115
+ function UpcomingCallState({ call, now }: { call: CloudEarningsCallPayload; now: number }) {
1116
+ const { start, newYork } = callStartText(call, now);
1117
+ const away = callAway(call, now);
1118
+ return (
1119
+ <EmptyState
1120
+ title={`Starts ${start}${newYork ? ` (${newYork})` : ""}${away ? `, ${away}` : ""}.`}
1121
+ message="The transcript follows once the call is over."
1122
+ />
1123
+ );
1124
+ }
@@ -0,0 +1,195 @@
1
+ import type { CloudEarningsCallPayload } from "../../../api-client";
2
+ import type { TableSection } from "../../../components";
3
+ import { formatCountdown } from "../../../utils/datetime-format";
4
+ import { addDays, marketDays, newYorkToday, type MarketDay } from "../earnings/board-model";
5
+ import { shortDate, weekday } from "../earnings/format";
6
+
7
+ const DAY_MS = 86_400_000;
8
+
9
+ /**
10
+ * Whether a call's `callAt` is its start. A call known by its day alone is
11
+ * stored at 00:00 UTC of that New York day; a server that does not say which
12
+ * is read the same way.
13
+ */
14
+ export function callTimeKnown(call: Pick<CloudEarningsCallPayload, "callAt" | "callTimeKnown">): boolean {
15
+ const at = call.callAt ? Date.parse(call.callAt) : Number.NaN;
16
+ if (!Number.isFinite(at)) return false;
17
+ if (typeof call.callTimeKnown === "boolean") return call.callTimeKnown;
18
+ return at % DAY_MS !== 0;
19
+ }
20
+
21
+ /** The New York day a call is on (YYYY-MM-DD): its start's, or the day it is known by. */
22
+ export function callDay(call: Pick<CloudEarningsCallPayload, "callAt" | "callTimeKnown">): string | null {
23
+ const at = call.callAt ? Date.parse(call.callAt) : Number.NaN;
24
+ if (!Number.isFinite(at)) return null;
25
+ return callTimeKnown(call) ? newYorkToday(new Date(at)) : new Date(at).toISOString().slice(0, 10);
26
+ }
27
+
28
+ /**
29
+ * A call still to come: no transcript yet, and its start ahead, or, known by
30
+ * its day alone, that day today or later in New York. A transcribed call has
31
+ * happened, whatever its date says.
32
+ */
33
+ export function isUpcomingCall(call: CloudEarningsCallPayload, now = Date.now()): boolean {
34
+ if (call.hasTranscript) return false;
35
+ if (callTimeKnown(call)) return Date.parse(call.callAt!) > now;
36
+ const day = callDay(call);
37
+ return day !== null && day >= newYorkToday(new Date(now));
38
+ }
39
+
40
+ /** Earliest first: by New York day, then the calls with a start, in order, then those known by the day. */
41
+ export function compareCallStarts(left: CloudEarningsCallPayload, right: CloudEarningsCallPayload): number {
42
+ const leftDay = callDay(left) ?? "9999-12-31";
43
+ const rightDay = callDay(right) ?? "9999-12-31";
44
+ if (leftDay !== rightDay) return leftDay < rightDay ? -1 : 1;
45
+ const leftKnown = callTimeKnown(left);
46
+ const rightKnown = callTimeKnown(right);
47
+ if (leftKnown !== rightKnown) return leftKnown ? -1 : 1;
48
+ return (Date.parse(left.callAt ?? "") || 0) - (Date.parse(right.callAt ?? "") || 0) || left.ticker.localeCompare(right.ticker);
49
+ }
50
+
51
+ /** A company's next call: the soonest of its calls still to come. */
52
+ export function nextCall(calls: readonly CloudEarningsCallPayload[], now = Date.now()): CloudEarningsCallPayload | null {
53
+ return calls.filter((call) => isUpcomingCall(call, now)).sort(compareCallStarts)[0] ?? null;
54
+ }
55
+
56
+ const localDay = (at: number) => {
57
+ const date = new Date(at);
58
+ return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
59
+ };
60
+
61
+ /**
62
+ * How far away a call is. With its start: "in 25m" and "in 3h" within a day
63
+ * (the countdown econ events use), then its weekday on this machine's clock
64
+ * within the week ("Thu"), then its date ("Oct 30"); "started" once it has.
65
+ * Known by its day alone: "today", "tomorrow", then the same.
66
+ */
67
+ export function callCountdown(call: CloudEarningsCallPayload, now = Date.now()): string {
68
+ const day = callDay(call);
69
+ if (!day) return "";
70
+ if (!callTimeKnown(call)) {
71
+ const today = newYorkToday(new Date(now));
72
+ if (day < today) return shortDate(day);
73
+ if (day === today) return "today";
74
+ if (day === addDays(today, 1)) return "tomorrow";
75
+ return day <= addDays(today, 6) ? weekday(day) : shortDate(day);
76
+ }
77
+ const at = Date.parse(call.callAt!);
78
+ const ahead = at - now;
79
+ if (ahead <= 0) return "started";
80
+ if (ahead < DAY_MS) return formatCountdown(ahead);
81
+ const days = Math.round((localDay(at) - localDay(now)) / DAY_MS);
82
+ const date = new Date(at);
83
+ const local = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
84
+ return days <= 6 ? weekday(local) : shortDate(local);
85
+ }
86
+
87
+ /**
88
+ * The countdown when it says more than the call's day does: "in 3h", "today",
89
+ * "tomorrow". Null when it would only name the day ("Thu", "Oct 30").
90
+ */
91
+ export function callAway(call: CloudEarningsCallPayload, now = Date.now()): string | null {
92
+ const countdown = callCountdown(call, now);
93
+ return /^(in |today$|tomorrow$)/.test(countdown) ? countdown : null;
94
+ }
95
+
96
+ const clockFormatters = new Map<string, Intl.DateTimeFormat>();
97
+
98
+ function clockFormatter(timeZone: string | undefined, withDay: boolean): Intl.DateTimeFormat {
99
+ const key = `${timeZone ?? ""}:${withDay}`;
100
+ let formatter = clockFormatters.get(key);
101
+ if (!formatter) {
102
+ formatter = new Intl.DateTimeFormat("en-US", {
103
+ timeZone,
104
+ hour: "2-digit",
105
+ minute: "2-digit",
106
+ hourCycle: "h23",
107
+ ...(withDay ? { weekday: "short", month: "short", day: "numeric" } : {}),
108
+ });
109
+ clockFormatters.set(key, formatter);
110
+ }
111
+ return formatter;
112
+ }
113
+
114
+ function clock(at: number, timeZone: string | undefined, withDay: boolean): string {
115
+ const parts = Object.fromEntries(clockFormatter(timeZone, withDay).formatToParts(new Date(at)).map((part) => [part.type, part.value]));
116
+ const time = `${parts.hour}:${parts.minute}`;
117
+ return withDay ? `${parts.weekday} ${parts.month} ${parts.day} ${time}` : time;
118
+ }
119
+
120
+ const NEW_YORK = "America/New_York";
121
+
122
+ /** Its start on this machine's clock ("22:30"), or null for a call known by its day alone. */
123
+ export function callLocalClock(call: CloudEarningsCallPayload): string | null {
124
+ return callTimeKnown(call) ? clock(Date.parse(call.callAt!), undefined, false) : null;
125
+ }
126
+
127
+ /** Its start on New York's clock ("16:30"), or null for a call known by its day alone. */
128
+ export function callNewYorkClock(call: CloudEarningsCallPayload): string | null {
129
+ return callTimeKnown(call) ? clock(Date.parse(call.callAt!), NEW_YORK, false) : null;
130
+ }
131
+
132
+ /** Whether this machine's clock reads New York's at every one of these starts, so one time says both. */
133
+ export function clockIsNewYork(calls: readonly CloudEarningsCallPayload[], now = Date.now()): boolean {
134
+ const starts = [now, ...calls.filter(callTimeKnown).map((call) => Date.parse(call.callAt!))];
135
+ return starts.every((at) => clock(at, undefined, true) === clock(at, NEW_YORK, true));
136
+ }
137
+
138
+ /**
139
+ * When the next call starts, as its own line names it: the day and time here,
140
+ * then New York's ("Thu Oct 22 22:30", "16:30 ET"), New York's alone when the
141
+ * two agree ("Thu Oct 22 16:30 ET"), or the day alone ("Thu Oct 22").
142
+ */
143
+ export function callStartText(call: CloudEarningsCallPayload, now = Date.now()): { start: string; newYork: string | null } {
144
+ const day = callDay(call);
145
+ if (!day) return { start: "", newYork: null };
146
+ if (!callTimeKnown(call)) return { start: `${weekday(day)} ${shortDate(day)}`, newYork: null };
147
+ const at = Date.parse(call.callAt!);
148
+ if (clockIsNewYork([call], now)) return { start: `${clock(at, NEW_YORK, true)} ET`, newYork: null };
149
+ return { start: clock(at, undefined, true), newYork: `${clock(at, NEW_YORK, false)} ET` };
150
+ }
151
+
152
+ /** The calendar's days: today when the market trades, the next session, then the rest of that week (ERN's board). */
153
+ export function calendarDays(now = Date.now()): MarketDay[] {
154
+ return marketDays(newYorkToday(new Date(now)));
155
+ }
156
+
157
+ export type CalendarSort = { column: "time" | "ticker" | "company"; direction: "asc" | "desc" };
158
+
159
+ export const DEFAULT_CALENDAR_SORT: CalendarSort = { column: "time", direction: "asc" };
160
+
161
+ function compareRows(left: CloudEarningsCallPayload, right: CloudEarningsCallPayload, sort: CalendarSort): number {
162
+ const order = sort.column === "ticker"
163
+ ? left.ticker.localeCompare(right.ticker)
164
+ : sort.column === "company"
165
+ ? (left.companyName ?? left.ticker).localeCompare(right.companyName ?? right.ticker, undefined, { sensitivity: "base" })
166
+ : compareCallStarts(left, right);
167
+ return (sort.direction === "asc" ? order : -order) || compareCallStarts(left, right);
168
+ }
169
+
170
+ /**
171
+ * The calendar's sections: one per day with calls on it, its calls in start
172
+ * order (or the sort's), one per company and start.
173
+ */
174
+ export function calendarSections(
175
+ calls: readonly CloudEarningsCallPayload[],
176
+ days: readonly MarketDay[],
177
+ sort: CalendarSort = DEFAULT_CALENDAR_SORT,
178
+ ): Array<TableSection<CloudEarningsCallPayload>> {
179
+ const seen = new Set<string>();
180
+ const unique = calls.filter((call) => {
181
+ const key = `${call.ticker}:${call.callAt}`;
182
+ if (seen.has(key)) return false;
183
+ seen.add(key);
184
+ return true;
185
+ });
186
+ return days.map((day) => ({
187
+ label: day.label,
188
+ items: unique
189
+ .filter((call) => {
190
+ const on = callDay(call);
191
+ return on !== null && on >= day.from && on <= day.to;
192
+ })
193
+ .sort((left, right) => compareRows(left, right, sort)),
194
+ }));
195
+ }
@@ -46,11 +46,16 @@ const HOP_SEPARATOR = " › ";
46
46
 
47
47
  /**
48
48
  * Holding to via, then via to the company that reports. The first hop is
49
- * padded with no-break spaces, which the desktop does not collapse.
49
+ * padded with no-break spaces, which the desktop does not collapse. A column
50
+ * too narrow for the route keeps each share whole or leaves it out (`8% of
51
+ * NVDA purchases › …`), never a figure cut off from whose it is.
50
52
  */
51
- function shareText(row: SecondHopRow, firstHopWidth: number) {
52
- const first = hopLabel(row.hops[0]);
53
- return `${first}${"\u00a0".repeat(Math.max(0, firstHopWidth - displayWidth(first)))}${HOP_SEPARATOR}${hopLabel(row.hops[1])}`;
53
+ function shareText(row: SecondHopRow, firstHopWidth: number, cells = Infinity) {
54
+ const first = hopLabel(row.hops[0]), second = hopLabel(row.hops[1]);
55
+ const lined = `${first}${"\u00a0".repeat(Math.max(0, firstHopWidth - displayWidth(first)))}${HOP_SEPARATOR}${second}`;
56
+ if (displayWidth(lined) <= cells) return lined;
57
+ const whole = `${first}${HOP_SEPARATOR}${second}`;
58
+ return displayWidth(whole) <= cells ? whole : `${first}${HOP_SEPARATOR}…`;
54
59
  }
55
60
 
56
61
  /**
@@ -113,7 +118,7 @@ function renderSecondHopCell(row: SecondHopRow, column: DataTableColumn, firstHo
113
118
  case "link": return { text: row.link === "customer" ? "customer's customer" : "supplier's supplier" };
114
119
  case "via": return { text: row.via };
115
120
  case "holding": return { text: row.holding };
116
- case "shares": return { text: shareText(row, firstHopWidth), value: shareText(row, 0) };
121
+ case "shares": return { text: shareText(row, firstHopWidth, column.width), value: shareText(row, 0) };
117
122
  case "move": return move(row);
118
123
  default: return { text: row.holdingDate ?? "--" };
119
124
  }