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
@@ -26,7 +26,8 @@ import {
26
26
  } from "../command-bar/panel/prompt-binding";
27
27
  import { useAppDispatch, useAppSelector, type AppState } from "../../state/app/context";
28
28
  import { useViewport } from "../../react/input";
29
- import { canRetryUpdate } from "../../app/global-shortcuts";
29
+ import { canRetryUpdate } from "../../updater";
30
+ import { updateFailureReason } from "../../updater/failure";
30
31
  import { t, tf } from "../../i18n";
31
32
  import { displayWidth, truncateToDisplayWidth } from "../../utils/format";
32
33
  import { ClippedText, NATIVE_CLIP_STYLE } from "../ui/display";
@@ -43,8 +44,12 @@ const UPDATE_NOTICE_DURATION_MS = 5_000;
43
44
  * The retry hint gives way before the message goes under it.
44
45
  */
45
46
  const UPDATE_ERROR_MIN_COLUMNS = 12;
46
- /** Kept clear after the failed-update banner, so its last character never touches the Help pill. */
47
- const UPDATE_ERROR_GAP_COLUMNS = 1;
47
+ /** Kept clear after the terminal update status, so its last character never touches the Help pill. */
48
+ const UPDATE_STATUS_GAP_COLUMNS = 1;
49
+ /** Below this many characters of the reason, the terminal banner says "Update failed" and the retry key instead. */
50
+ const UPDATE_REASON_MIN_COLUMNS = 8;
51
+ /** A terminal line about an update narrower than this is left out rather than shown as a stub. */
52
+ const UPDATE_TEXT_MIN_COLUMNS = 8;
48
53
  /** Left padding of the update status's slot, in cells; the desktop's title-bar layout also pads its right. */
49
54
  const UPDATE_SLOT_PADDING_COLUMNS = 2;
50
55
  /** The Help pill's own props, shared by its button and the width the update status leaves it. */
@@ -315,6 +320,9 @@ type UpdateStatusView =
315
320
  | { kind: "restart"; text: string; version: string }
316
321
  | { kind: "failed"; message: string; parts: StatusPart[]; retry: boolean };
317
322
 
323
+ /** The failed banner's words without the reason, for a terminal slot too narrow to read one. */
324
+ const UPDATE_FAILED_SHORT = "Update failed";
325
+
318
326
  /**
319
327
  * A line of the status in the pieces the desktop may treat apart: a `cut`
320
328
  * piece ends in an ellipsis and gives way, the rest stays whole. The download
@@ -372,8 +380,13 @@ function resolveUpdateStatusView({
372
380
  return { kind: "text", text: t(updateProgress.message ?? "Update ready, restart to apply") };
373
381
  }
374
382
  if (updateProgress.phase === "error") {
375
- // One line: an error that carries a stack or a command's output must not grow the header.
376
- const error = (updateProgress.error ?? "Unknown error").replace(/\s+/g, " ").trim();
383
+ // The reason in a few words; the whole error is in the command bar's Check
384
+ // for Updates and the log. An error without one (from an older desktop
385
+ // process) is shown on one line: a stack or a command's output must not
386
+ // grow the header.
387
+ const error = updateProgress.failure
388
+ ? t(updateFailureReason(updateProgress.failure))
389
+ : (updateProgress.error ?? "Unknown error").replace(/\s+/g, " ").trim();
377
390
  return {
378
391
  kind: "failed",
379
392
  message: tf("Update failed: {error}", { error }),
@@ -399,7 +412,7 @@ function resolveUpdateStatusView({
399
412
  if (updateAvailable.updateAction.kind === "managed") {
400
413
  return {
401
414
  kind: "text",
402
- text: tf("v{version} available, update through the package manager that installed Gloomberb", {
415
+ text: tf("v{version} available, update through the package manager that installed Gloom", {
403
416
  version: updateAvailable.version,
404
417
  }),
405
418
  };
@@ -411,24 +424,16 @@ function resolveUpdateStatusView({
411
424
  }
412
425
 
413
426
  /**
414
- * What the header says about an update. The terminal cuts it to `columns`,
415
- * the room its slot is guaranteed; the desktop and the web let the browser fit
416
- * it to the room the bar leaves (NativeUpdateStatus). Either way it never runs
417
- * into the Help pill or the market cluster beside it.
427
+ * What the header says about an update, and the key that acts on it (Restart
428
+ * for a downloaded update, retry for a failed one). A passing notice goes
429
+ * after its time.
418
430
  */
419
- function UpdateStatus({ columns, onRestart, trailingGap = false }: {
420
- columns: number;
421
- onRestart?: () => void;
422
- /** The desktop title bar keeps a gap after the status as well as before it. */
423
- trailingGap?: boolean;
424
- }) {
425
- const { nativePaneChrome = false } = useUiCapabilities();
431
+ function useUpdateStatus(canRestart: boolean): { view: UpdateStatusView | null; updateKey: string } {
426
432
  const dispatch = useAppDispatch();
427
433
  const updateAvailable = useAppSelector((state) => state.updateAvailable);
428
434
  const updateProgress = useAppSelector((state) => state.updateProgress);
429
435
  const updateCheckInProgress = useAppSelector((state) => state.updateCheckInProgress);
430
436
  const updateNotice = useAppSelector((state) => state.updateNotice);
431
- // One key: Restart for a downloaded update, retry for a failed one.
432
437
  const updateKey = useActionShortcut("install-update");
433
438
 
434
439
  useEffect(() => {
@@ -440,12 +445,65 @@ function UpdateStatus({ columns, onRestart, trailingGap = false }: {
440
445
  }, [dispatch, updateAvailable, updateCheckInProgress, updateNotice, updateProgress]);
441
446
 
442
447
  const view = resolveUpdateStatusView({
443
- canRestart: !!onRestart,
448
+ canRestart,
444
449
  updateAvailable,
445
450
  updateCheckInProgress,
446
451
  updateNotice,
447
452
  updateProgress,
448
453
  });
454
+ return { view, updateKey };
455
+ }
456
+
457
+ /** The retry key after a failed update's message, when there is something to retry. */
458
+ function retryHint(view: Extract<UpdateStatusView, { kind: "failed" }>, updateKey: string): string {
459
+ return updateKey && view.retry ? ` ${updateKey} ${t("retry")}` : "";
460
+ }
461
+
462
+ /**
463
+ * Columns the terminal status takes when nothing is cut: the header gives the
464
+ * slot that much from the closed prompt's empty room before it cuts anything.
465
+ */
466
+ function terminalUpdateStatusColumns(view: UpdateStatusView, updateKey: string): number {
467
+ return UPDATE_STATUS_GAP_COLUMNS + terminalUpdateStatusContentColumns(view, updateKey);
468
+ }
469
+
470
+ function terminalUpdateStatusContentColumns(view: UpdateStatusView, updateKey: string): number {
471
+ switch (view.kind) {
472
+ case "busy":
473
+ return 2 + displayWidth(view.text);
474
+ case "restart":
475
+ return displayWidth(view.text) + 1 + terminalButtonColumns({ label: "Restart", shortcut: updateKey || undefined, compact: true });
476
+ case "failed":
477
+ return displayWidth(view.message) + displayWidth(retryHint(view, updateKey));
478
+ case "text":
479
+ return displayWidth(view.text);
480
+ }
481
+ }
482
+
483
+ /**
484
+ * The narrowest the closed terminal prompt goes to make room for an update's
485
+ * status: its caret and the whole placeholder, which sells the command bar to
486
+ * a first-time user, without the key hint (resolveHeaderPromptContent).
487
+ */
488
+ function terminalClosedPromptFloor(): number {
489
+ return 2 + PROMPT_CARET.length + t("Search or run a command").length;
490
+ }
491
+
492
+ /**
493
+ * What the header says about an update. The terminal cuts it to `columns`,
494
+ * the room its slot is guaranteed; the desktop and the web let the browser fit
495
+ * it to the room the bar leaves (NativeUpdateStatus). Either way it never runs
496
+ * into the Help pill or the market cluster beside it.
497
+ */
498
+ function UpdateStatus({ columns, onRestart, status, trailingGap = false }: {
499
+ columns: number;
500
+ onRestart?: () => void;
501
+ status: { view: UpdateStatusView | null; updateKey: string };
502
+ /** The desktop title bar keeps a gap after the status as well as before it. */
503
+ trailingGap?: boolean;
504
+ }) {
505
+ const { nativePaneChrome = false } = useUiCapabilities();
506
+ const { view, updateKey } = status;
449
507
  if (!view) return null;
450
508
  return nativePaneChrome
451
509
  ? <NativeUpdateStatus view={view} onRestart={onRestart} trailingGap={trailingGap} updateKey={updateKey} />
@@ -458,39 +516,115 @@ function TerminalUpdateStatus({ columns, onRestart, updateKey, view }: {
458
516
  updateKey: string;
459
517
  view: UpdateStatusView;
460
518
  }) {
461
- const colors = useThemeColors();
519
+ const content = terminalUpdateStatusContent({ room: columns - UPDATE_STATUS_GAP_COLUMNS, onRestart, updateKey, view });
520
+ if (!content) return null;
521
+ return (
522
+ <Box flexDirection="row" overflow="hidden" paddingRight={UPDATE_STATUS_GAP_COLUMNS}>
523
+ {content}
524
+ </Box>
525
+ );
526
+ }
527
+
528
+ /** The status cut to `room` columns, or null when nothing of it would read. */
529
+ function terminalUpdateStatusContent({ onRestart, room, updateKey, view }: {
530
+ onRestart?: () => void;
531
+ room: number;
532
+ updateKey: string;
533
+ view: UpdateStatusView;
534
+ }): ReactNode {
462
535
  if (view.kind === "busy") {
463
- return (
464
- <Box flexDirection="row" gap={1}>
465
- <SpinnerMark name="dots" color={colors.headerText} />
466
- <Text fg={colors.headerText}>{view.text}</Text>
467
- </Box>
468
- );
536
+ // The spinner and a cell after it, then the words, cut to what is left.
537
+ if (room < 2 + UPDATE_TEXT_MIN_COLUMNS) return null;
538
+ return <TerminalBusyStatus text={fitStatusParts(view.parts, room - 2)} />;
469
539
  }
470
540
  if (view.kind === "restart") {
471
- return (
472
- <Box flexDirection="row" gap={1} alignItems="center">
473
- <Text fg={colors.headerText}>{view.text}</Text>
474
- <Button compact label="Restart" shortcut={updateKey || undefined} onPress={onRestart} stopPropagation />
475
- </Box>
476
- );
541
+ // The button stays when the words do not fit beside it.
542
+ const buttonColumns = terminalButtonColumns({ label: "Restart", shortcut: updateKey || undefined, compact: true });
543
+ if (room < buttonColumns) return null;
544
+ const showText = displayWidth(view.text) + 1 + buttonColumns <= room;
545
+ return <TerminalRestartStatus text={showText ? view.text : null} onRestart={onRestart} updateKey={updateKey} />;
477
546
  }
478
547
  if (view.kind === "failed") {
479
- const hint = updateKey && view.retry ? ` ${updateKey} ${t("retry")}` : "";
548
+ const hint = retryHint(view, updateKey);
480
549
  const hintColumns = displayWidth(hint);
481
- // The message goes first, and keeps its room before the hint takes any.
482
- const room = columns - UPDATE_ERROR_GAP_COLUMNS;
483
- const showHint = hintColumns > 0 && room - hintColumns >= UPDATE_ERROR_MIN_COLUMNS;
484
- const messageColumns = room - (showHint ? hintColumns : 0);
485
- if (messageColumns < UPDATE_ERROR_MIN_COLUMNS) return null;
486
- return (
487
- <Box flexDirection="row" overflow="hidden" paddingRight={UPDATE_ERROR_GAP_COLUMNS}>
488
- <ClippedText fg={colors.headerText} text={view.message} width={messageColumns} />
489
- {showHint ? <Text fg={blendHex(colors.headerText, colors.header, 0.62)}>{hint}</Text> : null}
490
- </Box>
491
- );
550
+ const messageColumns = displayWidth(view.message);
551
+ const short = t(UPDATE_FAILED_SHORT);
552
+ const reasonRoom = room - displayWidth(view.parts[0]?.cut === false ? view.parts[0].text : "");
553
+ // The whole message with its key, then the message alone, then as much of
554
+ // the reason as reads, then "Update failed" with its key; never less.
555
+ let text: string;
556
+ let showHint = false;
557
+ if (messageColumns + hintColumns <= room) {
558
+ text = view.message;
559
+ showHint = hintColumns > 0;
560
+ } else if (messageColumns <= room) {
561
+ text = view.message;
562
+ } else if (reasonRoom >= UPDATE_REASON_MIN_COLUMNS) {
563
+ text = truncateToDisplayWidth(view.message, room);
564
+ } else if (displayWidth(short) + hintColumns <= room) {
565
+ text = short;
566
+ showHint = hintColumns > 0;
567
+ } else if (room >= UPDATE_ERROR_MIN_COLUMNS) {
568
+ text = truncateToDisplayWidth(short, room);
569
+ } else {
570
+ return null;
571
+ }
572
+ return <TerminalFailedStatus text={text} hint={showHint ? hint : ""} />;
492
573
  }
493
- return <Text fg={colors.headerText}>{view.text}</Text>;
574
+ // A notice or a line about the update: cut to the slot, never past it.
575
+ if (room < UPDATE_TEXT_MIN_COLUMNS) return null;
576
+ return <TerminalTextStatus text={view.text} width={room} />;
577
+ }
578
+
579
+ /**
580
+ * A status line in `width` columns: the pieces that stay whole (a download's
581
+ * percent) keep their room, and the rest is cut to what they leave.
582
+ */
583
+ function fitStatusParts(parts: StatusPart[], width: number): string {
584
+ const whole = parts.reduce((total, part) => total + (part.cut ? 0 : displayWidth(part.text)), 0);
585
+ const cutRoom = Math.max(0, width - whole);
586
+ const cutTotal = parts.reduce((total, part) => total + (part.cut ? displayWidth(part.text) : 0), 0);
587
+ if (cutTotal <= cutRoom) return parts.map((part) => part.text).join("");
588
+ // A cut piece keeps a space before the whole one after it: "Downloading v... 42%".
589
+ const cut = (part: StatusPart, index: number) => index < parts.length - 1
590
+ ? `${truncateToDisplayWidth(part.text.trimEnd(), Math.max(0, cutRoom - 1))} `
591
+ : truncateToDisplayWidth(part.text, cutRoom);
592
+ return truncateToDisplayWidth(parts.map((part, index) => (part.cut ? cut(part, index) : part.text)).join(""), width);
593
+ }
594
+
595
+ function TerminalBusyStatus({ text }: { text: string }) {
596
+ const colors = useThemeColors();
597
+ return (
598
+ <Box flexDirection="row" gap={1}>
599
+ <SpinnerMark name="dots" color={colors.headerText} />
600
+ <Text fg={colors.headerText}>{text}</Text>
601
+ </Box>
602
+ );
603
+ }
604
+
605
+ function TerminalRestartStatus({ onRestart, text, updateKey }: { onRestart?: () => void; text: string | null; updateKey: string }) {
606
+ const colors = useThemeColors();
607
+ return (
608
+ <Box flexDirection="row" gap={1} alignItems="center">
609
+ {text ? <Text fg={colors.headerText}>{text}</Text> : null}
610
+ <Button compact label="Restart" shortcut={updateKey || undefined} onPress={onRestart} stopPropagation />
611
+ </Box>
612
+ );
613
+ }
614
+
615
+ function TerminalFailedStatus({ hint, text }: { hint: string; text: string }) {
616
+ const colors = useThemeColors();
617
+ return (
618
+ <>
619
+ <Text fg={colors.headerText}>{text}</Text>
620
+ {hint ? <Text fg={blendHex(colors.headerText, colors.header, 0.62)}>{hint}</Text> : null}
621
+ </>
622
+ );
623
+ }
624
+
625
+ function TerminalTextStatus({ text, width }: { text: string; width: number }) {
626
+ const colors = useThemeColors();
627
+ return <ClippedText fg={colors.headerText} text={text} width={width} />;
494
628
  }
495
629
 
496
630
  /**
@@ -510,6 +644,23 @@ function nativeCutTextStyle(alone: boolean) {
510
644
  maxWidth: "max-content",
511
645
  } as const;
512
646
  }
647
+ /**
648
+ * A failed update's reason on the desktop: whole when the line has room for it,
649
+ * so the retry key after it moves to the hidden line first; never wider than
650
+ * what the words before it leave, so when even that is too little it stays on
651
+ * the line and ends in an ellipsis instead of leaving with the key.
652
+ */
653
+ function nativeReasonStyle(leadColumns: number) {
654
+ return {
655
+ ...NATIVE_CLIP_STYLE,
656
+ flexGrow: 0,
657
+ flexShrink: 1,
658
+ flexBasis: "auto",
659
+ minWidth: `${NATIVE_STATUS_PIECE_MIN_CH}ch`,
660
+ maxWidth: `calc(100% - ${leadColumns}ch)`,
661
+ } as const;
662
+ }
663
+
513
664
  /** One cell between the parts of the desktop status, as `gap={1}` puts it in the terminal. */
514
665
  const NATIVE_STATUS_GAP = "var(--cell-w)";
515
666
 
@@ -597,12 +748,16 @@ function NativeUpdateStatus({ onRestart, trailingGap, updateKey, view }: {
597
748
  );
598
749
  }
599
750
  if (view.kind === "failed") {
600
- // The words that say it failed, then as much of the error as reads, then the retry key.
601
- const hint = updateKey && view.retry ? ` ${updateKey} ${t("retry")}` : "";
602
- const alone = view.parts.every((part) => part.cut);
751
+ // The words that say it failed, then the reason, then the retry key, which
752
+ // gives way first, as in the terminal: the reason is cut only once the key
753
+ // is gone and it still does not fit (nativeReasonStyle).
754
+ const hint = retryHint(view, updateKey);
755
+ const lead = view.parts.reduce((total, part) => total + (part.cut ? 0 : displayWidth(part.text)), 0);
603
756
  return (
604
757
  <NativeStatusRow trailingGap={trailingGap}>
605
- {view.parts.map((part, index) => nativeStatusPiece(part, index, { alone, color, title: view.message }))}
758
+ {view.parts.map((part, index) => part.cut
759
+ ? <Text key={index} fg={color} title={view.message} style={nativeReasonStyle(lead)}>{part.text}</Text>
760
+ : nativeStatusPiece(part, index, { alone: false, color, title: view.message }))}
606
761
  {hint ? <Text fg={colors.textMuted}>{hint}</Text> : null}
607
762
  </NativeStatusRow>
608
763
  );
@@ -625,7 +780,7 @@ function HeaderMarketSummary({ nativePaneChrome, width }: { nativePaneChrome: bo
625
780
  const summary = useMarketSummary();
626
781
  const fit = resolveMarketSummaryFit({
627
782
  available: width,
628
- baseCurrencyWidth: summary.baseCurrency.length + 1,
783
+ baseCurrencyWidth: displayWidth(summary.baseCurrencyLabel) + 1,
629
784
  countdownWidth: summary.marketLabel.length - summary.marketLabelShort.length,
630
785
  spyWidth: summary.spyText.length + 1,
631
786
  stateWidth: summary.marketLabelShort ? summary.marketLabelShort.length + 1 : 0,
@@ -635,20 +790,20 @@ function HeaderMarketSummary({ nativePaneChrome, width }: { nativePaneChrome: bo
635
790
  return (
636
791
  <>
637
792
  {fit.showState && marketLabel ? (
638
- <Box paddingRight={1} flexShrink={0}>
793
+ <Box paddingRight={1} flexShrink={0} data-gloom-role="header-market">
639
794
  <Text fg={summary.marketColor} {...(nativePaneChrome ? { attributes: TextAttributes.BOLD } : {})}>
640
795
  {marketLabel}
641
796
  </Text>
642
797
  </Box>
643
798
  ) : null}
644
799
  {fit.showSpy ? (
645
- <Box paddingRight={1} flexShrink={0}>
800
+ <Box paddingRight={1} flexShrink={0} data-gloom-role="header-market">
646
801
  <Text fg={summary.spyColor}>{summary.spyText}</Text>
647
802
  </Box>
648
803
  ) : null}
649
804
  {fit.showBaseCurrency ? (
650
805
  <Box paddingRight={1} flexShrink={0}>
651
- <Text fg={nativePaneChrome ? colors.textDim : blendHex(colors.headerText, colors.header, 0.42)}>{summary.baseCurrency}</Text>
806
+ <Text fg={nativePaneChrome ? colors.textDim : blendHex(colors.headerText, colors.header, 0.42)}>{summary.baseCurrencyLabel}</Text>
652
807
  </Box>
653
808
  ) : null}
654
809
  </>
@@ -690,22 +845,41 @@ export function Header({
690
845
  const { nativePaneChrome = false, titleBarOverlay, nativeWindowChrome = titleBarOverlay, windowControls } = useUiCapabilities();
691
846
  const showWindowControls = nativeWindowChrome && windowControls === "windows";
692
847
  const windowFullscreen = useWindowFullscreen();
848
+ const updateStatus = useUpdateStatus(!!onRestartForUpdate);
693
849
  const prompt = resolveHeaderPromptGeometry({
694
850
  nativePaneChrome,
695
851
  nativeWindowChrome,
696
852
  termWidth,
697
853
  titleBarOverlay,
698
854
  windowFullscreen,
855
+ allowMarketExpansion: !updateStatus.view,
699
856
  });
700
857
  const shortcutLabel = useCommandBarShortcut();
701
858
  // The terminal lays the header out by cell counts, so it works out what is left
702
859
  // for the update status once the Help pill and the slot's padding are paid for.
703
- const updateStatusColumns = Math.max(
860
+ let updateStatusColumns = Math.max(
704
861
  0,
705
862
  prompt.updateColumns
706
863
  - (onOpenHelp ? terminalButtonColumns(helpButtonProps()) + TERMINAL_HELP_PADDING_COLUMNS : 0)
707
864
  - UPDATE_SLOT_PADDING_COLUMNS * (titleBarOverlay ? 2 : 1),
708
865
  );
866
+ // Short of that, the closed prompt gives the status its empty room, down to
867
+ // its placeholder, as the desktop's does: at 80 to 160 columns the slot alone
868
+ // is too narrow to say anything. Open, the prompt is the command bar's input
869
+ // and keeps its width.
870
+ // The prompt's own right padding then stands for one of the slot's.
871
+ let promptWidth = prompt.width;
872
+ let terminalSlotPadding = UPDATE_SLOT_PADDING_COLUMNS;
873
+ if (!nativePaneChrome && !commandBarOpen && updateStatus.view) {
874
+ const need = terminalUpdateStatusColumns(updateStatus.view, updateStatus.updateKey);
875
+ if (need > updateStatusColumns) {
876
+ const spare = Math.max(0, prompt.width - terminalClosedPromptFloor());
877
+ const given = Math.min(need - updateStatusColumns - 1, spare);
878
+ promptWidth -= Math.max(0, given);
879
+ terminalSlotPadding -= 1;
880
+ updateStatusColumns += 1 + Math.max(0, given);
881
+ }
882
+ }
709
883
  // Desktop has its own window chrome to sit on; the terminal has none, so the
710
884
  // bar itself wears the prompt's fill and reads as a single strip.
711
885
  const headerBg = nativePaneChrome ? colors.header : headerSurface(colors);
@@ -727,7 +901,7 @@ export function Header({
727
901
  onOpen={openCommandBar}
728
902
  open={commandBarOpen}
729
903
  shortcutLabel={shortcutLabel}
730
- width={prompt.width}
904
+ width={promptWidth}
731
905
  />
732
906
  );
733
907
  const marketSummary = prompt.marketColumns > 0
@@ -748,7 +922,7 @@ export function Header({
748
922
  data-gloom-role="header-update-status"
749
923
  style={{ alignSelf: "stretch" }}
750
924
  >
751
- <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} trailingGap={!!titleBarOverlay} />
925
+ <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} status={updateStatus} trailingGap={!!titleBarOverlay} />
752
926
  </Box>
753
927
  ) : null;
754
928
 
@@ -771,8 +945,8 @@ export function Header({
771
945
  <Box width={prompt.left} />
772
946
  {commandPrompt}
773
947
  {nativeUpdateSlot ?? (
774
- <Box flexGrow={1} paddingLeft={UPDATE_SLOT_PADDING_COLUMNS} paddingRight={UPDATE_SLOT_PADDING_COLUMNS} minWidth={0}>
775
- <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} />
948
+ <Box flexGrow={1} paddingLeft={terminalSlotPadding} paddingRight={UPDATE_SLOT_PADDING_COLUMNS} minWidth={0}>
949
+ <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} status={updateStatus} />
776
950
  </Box>
777
951
  )}
778
952
  {onOpenHelp ? <HeaderHelpButton nativePaneChrome onPress={onOpenHelp} /> : null}
@@ -795,8 +969,8 @@ export function Header({
795
969
  <Box width={prompt.left} />
796
970
  {commandPrompt}
797
971
  {nativeUpdateSlot ?? (
798
- <Box flexGrow={1} minWidth={0} paddingLeft={UPDATE_SLOT_PADDING_COLUMNS}>
799
- <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} />
972
+ <Box flexGrow={1} minWidth={0} paddingLeft={terminalSlotPadding}>
973
+ <UpdateStatus columns={updateStatusColumns} onRestart={onRestartForUpdate} status={updateStatus} />
800
974
  </Box>
801
975
  )}
802
976
  {onOpenHelp ? <HeaderHelpButton nativePaneChrome={nativePaneChrome} onPress={onOpenHelp} /> : null}
@@ -4,12 +4,12 @@ import { useThemeColors } from "../../theme/theme-context";
4
4
  import { useAppVisible } from "../../state/app/activity";
5
5
  import { useAppSelector } from "../../state/app/context";
6
6
  import { getSharedMarketDataCoordinator } from "../../market-data/coordinator";
7
- import { t } from "../../i18n";
7
+ import { t, tf } from "../../i18n";
8
8
  import { useQuoteEntry, useResolvedEntryValue } from "../../market-data/hooks";
9
9
  import { useQuoteStreaming } from "../../state/hooks/quote-streaming";
10
10
  import type { QuoteSubscriptionTarget } from "../../types/data-provider";
11
11
  import { formatPercentRaw } from "../../utils/format";
12
- import { formatMarketPrice, liveQuoteFormatOptions } from "../../market-data/market/format";
12
+ import { formatMarketPriceWithCurrency, liveQuoteFormatOptions } from "../../market-data/market/format";
13
13
  import { getSessionMoveDisplay, marketStateColor, marketStateCountdown, marketStateLabel } from "../../market-data/market/status";
14
14
  import type { Quote } from "../../types/financials";
15
15
 
@@ -33,7 +33,8 @@ const SPY_STREAM_TARGETS: QuoteSubscriptionTarget[] = [{
33
33
  }];
34
34
 
35
35
  export interface MarketSummary {
36
- baseCurrency: string;
36
+ /** The base currency under its own label (base THB), so it never reads as the unit of SPY's price beside it. */
37
+ baseCurrencyLabel: string;
37
38
  marketColor: string;
38
39
  /** Market state with its countdown, when the state has one. */
39
40
  marketLabel: string;
@@ -83,6 +84,8 @@ export function resolveMarketSummaryFit(options: {
83
84
  * it, as `ticker SPY` headlines them. While a pre-market or after-hours
84
85
  * session is open (PRE-MKT, AFTER-HRS) the slot is that session's print and
85
86
  * its move from the close, so the figure is the session the label names.
87
+ * The price carries its currency's sign ($), so the base currency label
88
+ * after it is never read as its unit.
86
89
  */
87
90
  export function spySummary(quote: Quote | null | undefined, colors: ThemeColors): Pick<MarketSummary, "spyColor" | "spyText"> {
88
91
  const display = getSessionMoveDisplay(quote);
@@ -91,7 +94,7 @@ export function spySummary(quote: Quote | null | undefined, colors: ThemeColors)
91
94
  return {
92
95
  spyColor: display?.change != null ? priceColor(display.change, colors) : colors.textDim,
93
96
  spyText: display
94
- ? `SPY ${formatMarketPrice(display.price, liveQuoteFormatOptions(quote, quote?.currency, "ETF"))} ${formatPercentRaw(display.changePercent).padStart(6)}`
97
+ ? `SPY ${formatMarketPriceWithCurrency(display.price, quote?.currency || "USD", liveQuoteFormatOptions(quote, quote?.currency, "ETF"))} ${formatPercentRaw(display.changePercent).padStart(6)}`
95
98
  : "SPY —",
96
99
  };
97
100
  }
@@ -137,11 +140,11 @@ export function useMarketSummary(): MarketSummary {
137
140
  const mktCountdown = mktState ? marketStateCountdown(mktState, now) : null;
138
141
  const marketLabelShort = mktState ? t(marketStateLabel(mktState)) : "";
139
142
  const marketLabel = marketLabelShort && mktCountdown
140
- ? `${marketLabelShort} · ${mktCountdown}`
143
+ ? `${marketLabelShort} · ${mktCountdown}${mktState === "PRE" ? ` ${t("to regular open")}` : ""}`
141
144
  : marketLabelShort;
142
145
 
143
146
  return {
144
- baseCurrency,
147
+ baseCurrencyLabel: tf("base {currency}", { currency: baseCurrency }),
145
148
  marketColor: mktState ? marketStateColor(mktState, colors) : colors.textDim,
146
149
  marketLabel,
147
150
  marketLabelShort,
@@ -1,7 +1,7 @@
1
1
  import { createContext, useContext } from "react";
2
2
 
3
3
  /**
4
- * True inside a `gloomberb shot` whose status line dates the pane's data: the
4
+ * True inside a `gloom shot` whose status line dates the pane's data: the
5
5
  * pane's own `as of` text (a query bar's `asOf`) is left out, so the date is
6
6
  * said once. False everywhere else.
7
7
  */
@@ -38,7 +38,7 @@ export interface PaneFooterSegment {
38
38
  asOf?: boolean;
39
39
  /**
40
40
  * The segment only says how current the pane's quotes are (`2026-10-09 ·
41
- * 15m delayed`), which a `gloomberb shot` status line says too: a shot whose
41
+ * 15m delayed`), which a `gloom shot` status line says too: a shot whose
42
42
  * line states its data's date and delay leaves it out.
43
43
  */
44
44
  quoteStatus?: boolean;
@@ -165,7 +165,12 @@ export interface CombinedPaneFooter {
165
165
 
166
166
  export const EMPTY_FOOTER: CombinedPaneFooter = { info: [], hints: [], menu: [], keys: [] };
167
167
 
168
- /** Status the hints leave room for, more when it is a warning: a failure must stay readable. */
168
+ /**
169
+ * Status the hints leave room for, more when it is a warning: a failure must
170
+ * stay readable. A status no longer than the warning's room is kept whole,
171
+ * with the hints that no longer fit under More, so a status word is never cut
172
+ * against them ("Cloud sync d [a]dd event"); a longer one gives way to the hints.
173
+ */
169
174
  const INFO_FLOOR_CHARS = 10;
170
175
  const WARNING_FLOOR_CHARS = 24;
171
176
  const HINT_GAP = 1;
@@ -264,9 +269,10 @@ export function layoutPaneFooterHintRow(
264
269
  const width = Math.max(0, Math.floor(contentWidth));
265
270
  const hints = footer.hints.filter((hint) => !hint.disabled);
266
271
  const warning = footer.info.some((segment) => segment.parts.some((part) => part.tone === "warning" || part.tone === "negative"));
267
- const textFloor = footer.info.length > 0
268
- ? Math.min(warning ? WARNING_FLOOR_CHARS : INFO_FLOOR_CHARS, infoTextWidth(footer.info))
269
- : 0;
272
+ const infoChars = infoTextWidth(footer.info);
273
+ const textFloor = footer.info.length === 0 ? 0
274
+ : warning || infoChars <= WARNING_FLOOR_CHARS ? Math.min(WARNING_FLOOR_CHARS, infoChars)
275
+ : INFO_FLOOR_CHARS;
270
276
  const infoFloor = Math.min(width, Math.max(iconReserve, textFloor));
271
277
  const hintBudget = Math.max(0, width - infoFloor - (infoFloor > 0 && hints.length > 0 ? 1 : 0));
272
278
  const more = moreControl(hintBudget);
@@ -10,7 +10,6 @@ import type { PaneHeaderTabsRegistration } from "./header-tabs";
10
10
  import { nativePaneHeaderRows } from "./sizing";
11
11
 
12
12
  const PANE_HEADER_HEIGHT = 1;
13
- /** Space above desktop title-bar tabs, in px. */
14
13
  const PANE_HEADER_GRIP = ":: ";
15
14
  export const PANE_HEADER_ACTION = " ... ";
16
15
  /** The pane's docs: the same width shown or blank, so the title never shifts. */
@@ -38,6 +37,8 @@ interface PaneHeaderProps {
38
37
  quickSettings?: PaneHeaderQuickSetting[];
39
38
  /** Desktop only: the pane's primary tab strip, drawn as title-bar tabs. */
40
39
  tabs?: PaneHeaderTabsRegistration | null;
40
+ /** The body colour the active title-bar tab opens into. */
41
+ bodyBackground?: string;
41
42
  /**
42
43
  * Desktop: a 1px line is drawn over the header's first row (a dock divider
43
44
  * above it, or a floating pane's border). The header mirrors it with padding
@@ -131,6 +132,7 @@ export function PaneHeader({
131
132
  showActions = false,
132
133
  quickSettings = [],
133
134
  tabs = null,
135
+ bodyBackground,
134
136
  topRule = false,
135
137
  titleBar = null,
136
138
  onHeaderMouseMove,
@@ -262,9 +264,14 @@ export function PaneHeader({
262
264
  marginTop: -topInset,
263
265
  marginBottom: -1,
264
266
  marginLeft: "var(--gloom-space-sm)",
265
- // Undoes the negative top margin for controls centred in the
266
- // strip (the overflow chevron).
267
+ // Undoes the negative top margin for what is centred in the strip:
268
+ // the overflow chevron, and the tab labels (styles.css).
267
269
  "--pane-tab-top-inset": `${topInset}px`,
270
+ // The active tab's box opens into the pane over the bottom rule
271
+ // (styles.css), drawn in the rule's colour so the two are one line.
272
+ "--pane-tab-border": ruleColor,
273
+ // Until the strip has measured the surface under the tab (top-surface.ts).
274
+ "--pane-tab-active-bg": bodyBackground ?? colors.bg,
268
275
  // The active tab reads as active whenever the pane is focused, even
269
276
  // while a detail or field inside the pane owns the keyboard.
270
277
  "--pane-tab-active-fg": visuallyFocused ? colors.textBright : colors.text,
@@ -119,6 +119,7 @@ export function PaneWrapper({
119
119
  showActions={showActions}
120
120
  quickSettings={quickSettings}
121
121
  tabs={headerTabs}
122
+ bodyBackground={bg}
122
123
  topRule={topRule}
123
124
  onHeaderMouseMove={onHeaderMouseMove}
124
125
  onHeaderMouseDown={onHeaderMouseDown}
@@ -25,7 +25,15 @@ export interface PaneTabs {
25
25
  * A pane's primary tab strip in one call. It registers the strip with the
26
26
  * chrome, which draws it in the desktop title bar, and otherwise returns the
27
27
  * row the body draws first, so the tabs are described once. Call it above any
28
- * early return, and pass null while the pane has no strip (a sign-in wall).
28
+ * early return, and draw `strip` above every body state, loading and error
29
+ * included.
30
+ *
31
+ * The strip is chrome: it is there from the first frame and stays while a tab,
32
+ * a filter or a refresh loads, fails or comes back empty, so switching never
33
+ * takes it away. Pass null only while there is nothing to choose between: a
34
+ * sign-in or plan wall, no ticker or portfolio yet, a detail that replaces the
35
+ * tabs by design. A conditional call is listed with its reason in
36
+ * `src/architecture/pane-tabs-allowlist.json`.
29
37
  */
30
38
  export function usePaneTabs(options: PaneTabsOptions | null): PaneTabs {
31
39
  const inHeader = usePaneHeaderTabs(options);