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
@@ -5,9 +5,10 @@ import { isAccessDenied } from "../../../api-client/errors";
5
5
  import { usePlanAccess } from "../../../api-client/plan-access";
6
6
  import type { SupplyChainPayload, SupplyOptions, SupplyRole, SupplyRow, SupplyTierFilter } from "../../../api-client/supply-chain";
7
7
  import {
8
- Badge, buildSectionedRows, DataTableView, EmptyState, isSectionedItemRow, PageStackView, renderSectionedRowHeader, PaneStatusBody, QueryBar, StatGrid, statGridRows, usePaneNoticeFooter,
9
- usePaneStatusFooter, usePaneTabs, type DataTableCell, type DataTableColumn, type PaneHint, type SectionedRow, type StatItem,
8
+ Badge, buildSectionedRows, ChartTableHeader, DataTableView, EmptyState, formatPercentAxis, isSectionedItemRow, PageStackView, renderSectionedRowHeader, PaneStatusBody, QueryBar, StatGrid,
9
+ statGridRows, useChartTableSelection, usePaneNoticeFooter, usePaneStatusFooter, usePaneTabs, type DataTableCell, type DataTableColumn, type PaneHint, type SectionedRow, type StatItem,
10
10
  } from "../../../components";
11
+ import { staticSeries } from "../../../components/chart/static/series";
11
12
  import { ClippedText } from "../../../components/ui/display";
12
13
  import { RatioBar } from "../../../components/ui/ratio-bar";
13
14
  import { getTableWidth } from "../../../components/ui/table-layout";
@@ -30,7 +31,7 @@ import { SupplyFlow } from "./flow";
30
31
  import { SupplyGraphPane } from "./graph-pane";
31
32
  import { entityTicker } from "./graph-model";
32
33
  import {
33
- cellText, counterpartyKind, counterpartyKindLabel, counterpartyLabel, counterpartyName, disclosedValue, earlierRows, lockedDisclosures, nativeValue, percentage, ROLE_COLORS, roleLabel,
34
+ cellText, counterpartyKind, counterpartyKindLabel, counterpartyLabel, counterpartyName, disclosedValue, earlierRows, fitShareBasis, receivablesConcentration, lockedDisclosures, nativeValue, percentage, ROLE_COLORS, roleLabel,
34
35
  shareParts, sortRows, supplyPreviewNote, supplyRoleCounts, type SupplySort,
35
36
  } from "./model";
36
37
  import { RowEvidence } from "./row-evidence";
@@ -38,37 +39,58 @@ import { evidenceDate, evidenceLabel, isUnconfirmed, matchesSupplyOptions, suppl
38
39
 
39
40
  type Item = { kind: "edge"; row: SupplyRow } | { kind: "locked"; id: string };
40
41
  const itemId = (item: Item) => item.kind === "edge" ? item.row.id : item.id;
42
+ const rowId = (row: SupplyRow) => row.id;
43
+ const formatShare = (value: number) => `${Number(value.toFixed(2))}%`;
41
44
  const ROLE_PLURALS: Record<SupplyRole, string> = { customer: "Customers", supplier: "Suppliers", partner: "Partners", competitor: "Competitors", investee: "Investees" };
42
45
  /** A share figure is at most five cells (`99.9%`, `100%`), right-aligned so the bars line up. */
43
46
  const SHARE_FIGURE_CELLS = 5;
44
- /** Bar, gap and figure: below this a share cell shows the figure alone. */
47
+ /** Bar, gap and figure: the least a share cell draws with its bar. */
45
48
  const SHARE_BAR_MIN_CELLS = 3 + 1 + SHARE_FIGURE_CELLS;
49
+ /** Cells a column keeps for the bare basis of the longest row (`cost of sales`); a longer one is cut by an ellipsis. */
50
+ const SHARE_BASIS_FLOOR_CELLS = 13;
51
+ /** Cells of basis kept in the last resort: three letters and an ellipsis. */
52
+ const SHARE_BASIS_LAST_CELLS = 4;
53
+
54
+ /** Every row's basis as the cells of each form, whole wording first: what a share column is laid out by. */
55
+ type BasisForms = readonly (readonly number[])[];
56
+
57
+ /** Cells a row's basis keeps in `room`: its longest whole form that fits, else as much of its bare form as the floor allows. */
58
+ const keptBasis = (forms: readonly number[], room: number) => forms.find((cells) => cells <= room) ?? Math.min(room, SHARE_BASIS_FLOOR_CELLS);
59
+ /** The cells the narrowest column keeps for the longest bare basis. */
60
+ const bareBasis = (bases: BasisForms) => Math.min(SHARE_BASIS_FLOOR_CELLS, Math.max(0, ...bases.map((forms) => forms[forms.length - 1]!)));
61
+
62
+ /** Cells of a share column's bar and of its basis; no bar leaves the figure beside its basis. */
63
+ interface ShareLayout { bar: number; basis: number }
46
64
 
47
65
  /**
48
- * Cells of a share column's bar: as long as the column allows after the figure
49
- * and the longest basis that fits, between 3 and 8 cells, and the same on every
50
- * row so the bars and figures line up. Zero leaves the figure alone.
66
+ * The bar and the basis of a share column, the same on every row so the bars
67
+ * and figures line up. A share keeps what it is a share of: the column gives
68
+ * up the bar, then the whole wording, before it gives up the basis. The bar
69
+ * takes what the longest basis leaves, between 3 and 8 cells.
51
70
  */
52
- function shareBarCells(width: number, bases: readonly number[]): number {
53
- if (width < SHARE_BAR_MIN_CELLS) return 0;
54
- // Room for the longest basis that can show at all; a longer one gives way, not every bar.
55
- const basis = longestBasis(bases, width);
56
- return Math.min(width >= 36 ? 8 : 5, Math.max(3, width - SHARE_FIGURE_CELLS - 2 - basis));
71
+ function shareLayout(width: number, bases: BasisForms): ShareLayout {
72
+ const beside = width - SHARE_BAR_MIN_CELLS - 1;
73
+ if (beside >= bareBasis(bases)) {
74
+ const longest = Math.max(0, ...bases.map((forms) => keptBasis(forms, beside)));
75
+ const bar = Math.min(width >= 36 ? 8 : 5, Math.max(3, width - SHARE_FIGURE_CELLS - 2 - longest));
76
+ return { bar, basis: width - bar - SHARE_FIGURE_CELLS - 2 };
77
+ }
78
+ return { bar: 0, basis: Math.max(0, width - SHARE_FIGURE_CELLS - 1) };
57
79
  }
58
- const longestBasis = (bases: readonly number[], width: number) => Math.max(0, ...bases.filter((cells) => SHARE_BAR_MIN_CELLS + 1 + cells <= width));
59
80
 
60
81
  /** A period end date; its length, when the source states it, follows it in a wider column. */
61
82
  const PERIOD_DATE_CELLS = 10;
62
83
  /**
63
84
  * Columns that fit the pane, giving up the least first: the share bar shortens
64
85
  * to keep the whole basis, the name shortens to 18 cells, the ticker folds into
65
- * the name and the period is left to the evidence view; then the share drops
66
- * its basis and its bar, and the name shortens further. Only a pane narrower
67
- * than that scrolls sideways, so the pane edge never cuts a share in half.
86
+ * the name and the period is left to the evidence view; then the share gives
87
+ * its bar, then its whole wording for the bare basis, and the name shortens
88
+ * further. A share never loses its basis. Only a pane narrower than that
89
+ * scrolls sideways, so the pane edge never cuts a share in half.
68
90
  * Value shows only when some row discloses a value, retaining its original
69
91
  * currency and units.
70
92
  */
71
- function tableColumns(width: number, desktop: boolean, locked: boolean, valueWidth: number | null, bases: readonly number[], periodWidth = PERIOD_DATE_CELLS): DataTableColumn[] {
93
+ function tableColumns(width: number, desktop: boolean, locked: boolean, valueWidth: number | null, bases: BasisForms, periodWidth = PERIOD_DATE_CELLS): DataTableColumn[] {
72
94
  const wide = width >= 150, medium = width >= 110;
73
95
  const name: DataTableColumn = { id: "name", label: "Counterparty", width: Math.max(locked && !desktop ? 34 : 0, wide ? 30 : medium ? 26 : 20), flexGrow: 1, align: "left" };
74
96
  const share: DataTableColumn = { id: "pct", label: "Share", width: wide ? 34 : medium ? 30 : 26, align: "left" };
@@ -89,8 +111,11 @@ function tableColumns(width: number, desktop: boolean, locked: boolean, valueWid
89
111
  const preferred = { share: share.width, name: name.width };
90
112
  // The table ignores its last trailing gutter when deciding whether it fits.
91
113
  const overflow = () => getTableWidth(columns) - width - 1;
92
- // Native units keep their column before the share keeps its bar or basis.
93
- const shareFloor = valueWidth !== null ? SHARE_BAR_MIN_CELLS + 1 : SHARE_BAR_MIN_CELLS + 1 + longestBasis(bases, preferred.share);
114
+ // Native units keep their column before the share keeps its bar or its whole wording.
115
+ const withBar = SHARE_BAR_MIN_CELLS + 1;
116
+ const plain = SHARE_FIGURE_CELLS + 1;
117
+ const bare = bareBasis(bases);
118
+ const shareFloor = withBar + (valueWidth !== null ? bare : Math.max(bare, ...bases.map((forms) => keptBasis(forms, preferred.share - withBar))));
94
119
  const fit = (shareMin: number, nameMin = 18) => {
95
120
  share.width = preferred.share; name.width = preferred.name;
96
121
  share.width = Math.max(shareMin, share.width - Math.max(0, overflow()));
@@ -103,9 +128,12 @@ function tableColumns(width: number, desktop: boolean, locked: boolean, valueWid
103
128
  columns = columns.filter((column) => column.id !== id);
104
129
  fit(shareFloor);
105
130
  }
106
- // The narrowest panes keep the figure alone, then a shorter name, before anything scrolls.
107
- if (overflow() > 0) fit(SHARE_BAR_MIN_CELLS);
108
- if (overflow() > 0) fit(SHARE_FIGURE_CELLS + 2, 12);
131
+ // The narrowest panes keep the figure and the bare basis, then a shorter name and a cut basis, before anything scrolls.
132
+ const shares = bases.length > 0;
133
+ if (overflow() > 0) fit(withBar + bare);
134
+ if (overflow() > 0 && shares) fit(plain + bare);
135
+ if (overflow() > 0) fit(shares ? plain + bare : SHARE_FIGURE_CELLS + 2, 12);
136
+ if (overflow() > 0 && shares) fit(plain + SHARE_BASIS_LAST_CELLS, 12);
109
137
  return columns;
110
138
  }
111
139
 
@@ -123,20 +151,20 @@ function supplyFigures(data: SupplyChainPayload, views: readonly ("says" | "name
123
151
 
124
152
  /**
125
153
  * The share as a bar on a 0 to 100% scale, the figure, and what it is a share
126
- * of. The basis shows whole or not at all: a column too narrow for it keeps
127
- * the bar and figure, and the evidence view says the rest.
154
+ * of. The basis never goes: a column too narrow for the whole wording shows a
155
+ * shorter form of it, then drops the bar, then cuts it behind an ellipsis.
156
+ * The evidence view and the selected row's line say it whole.
128
157
  */
129
- function ShareCell({ row, focusId, width, bases, selected }: { row: SupplyRow; focusId?: string; width: number; bases: readonly number[]; selected: boolean }) {
158
+ function ShareCell({ row, focusId, width, layout, selected }: { row: SupplyRow; focusId?: string; width: number; layout: ShareLayout; selected: boolean }) {
130
159
  const colors = useThemeColors();
131
160
  const share = shareParts(row, focusId);
132
161
  if (!share) return <Text fg={colors.textMuted}>{""}</Text>;
133
- const bar = shareBarCells(width, bases);
134
- if (!bar) return <Text fg={selected ? colors.selectedText : colors.textBright} attributes={TextAttributes.BOLD}>{share.value}</Text>;
135
- const basis = bar + SHARE_FIGURE_CELLS + 2 + displayWidth(share.basis) <= width;
162
+ const ink = selected ? colors.selectedText : colors.textBright;
163
+ const basis = fitShareBasis(share, layout.basis);
136
164
  return <Box flexDirection="row" width={width} height={1} gap={1} overflow="hidden">
137
- <RatioBar ratio={row.pctOfRevenue! / 100} width={bar} color={ROLE_COLORS[row.role]} track />
138
- <Text fg={selected ? colors.selectedText : colors.textBright} attributes={TextAttributes.BOLD}>{share.value.padStart(SHARE_FIGURE_CELLS)}</Text>
139
- {basis ? <Text fg={selected ? colors.selectedText : colors.textDim}>{share.basis}</Text> : null}
165
+ {layout.bar ? <RatioBar ratio={row.pctOfRevenue! / 100} width={layout.bar} color={ROLE_COLORS[row.role]} track /> : null}
166
+ <Text fg={ink} attributes={TextAttributes.BOLD}>{share.value.padStart(SHARE_FIGURE_CELLS)}</Text>
167
+ {basis ? <Text fg={selected ? colors.selectedText : colors.textDim}>{basis}</Text> : null}
140
168
  </Box>;
141
169
  }
142
170
 
@@ -225,9 +253,18 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
225
253
  ...(savedTab === "flow" && tooSmall ? ["Flow needs a wider pane. Showing the table."] : []),
226
254
  ] });
227
255
  const focusId = data?.entity?.id;
256
+ // Over the table, how much of the receivables one customer holds at each period end the company disclosed.
257
+ const concentration = useMemo(() => tab === "table" && view === "says" ? receivablesConcentration(tableRows, focusId) : [], [tab, view, tableRows, focusId]);
258
+ const concentrationDates = useMemo(() => new Map(concentration.map((point) => [point.rowId, point.date])), [concentration]);
259
+ const getConcentrationDate = useCallback((row: SupplyRow) => concentrationDates.get(row.id) ?? null, [concentrationDates]);
260
+ const chartSelection = useChartTableSelection({ rows: tableRows, getId: rowId, getDate: getConcentrationDate,
261
+ selectedId: selected?.id ?? null, onSelect: setSelected, focused: focused && !openRow, enabled: concentration.length > 0 });
262
+ const concentrationSeries = useMemo(() => [{ ...staticSeries(concentration.map((point) => ({ date: point.date, observedAt: point.date, value: point.pct })),
263
+ { id: "receivables-concentration", label: "Largest disclosed customer · receivables", color: ROLE_COLORS.customer, calendarSpaced: true, style: "points" }), unit: "%", unitGroup: "percent" }], [concentration]);
264
+ const concentrationChart = concentration.length ? { series: concentrationSeries, formatValue: formatShare, formatAxisValue: formatPercentAxis, strip: null, ...chartSelection } : null;
228
265
  const values = tableRows.filter((row) => nativeValue(row) !== null || row.usd !== null);
229
266
  const valueWidth = values.length ? Math.min(28, Math.max(...values.map((row) => displayWidth(disclosedValue(row).replace(/ (disclosed|derived)$/, ""))))) : null;
230
- const bases = tableRows.flatMap((row) => { const share = shareParts(row, focusId); return share ? [displayWidth(share.basis)] : []; });
267
+ const bases: BasisForms = tableRows.flatMap((row) => { const share = shareParts(row, focusId); return share ? [share.forms.map(displayWidth)] : []; });
231
268
  // The period's length follows its end date when the source states it (2026-07-31 half) and costs
232
269
  // no column; laid out a cell narrower, the table also clears its own scrollbar. Otherwise the
233
270
  // evidence view says it.
@@ -235,6 +272,7 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
235
272
  const dated = tableColumns(width, desktop, locked > 0, valueWidth, bases);
236
273
  const lengths = periodWidth > PERIOD_DATE_CELLS ? tableColumns(width - 1, desktop, locked > 0, valueWidth, bases, periodWidth) : null;
237
274
  const columns = lengths?.some((column) => column.id === "fy") && lengths.map((column) => column.id).join() === dated.map((column) => column.id).join() ? lengths : dated;
275
+ const shareColumn = shareLayout(columns.find((column) => column.id === "pct")?.width ?? 0, bases);
238
276
  const renderCell = (entry: SectionedRow<Item>, column: DataTableColumn, _index: number, state: { selected: boolean }): DataTableCell => {
239
277
  if (!isSectionedItemRow(entry)) return { text: "" };
240
278
  const item = entry.item;
@@ -278,7 +316,7 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
278
316
  <Text fg={ink ?? ROLE_COLORS[row.role]}>{` ${roleLabel(row.role)}`}</Text>
279
317
  </Box> };
280
318
  case "pct": return { text: percentage(row) === "--" ? "" : `${shareParts(row, focusId)?.value ?? ""} ${shareParts(row, focusId)?.basis ?? ""}`.trim(), value: row.pctOfRevenue,
281
- content: <ShareCell row={row} focusId={focusId} width={column.width} bases={bases} selected={state.selected} /> };
319
+ content: <ShareCell row={row} focusId={focusId} width={column.width} layout={shareColumn} selected={state.selected} /> };
282
320
  case "usd": return nativeValue(row) === null && row.usd === null ? { text: "", value: null }
283
321
  : { text: disclosedValue(row).replace(/ (disclosed|derived)$/, ""), value: row.nativeAmount != null ? row.nativeAmount * (row.nativeScale ?? 1) : row.usd, color: colors.text };
284
322
  case "fy": return { text: displayWidth(cellText(row, "fy")) <= column.width ? cellText(row, "fy") : row.period, color: colors.textDim };
@@ -291,12 +329,13 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
291
329
  const bodyHeight = Math.max(3, height - tabRows);
292
330
  const figures = data ? supplyFigures(data, tab === "flow" ? ["says", "names"] : [view], options) : [];
293
331
  const tierFilter = { id: "tiers", label: "Evidence", kind: "multi" as const, emptyLabel: "Primary", values: options.tiers, options: TIER_OPTIONS, onChange: (value: string[]) => { setTiers(supplyOptions(value).tiers); setSelected(null); setOpen(null); } };
294
- const header = <Box flexDirection="column" flexShrink={0}>
295
- <QueryBar width={width} filters={[{ id: "direction", label: "Direction", inline: true, value: view,
296
- options: [{ value: "says", label: `${symbol} says` }, { value: "names", label: `Names ${symbol}` }], onChange: (value: string) => { setView(value); setSelected(null); setOpen(null); } }, tierFilter]}
297
- meta={view === "names" ? "% of reporting company's basis" : undefined} />
298
- <StatGrid items={figures} width={width} />
299
- </Box>;
332
+ const query = <QueryBar width={width} filters={[{ id: "direction", label: "Direction", inline: true, value: view,
333
+ options: [{ value: "says", label: `${symbol} says` }, { value: "names", label: `Names ${symbol}` }], onChange: (value: string) => { setView(value); setSelected(null); setOpen(null); } }, tierFilter]}
334
+ meta={view === "names" ? "% of reporting company's basis" : undefined} />;
335
+ // Without a trend the figures keep every row they had; the chart layout shares the height with the table only when it draws.
336
+ const header = concentrationChart
337
+ ? <ChartTableHeader width={width} height={bodyHeight} tableRows={items.length} tableColumns={columns} figures={figures} chart={concentrationChart} query={query} />
338
+ : <Box flexDirection="column" flexShrink={0}>{query}<StatGrid items={figures} width={width} /></Box>;
300
339
  const flowFigureColumns = Math.min(Math.max(1, figures.length), Math.max(1, Math.floor(width / 24)));
301
340
  // A short flow keeps one row of figures, dropping the last roles, so the cards keep their room.
302
341
  const flowFigures = bodyHeight < 26 ? figures.slice(0, flowFigureColumns) : figures;
@@ -25,7 +25,7 @@ export function SupplyVerification({ row }: { row: SupplyRow }) {
25
25
  <KeyValueRow label="Corroboration" value={corroborationLabel(row)} labelWidth={20} />
26
26
  {row.pctScope ? <KeyValueRow label={row.sourceKind === "xbrl" ? "Tagged context" : "Percentage scope"} value={row.pctScope} labelWidth={20} /> : null}
27
27
  {row.sectionRef ? <KeyValueRow label="Section" value={row.sectionRef} labelWidth={20} /> : null}
28
- {row.jurisdiction ? <KeyValueRow label="Jurisdiction" value={row.jurisdiction} labelWidth={20} /> : null}
28
+ {row.jurisdiction ? <KeyValueRow label="Jurisdiction" value={row.jurisdiction} country={row.jurisdiction} labelWidth={20} /> : null}
29
29
  {row.firstSeenAt ? <KeyValueRow label="First seen" value={row.firstSeenAt.slice(0, 10)} detail={row.lastSeenAt ? `last seen ${row.lastSeenAt.slice(0, 10)}` : undefined} labelWidth={20} /> : null}
30
30
  {!isUnconfirmed(row) && row.lastConfirmedAt ? <KeyValueRow label="Last confirmed" value={row.lastConfirmedAt.slice(0, 10)} labelWidth={20} /> : null}
31
31
  </>;
@@ -5,7 +5,7 @@ import { formatRelativeAge } from "../../../utils/datetime-format";
5
5
  import { fetchThemeMembers, fetchThemes } from "./client";
6
6
  import {
7
7
  aggregateText, boardClose, boardYtdBase, DEFAULT_SORT, matchTheme, memberExtended, memberExtendedSessions, memberPrice, percent, periodLabel,
8
- SNAPSHOT_STALE_MS, sortMembers, sortThemes,
8
+ isLiveBoard, SNAPSHOT_STALE_MS, sortMembers, sortThemes,
9
9
  } from "./model";
10
10
 
11
11
  /** The period columns; YTD names the close it is measured from, `YTD vs 31 Dec close`. */
@@ -50,13 +50,15 @@ function boardObservation(payload: ThemesPayload | ThemeMembersPayload, now = Da
50
50
  regularSessionDate: close?.date ?? null,
51
51
  regularSessionClosedAt: close?.closedAt ?? null,
52
52
  };
53
+ // A Pro account's board is priced from the server's live read.
54
+ const feed = isLiveBoard(payload) ? { status: "live" as const } : {};
53
55
  if (close && now - assembledAt <= SNAPSHOT_STALE_MS) {
54
56
  return {
55
57
  metadata: { asOf: close.closedAt != null ? new Date(close.closedAt).toISOString() : close.date, sessionExchange: "NYSE", ...snapshot },
56
- freshness: { tradingDayMarket: "US", note: `snapshot ${formatRelativeAge(assembledAt, now)}` },
58
+ freshness: { ...feed, tradingDayMarket: "US", note: `snapshot ${formatRelativeAge(assembledAt, now)}` },
57
59
  };
58
60
  }
59
- return { metadata: { asOf: payload.asOf, ...snapshot }, freshness: { maxAgeMinutes: 30 } };
61
+ return { metadata: { asOf: payload.asOf, ...snapshot }, freshness: { ...feed, maxAgeMinutes: 30 } };
60
62
  }
61
63
 
62
64
  /**
@@ -74,14 +76,15 @@ function themeReportTitle(query: string | undefined, theme: Pick<ThemeSummary, "
74
76
 
75
77
  export const themesHeadless: HeadlessPaneDefinition<"rows"> = {
76
78
  shape: "rows",
77
- // The pane's stored snapshot: 15-minute delayed prices, refreshed every 15 minutes. As in the pane,
79
+ // The pane's stored snapshot, refreshed every 15 minutes, priced in real time for a Pro account and
80
+ // fifteen minutes delayed otherwise (boardObservation says which). As in the pane,
78
81
  // the payload's stale flags are historical; a snapshot over 30 minutes old is what reads stale
79
82
  // (boardObservation, which dates a board outside the regular session by its close).
80
83
  freshness: { status: "delayed", delayMinutes: 15, ignoreStaleFlags: true },
81
84
  argument: { kind: "free-text", optional: true, placeholder: "theme", description: "Theme name or keyword, such as nuclear; omit for all themes." },
82
85
  options: [],
83
86
  discovery: { aliases: ["THEM"], dataRequirements: ["Gloom Cloud stored equity snapshot"],
84
- limitations: ["Updated every 15 minutes for Free and Pro.", "Equal-weight price returns; missing observations reduce coverage.", "Below half coverage a period is unavailable.",
87
+ limitations: ["Prices and 1D are real-time with Pro and fifteen minutes delayed otherwise; the longer returns start from a snapshot updated every 15 minutes.", "Equal-weight price returns; missing observations reduce coverage.", "Below half coverage a period is unavailable.",
85
88
  "Outside the regular session Price, 1D and the returns end at the last regular close; a pre-market or after-hours print is shown beside it and never enters them."] },
86
89
  describe: (args, result) => themeReportTitle(args.rawArgument, (result?.metadata as { theme?: ThemeSummary } | undefined)?.theme),
87
90
  async load(args, context) {
@@ -82,14 +82,24 @@ function closeLabel(date: string): string {
82
82
  * How current the board is, for its footer. Outside the regular session the
83
83
  * close its figures describe and how old the snapshot is, `Fri 9 Oct close ·
84
84
  * snapshot 12m ago`; while a session trades, or from a server that does not
85
- * name the close, the delay and the snapshot's age. `age` is the relative age
86
- * (`12m ago`).
85
+ * name the close, whether its prices are live (a Pro account's) or delayed,
86
+ * and the snapshot's age, which the longer returns start from. `age` is the
87
+ * relative age (`12m ago`).
87
88
  */
88
- export function snapshotFooterText(payload: { regularSessionDate?: unknown; regularSessionClosedAt?: unknown }, age: string): string {
89
+ export function snapshotFooterText(payload: { regularSessionDate?: unknown; regularSessionClosedAt?: unknown; access?: unknown }, age: string): string {
89
90
  const close = boardClose(payload);
90
- return close ? `${closeLabel(close.date)} · snapshot ${age}` : `15m delayed · snapshot ${age}`;
91
+ if (close) return `${closeLabel(close.date)} · snapshot ${age}`;
92
+ return `${isLiveBoard(payload) ? "live" : "15m delayed"} · snapshot ${age}`;
91
93
  }
92
94
 
95
+ /** Whether a board's prices are real-time: a Pro account's, priced from the server's live read. */
96
+ export function isLiveBoard(payload: { access?: unknown } | null | undefined): boolean {
97
+ return payload?.access === "realtime";
98
+ }
99
+
100
+ /** How often a board is worth checking again: the server renews a live board's prices every 15 seconds. */
101
+ export const LIVE_BOARD_REFRESH_MS = 15_000;
102
+
93
103
  /** A member's pre-market or after-hours print and its move from the close in Price, when it has a valid one. */
94
104
  export function memberExtended(row: ThemeMember): { session: ExtendedSession; price: number; change: number | null; changePercent: number | null } | null {
95
105
  const session = row.extendedSession;
@@ -13,10 +13,21 @@ import { useMembersMenu } from "../shared/members-menu";
13
13
  import { cachedMembers, cachedThemes, loadMembers, loadThemes } from "./client";
14
14
  import {
15
15
  aggregateText, boardYtdBase, coverageWidth, DEFAULT_SORT, extendedMove, matchTheme, memberColumns, memberExtendedSessions, memberPrice, percent,
16
- SNAPSHOT_STALE_MS, snapshotFooterText, sortMembers, sortThemes, themeColumns, type ThemeSort,
16
+ isLiveBoard, LIVE_BOARD_REFRESH_MS, SNAPSHOT_STALE_MS, snapshotFooterText, sortMembers, sortThemes, themeColumns, type ThemeSort,
17
17
  } from "./model";
18
18
 
19
- type SnapshotPayload = { asOf: string; stale: boolean; regularSessionDate?: string | null; regularSessionClosedAt?: number | null };
19
+ const LIVE_LEAD = "live · ";
20
+ type SnapshotPayload = { asOf: string; stale: boolean; access?: "realtime" | "delayed"; regularSessionDate?: string | null; regularSessionClosedAt?: number | null };
21
+
22
+ /**
23
+ * Refreshes a board on the user's interval, or every 15 seconds while it is
24
+ * live: a Pro account's prices are renewed that often on the server.
25
+ */
26
+ function useBoardRefresh(resource: { updatedAt: number | null; load: (force?: boolean) => Promise<unknown>; data: { payload: SnapshotPayload } | null }) {
27
+ const live = isLiveBoard(resource.data?.payload);
28
+ const { load } = resource;
29
+ useAutoRefresh(resource.updatedAt, live ? () => void load(true) : () => void load(), { intervalMs: live ? LIVE_BOARD_REFRESH_MS : null });
30
+ }
20
31
 
21
32
  function useSnapshotFooter(id: string, resource: { loading: boolean; error: string | null; data: { payload: SnapshotPayload; stale: boolean; refreshError: string | null } | null }, focused: boolean, enabled = true) {
22
33
  const data = resource.data;
@@ -24,7 +35,15 @@ function useSnapshotFooter(id: string, resource: { loading: boolean; error: stri
24
35
  const payload = data?.payload;
25
36
  // Outside the regular session the figures are a close, so the footer names it, not the snapshot's time.
26
37
  const text = age && payload ? snapshotFooterText(payload, age) : null;
27
- const info = useMemo(() => text ? splitDelayedStatus({ id: "snapshot", parts: [{ text, tone: "muted" }] }) : [], [text]);
38
+ const info = useMemo(() => {
39
+ if (!text) return [];
40
+ // A live board says so as the other live panes do, before the snapshot's age.
41
+ if (text.startsWith(LIVE_LEAD)) {
42
+ return [{ id: "snapshot-live", parts: [{ text: "live", tone: "positive" as const }] },
43
+ { id: "snapshot", parts: [{ text: text.slice(LIVE_LEAD.length), tone: "muted" as const }] }];
44
+ }
45
+ return splitDelayedStatus({ id: "snapshot", parts: [{ text, tone: "muted" }] });
46
+ }, [text]);
28
47
  // The server flag includes retained historical returns; it does not mean the daily board is old.
29
48
  const snapshotStale = !!data && Date.now() - Date.parse(data.payload.asOf) > SNAPSHOT_STALE_MS;
30
49
  usePaneStatusFooter({ registrationId: id, enabled, loading: resource.loading && !!data,
@@ -49,7 +68,7 @@ function Members({ id, width, height, focused }: { id: string; width: number; he
49
68
  const ytdBase = data ? boardYtdBase(data) : null;
50
69
  const columns = useMemo(() => memberColumns(width, extendedSessionsKey ? extendedSessionsKey.split(",") as ExtendedSession[] : [], ytdBase),
51
70
  [extendedSessionsKey, width, ytdBase]);
52
- useAutoRefresh(resource.updatedAt, resource.load);
71
+ useBoardRefresh(resource);
53
72
  usePaneRefreshKey(() => void resource.reload(), { focused });
54
73
  useSnapshotFooter("themes:members", resource, focused);
55
74
  const memberList = useMemo(() => data ? { title: data.theme.name, watchlistName: data.theme.name, members: rows } : null, [data, rows]);
@@ -107,7 +126,7 @@ export function ThemesBoard({ width, height, focused, tabStrip, tabRows = 0 }: T
107
126
  const rows = useMemo(() => sortThemes(data?.themes ?? [], sort), [data, sort]);
108
127
  const columns = useMemo(() => themeColumns(width, data?.themes ?? [], data ? boardYtdBase(data) : null), [width, data]);
109
128
  const theme = opened && data ? matchTheme(data.themes, opened) : null;
110
- useAutoRefresh(resource.updatedAt, resource.load);
129
+ useBoardRefresh(resource);
111
130
  usePaneRefreshKey(() => void resource.reload(), { focused, enabled: !opened });
112
131
  useSnapshotFooter("themes:list", resource, focused, !opened || !data);
113
132
  const renderCell = useCallback((row: ThemeSummary, column: DataTableColumn): DataTableCell => {
@@ -471,10 +471,10 @@ function thirteenFShotState(args: HeadlessPaneLoadArgs, metadata: Record<string,
471
471
  });
472
472
  }
473
473
  case "crowding":
474
- if (query) throw new Error(`The 13F pane draws the whole crowding ranking, not one ticker's rank. Drop "${query}" from shot, or run the report: gloomberb fn 13F ${query} --view crowding`);
474
+ if (query) throw new Error(`The 13F pane draws the whole crowding ranking, not one ticker's rank. Drop "${query}" from shot, or run the report: gloom fn 13F ${query} --view crowding`);
475
475
  return { pluginState: { [PANE_STATE_ID]: { browserTab: "crowding", "13f-crowding:ranking": CROWDING_RANKING[String(metadata.rank ?? "new")] ?? "newCount" } } };
476
476
  case "performance":
477
- if (cik) throw new Error(`The 13F pane draws the performance ranking, not one fund's row. Run the report for ${metadata.fund ?? cik}: gloomberb fn 13F ${cik} --view performance, or gloomberb shot 13F --view performance for the ranking.`);
477
+ if (cik) throw new Error(`The 13F pane draws the performance ranking, not one fund's row. Run the report for ${metadata.fund ?? cik}: gloom fn 13F ${cik} --view performance, or gloom shot 13F --view performance for the ranking.`);
478
478
  return browser("");
479
479
  case "latest":
480
480
  return browser("latest");
@@ -484,7 +484,7 @@ function thirteenFShotState(args: HeadlessPaneLoadArgs, metadata: Record<string,
484
484
  return browser(query);
485
485
  case "byTicker":
486
486
  // The pane lists a ticker's holders with their positions, and their whole books only when it cannot.
487
- if (String(args.options.view) !== "auto") throw new Error(`The 13F pane lists a ticker's holders with their positions. Drop --view ${args.options.view} from shot, or run the report: gloomberb fn 13F ${query} --view by-ticker`);
487
+ if (String(args.options.view) !== "auto") throw new Error(`The 13F pane lists a ticker's holders with their positions. Drop --view ${args.options.view} from shot, or run the report: gloom fn 13F ${query} --view by-ticker`);
488
488
  return browser(query);
489
489
  default:
490
490
  return {};
@@ -796,7 +796,7 @@ export function createThirteenFHeadless(
796
796
  // A fund's own row of the performance list, with the command that copies its basket.
797
797
  if (view === "performance" && query && inferBrowserTabFromQuery(query) === "funds") {
798
798
  const fund = await resolveFund(query, args, ctx, dependencies, {
799
- notFound: `No 13F fund matched "${query}". For the performance ranking, run gloomberb fn 13F --view performance; for one fund, give its CIK, as in gloomberb fn 13F 0001067983 --view performance.`,
799
+ notFound: `No 13F fund matched "${query}". For the performance ranking, run gloom fn 13F --view performance; for one fund, give its CIK, as in gloom fn 13F 0001067983 --view performance.`,
800
800
  });
801
801
  const performance = await dependencies.loadPerformance(fund.cik, fund.name, ctx);
802
802
  const row = performance.rows[0]!;
@@ -832,7 +832,7 @@ export function createThirteenFHeadless(
832
832
  performance.skipped?.length ? splitUnreadText(performance.skipped, "Left out of Est 13F") : "",
833
833
  performance.unavailable ? `No Est 13F${rankingText ? ` (${rankingText})` : ""}: ${performance.unavailable}` : "",
834
834
  ...filingGapNotes(performance.period ?? null, performance.filingGap ?? null),
835
- `Copy this basket: gloomberb portfolio import --13f ${row.cik}`,
835
+ `Copy this basket: gloom portfolio import --13f ${row.cik}`,
836
836
  ].filter(Boolean),
837
837
  },
838
838
  };
@@ -11,6 +11,8 @@ export interface TickerHolderRow {
11
11
  type: string;
12
12
  value: number | null;
13
13
  shares: number | null;
14
+ /** Shares at the prior period end when the two reports compare: 0 for a new position, null when unknown. Absent from an older service. */
15
+ previousShares?: number | null;
14
16
  weight: number | null;
15
17
  previousWeight: number | null;
16
18
  weightChange: number | null;
@@ -55,7 +57,7 @@ export interface Crowding extends SignalsBase {
55
57
  }
56
58
  export async function loadTickerHoldings(ticker: string, offset = 0, signal?: AbortSignal): Promise<TickerHoldings> {
57
59
  signal?.throwIfAborted();
58
- const result = await apiClient.getCloudSec13F("ticker-holdings", { tickers: ticker, offset, limit: 25 }) as TickerHoldings;
60
+ const result = await apiClient.getCloudSec13F("ticker-holdings", { tickers: ticker, offset, limit: 25 }, { signal }) as TickerHoldings;
59
61
  signal?.throwIfAborted();
60
62
  return result;
61
63
  }
@@ -0,0 +1,123 @@
1
+ import type { HeadlessPaneDefinition } from "../../../../types/headless";
2
+ import type { Quote } from "../../../../types/financials";
3
+ import { dollarPairLabel, spotFromUsdValue, spotRateKind } from "../../../../market-data/depositary-pair";
4
+ import { loadHeadlessFinancials, resolveHeadlessInstrument } from "../../shared/headless-market-data";
5
+ import { quoteObservation } from "../../shared/report-freshness";
6
+ import { heldCurrencyUnit } from "../../../../utils/currency-units";
7
+ import { adrPairComparison, adrPairFigures, adrPairInputRows, adrPairLegs, ADR_PAIR_TEMPLATE_ID } from "./model";
8
+
9
+ /** Words that ask for this report's figures without being its code: `fn CCL` answers with ADR. */
10
+ export const ADR_PAIR_KEYWORDS = [
11
+ "adr", "adrs", "adr vs home", "adr ratio", "adr premium", "adr discount", "depositary receipt", "depositary receipts",
12
+ "home listing", "home line", "implied fx", "implied exchange rate", "implied dollar", "ccl", "contado con liquidacion",
13
+ "dolar ccl", "mep", "dolar mep", "dolar bolsa", "blue chip swap", "cross listing", "dual listing",
14
+ ];
15
+
16
+ type LoadContext = Parameters<HeadlessPaneDefinition["load"]>[1];
17
+
18
+ /** The currency's dollar rate, dated when the cached query says when it was observed (as `fx` dates it). */
19
+ async function readSpot(currency: string, ctx: LoadContext) {
20
+ if (currency === "USD") return { rate: 1, observedAt: null };
21
+ const { marketData } = ctx;
22
+ if (marketData.getCachedQuery) {
23
+ const entry = await marketData.getCachedQuery("getExchangeRate", [currency]).load({ background: marketData.revalidatesInBackground });
24
+ return spotFromUsdValue(entry.value, entry.asOf ?? null);
25
+ }
26
+ return spotFromUsdValue(await marketData.getExchangeRate(currency));
27
+ }
28
+
29
+ /** A leg's quote through the standard quote path, so both legs are read alike. */
30
+ async function readQuote(key: string, ctx: LoadContext, failed: (error: unknown) => null): Promise<Quote | null> {
31
+ const instrument = await resolveHeadlessInstrument(ctx, key);
32
+ return ctx.marketData.getQuote(instrument.symbol, instrument.exchange ?? "").catch(failed);
33
+ }
34
+
35
+ export const adrPairHeadless: HeadlessPaneDefinition<"bundle"> = {
36
+ shape: "bundle",
37
+ argument: { kind: "ticker", description: "A depositary receipt (GGAL, TSM) or its home listing (GGAL.BA, 2330.TW)" },
38
+ options: [],
39
+ discovery: {
40
+ // CCL is also a ticker (Carnival), so neither word opens ADR: `fn CCL` and `catalog ccl` point to it.
41
+ suggestFor: ["CCL", "MEP"],
42
+ screenshotReadiness: "ready",
43
+ limitations: [
44
+ "Listings Gloom Cloud pairs with a receipt only; the ratio is the depositary's, checked against both lines' prices.",
45
+ ],
46
+ },
47
+ description: "A depositary receipt beside its home listing: the ratio, both regular-session prices with when each was set, the dollar rate they imply (home × ratio / ADR, the CCL rate for an Argentine pair), spot, and the receipt's premium or discount at spot.",
48
+ describe: ({ symbols }) => `ADR vs Home | ${symbols[0] ?? ""}`,
49
+ async load({ symbols }, ctx) {
50
+ const key = symbols[0]!;
51
+ const financials = await loadHeadlessFinancials(ctx, key);
52
+ ctx.signal.throwIfAborted();
53
+ const legs = adrPairLegs(financials, null, key);
54
+ if (!legs) {
55
+ return {
56
+ sections: [],
57
+ empty: `${key} has no depositary receipt pair on record. ADR takes a receipt (GGAL, TSM) or its home listing (GGAL.BA, 2330.TW).`,
58
+ unavailableSymbols: [key],
59
+ };
60
+ }
61
+ const errors: string[] = [];
62
+ const failed = (label: string) => (error: unknown) => {
63
+ errors.push(`${label}: ${error instanceof Error ? error.message : String(error)}`);
64
+ return null;
65
+ };
66
+ const [receipt, home] = await Promise.all([
67
+ readQuote(legs.receiptKey, ctx, failed(legs.receiptKey)),
68
+ readQuote(legs.homeKey, ctx, failed(legs.homeKey)),
69
+ ]);
70
+ ctx.signal.throwIfAborted();
71
+ const quotes = { receipt, home };
72
+ // A minor unit (GBp) is read as its currency, as the comparison reads the price.
73
+ const homeCurrency = quotes.home?.currency ? heldCurrencyUnit(quotes.home.currency).currency : "";
74
+ const spot = homeCurrency ? await readSpot(homeCurrency, ctx).catch(failed(dollarPairLabel(homeCurrency))) : null;
75
+ const comparison = adrPairComparison(legs, quotes, spot);
76
+ if (!comparison) {
77
+ const missing = !quotes.receipt ? legs.receiptKey : legs.homeKey;
78
+ return { sections: [], empty: `No price for ${missing}, so the pair cannot be compared.`, unavailableSymbols: [missing], errors };
79
+ }
80
+ const figures = adrPairFigures(comparison);
81
+ const rows = adrPairInputRows(comparison);
82
+ const kind = spotRateKind(homeCurrency);
83
+ return {
84
+ sections: [
85
+ {
86
+ title: `${legs.receiptKey} vs ${legs.homeKey}`,
87
+ entries: figures.map((figure) => ({
88
+ key: figure.id, label: figure.label,
89
+ value: figure.id === "implied" ? comparison.impliedFx
90
+ : figure.id === "spot" ? comparison.spot?.rate ?? null
91
+ : figure.id === "premium" ? comparison.premiumPercent
92
+ : comparison.ratio,
93
+ formatted: figure.detail ? `${figure.value} (${figure.detail})` : figure.value,
94
+ })),
95
+ },
96
+ {
97
+ title: "Inputs",
98
+ columns: [
99
+ { key: "listing", header: "Listing" },
100
+ { key: "role", header: "Role" },
101
+ { key: "price", header: "Price", align: "right" },
102
+ { key: "asOf", header: "As of (UTC)" },
103
+ { key: "session", header: "Session" },
104
+ ],
105
+ rows: rows.map(({ opens: _opens, ...row }) => row),
106
+ },
107
+ ],
108
+ ...(comparison.timingNote ? { notes: [comparison.timingNote] } : {}),
109
+ ...(errors.length > 0 ? { errors } : {}),
110
+ freshness: {
111
+ observations: [quotes.receipt, quotes.home].filter((quote): quote is Quote => !!quote).map((quote) => ({ ...quoteObservation(quote) })),
112
+ },
113
+ metadata: {
114
+ receipt: legs.receiptKey, home: legs.homeKey, ratio: comparison.ratio, currency: homeCurrency,
115
+ impliedFx: comparison.impliedFx, spot: comparison.spot?.rate ?? null, ...(kind ? { spotKind: kind } : {}),
116
+ premiumPercent: comparison.premiumPercent,
117
+ receiptPrice: comparison.receipt.price, receiptObservedAt: comparison.receipt.observedAt,
118
+ homePrice: comparison.home.price, homeObservedAt: comparison.home.observedAt,
119
+ spotObservedAt: comparison.spot?.observedAt ?? null, template: ADR_PAIR_TEMPLATE_ID,
120
+ },
121
+ };
122
+ },
123
+ };