gloomberb 0.15.5 → 0.15.7

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 (324) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/src/api-client/auth.ts +28 -0
  5. package/src/api-client/data.ts +37 -10
  6. package/src/api-client/estimate-revisions.ts +1 -1
  7. package/src/api-client/futures-curve.ts +1 -1
  8. package/src/api-client/index.ts +10 -1
  9. package/src/api-client/market-discovery.ts +84 -0
  10. package/src/api-client/paths.ts +14 -11
  11. package/src/api-client/request.ts +12 -2
  12. package/src/api-client/research-activity.ts +4 -1
  13. package/src/api-client/tape.ts +2 -2
  14. package/src/api-client/types.ts +10 -0
  15. package/src/app/dialog-bridge.tsx +33 -0
  16. package/src/app/pane-runtime/index.tsx +9 -2
  17. package/src/app/pane-runtime/pane-settings-runtime.tsx +2 -1
  18. package/src/app/pane-runtime/pane-template-runtime.ts +8 -28
  19. package/src/app/pane-runtime/plugin-bindings.ts +34 -12
  20. package/src/app/pane-runtime/ticker-open-runtime.ts +5 -3
  21. package/src/app/runtime/broker-import.ts +5 -3
  22. package/src/app/runtime/desktop-menu.ts +9 -6
  23. package/src/app/runtime/plugin-bindings.ts +7 -1
  24. package/src/app/runtime/ticker-refresh.ts +1 -1
  25. package/src/app.tsx +12 -0
  26. package/src/brokers/directory.ts +11 -2
  27. package/src/brokers/profile-form.ts +2 -1
  28. package/src/brokers/remove-profile.ts +61 -0
  29. package/src/brokers/signed-in/connect.ts +20 -7
  30. package/src/brokers/signed-in/sign-in-dialog.tsx +68 -30
  31. package/src/cli/desktop-pane-shot.ts +2 -2
  32. package/src/cli/history-rows.ts +1 -1
  33. package/src/cli/pane-functions/function-help.ts +10 -3
  34. package/src/cli/ticker-resolution.ts +2 -2
  35. package/src/components/chart/composite/composite-chart.tsx +4 -2
  36. package/src/components/chart/composite/rasterizer.ts +69 -9
  37. package/src/components/command-bar/action-runtime.ts +7 -67
  38. package/src/components/command-bar/commands/direct/index.ts +9 -5
  39. package/src/components/command-bar/commands/direct/runtime.ts +12 -11
  40. package/src/components/command-bar/commands/plugin/actions.ts +6 -35
  41. package/src/components/command-bar/helpers.ts +3 -31
  42. package/src/components/command-bar/keyboard-handlers.ts +7 -219
  43. package/src/components/command-bar/keyboard-shortcuts.ts +25 -99
  44. package/src/components/command-bar/layout-items/current-layout.ts +12 -1
  45. package/src/components/command-bar/layout-items/focused-pane.ts +2 -1
  46. package/src/components/command-bar/layout-items/types.ts +2 -0
  47. package/src/components/command-bar/layout-items.ts +3 -0
  48. package/src/components/command-bar/list/model.ts +1 -1
  49. package/src/components/command-bar/list/navigation.ts +5 -12
  50. package/src/components/command-bar/pane-actions.ts +17 -14
  51. package/src/components/command-bar/pane-settings.ts +7 -250
  52. package/src/components/command-bar/pane-templates/workflow.ts +6 -13
  53. package/src/components/command-bar/panel/index.tsx +4 -110
  54. package/src/components/command-bar/panel/layout.ts +4 -16
  55. package/src/components/command-bar/panel/runtime.ts +1 -87
  56. package/src/components/command-bar/panel/state.ts +12 -29
  57. package/src/components/command-bar/panel/types.ts +2 -26
  58. package/src/components/command-bar/picker-activation.ts +7 -56
  59. package/src/components/command-bar/routes/root/plugin-install.ts +3 -3
  60. package/src/components/command-bar/routes/root/search-report.ts +2 -1
  61. package/src/components/command-bar/routing/actions.ts +21 -59
  62. package/src/components/command-bar/routing/confirm.ts +15 -88
  63. package/src/components/command-bar/routing/effects.ts +1 -20
  64. package/src/components/command-bar/routing/launch-request.ts +1 -36
  65. package/src/components/command-bar/routing/list-state.ts +5 -36
  66. package/src/components/command-bar/selection-runtime.ts +6 -35
  67. package/src/components/command-bar/surface/environment.ts +10 -6
  68. package/src/components/command-bar/surface/index.tsx +4 -37
  69. package/src/components/command-bar/workflow/alert.ts +23 -17
  70. package/src/components/command-bar/workflow/broker.ts +30 -40
  71. package/src/components/command-bar/workflow/builtin.ts +33 -38
  72. package/src/components/command-bar/workflow/collection-actions.ts +26 -21
  73. package/src/components/command-bar/workflow/collection-ticker.ts +4 -4
  74. package/src/components/command-bar/workflow/coordinator.ts +27 -156
  75. package/src/components/command-bar/workflow/fields.ts +6 -22
  76. package/src/components/command-bar/workflow/ops.ts +46 -3
  77. package/src/components/command-bar/workflow/submit.ts +28 -43
  78. package/src/components/command-bar/workflow/ticker-listing-picker.ts +12 -9
  79. package/src/components/command-bar/workflow/tickers.ts +2 -2
  80. package/src/components/command-bar/workflow/types.ts +10 -35
  81. package/src/components/feedback-dialog.tsx +1 -13
  82. package/src/components/form-modal/broker-step.tsx +119 -0
  83. package/src/components/form-modal/confirm.tsx +145 -0
  84. package/src/components/form-modal/content.tsx +698 -0
  85. package/src/components/form-modal/deps.ts +77 -0
  86. package/src/components/form-modal/field-row.tsx +318 -0
  87. package/src/components/form-modal/host.tsx +169 -0
  88. package/src/components/form-modal/index.ts +2 -0
  89. package/src/components/form-modal/model.ts +131 -0
  90. package/src/components/form-modal/request.ts +67 -0
  91. package/src/components/form-modal/routes.ts +139 -0
  92. package/src/components/layout/pane/frame.tsx +2 -1
  93. package/src/components/layout/pane/surface.ts +26 -0
  94. package/src/components/layout/pane/title.ts +21 -5
  95. package/src/components/layout/shell/index.tsx +12 -1
  96. package/src/components/layout/shell/ticker-link-menu.ts +46 -23
  97. package/src/components/layout/status-bar.tsx +7 -1
  98. package/src/components/onboarding/desks-step.tsx +43 -0
  99. package/src/components/onboarding/first-run-workspace.ts +1 -1
  100. package/src/components/onboarding/onboarding-frame.tsx +4 -1
  101. package/src/components/onboarding/onboarding-wizard.tsx +151 -26
  102. package/src/components/onboarding/wizard-positions.ts +19 -6
  103. package/src/components/pane-settings-dialog.tsx +7 -1
  104. package/src/components/pane-template-wizard.tsx +4 -149
  105. package/src/components/sign-in-code-panel.tsx +22 -9
  106. package/src/components/textarea-keys.ts +13 -0
  107. package/src/components/toggle-list.tsx +18 -10
  108. package/src/components/ui/button.tsx +3 -2
  109. package/src/components/ui/confirm-dialog.tsx +62 -10
  110. package/src/components/ui/frame.tsx +7 -2
  111. package/src/components/ui/list-view.tsx +16 -9
  112. package/src/core/app-runtime.ts +1 -1
  113. package/src/core/state/app/layout.ts +2 -0
  114. package/src/core/state/app/types.ts +1 -15
  115. package/src/data/config/home.ts +82 -11
  116. package/src/data/config/store/node.ts +29 -16
  117. package/src/data/config/store/normalize.ts +3 -0
  118. package/src/i18n/es.ts +79 -7
  119. package/src/i18n/ja.ts +79 -7
  120. package/src/i18n/ko.ts +79 -7
  121. package/src/i18n/zh-cn.ts +79 -7
  122. package/src/i18n/zh-tw.ts +79 -7
  123. package/src/layout/desks.ts +335 -0
  124. package/src/layout/pane-follow.ts +47 -0
  125. package/src/layout/ticker-navigation.ts +13 -0
  126. package/src/layout-marketplace/gallery.tsx +11 -3
  127. package/src/market-data/coordinator/fx-legs.ts +1 -1
  128. package/src/market-data/history-session.ts +3 -5
  129. package/src/market-data/market/format.ts +15 -9
  130. package/src/market-data/market/freshness.ts +1 -1
  131. package/src/market-data/market/status.ts +1 -1
  132. package/src/market-data/quotes/metadata.ts +3 -3
  133. package/src/market-data/quotes/resolution.ts +3 -3
  134. package/src/news/types.ts +1 -1
  135. package/src/plugins/builtin/account-management/calendar-tab.tsx +196 -0
  136. package/src/plugins/builtin/account-management/footer.ts +5 -2
  137. package/src/plugins/builtin/account-management/index.tsx +2 -2
  138. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  139. package/src/plugins/builtin/account-management/pane.tsx +11 -1
  140. package/src/plugins/builtin/alerts/alert-engine.ts +2 -0
  141. package/src/plugins/builtin/alerts/cli.ts +2 -2
  142. package/src/plugins/builtin/alerts/types.ts +2 -0
  143. package/src/plugins/builtin/analytics/index.tsx +16 -9
  144. package/src/plugins/builtin/analytics/pane-model.ts +20 -11
  145. package/src/plugins/builtin/backtest/index.tsx +1 -1
  146. package/src/plugins/builtin/broker-manager/add-flow.tsx +625 -0
  147. package/src/plugins/builtin/broker-manager/add-request.ts +34 -0
  148. package/src/plugins/builtin/broker-manager/detail.tsx +128 -50
  149. package/src/plugins/builtin/broker-manager/footer.ts +6 -5
  150. package/src/plugins/builtin/broker-manager/index.tsx +62 -21
  151. package/src/plugins/builtin/broker-manager/model.ts +7 -0
  152. package/src/plugins/builtin/broker-manager/pane-actions.tsx +47 -44
  153. package/src/plugins/builtin/chart-composer/index.tsx +20 -0
  154. package/src/plugins/builtin/chart-composer/pane.tsx +35 -7
  155. package/src/plugins/builtin/cloud/company-picker.tsx +658 -0
  156. package/src/plugins/builtin/credit-boards/model.ts +1 -1
  157. package/src/plugins/builtin/debt-maturities/index.tsx +1 -0
  158. package/src/plugins/builtin/dividend-yield/browser.tsx +2 -25
  159. package/src/plugins/builtin/dividend-yield/client.ts +34 -122
  160. package/src/plugins/builtin/dividend-yield/index.tsx +10 -9
  161. package/src/plugins/builtin/dividend-yield/provider-client.ts +1 -1
  162. package/src/plugins/builtin/estimate-revisions/client.ts +3 -3
  163. package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
  164. package/src/plugins/builtin/estimate-revisions/pane.tsx +2 -2
  165. package/src/plugins/builtin/executives/index.tsx +1 -0
  166. package/src/plugins/builtin/executives/pane.tsx +13 -4
  167. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  168. package/src/plugins/builtin/filing-events/pane.tsx +23 -6
  169. package/src/plugins/builtin/futures/contracts.ts +3 -3
  170. package/src/plugins/builtin/futures/returns.ts +1 -1
  171. package/src/plugins/builtin/futures-curve/client.ts +1 -1
  172. package/src/plugins/builtin/futures-curve/model.ts +1 -1
  173. package/src/plugins/builtin/help/index.tsx +8 -3
  174. package/src/plugins/builtin/holders/index.tsx +1 -0
  175. package/src/plugins/builtin/insider/index.tsx +1 -0
  176. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  177. package/src/plugins/builtin/layout-manager/index.tsx +75 -1
  178. package/src/plugins/builtin/market-heatmap/data.ts +13 -256
  179. package/src/plugins/builtin/market-heatmap/index.tsx +5 -15
  180. package/src/plugins/builtin/market-movers/client.ts +1 -1
  181. package/src/plugins/builtin/market-movers/screener.ts +60 -142
  182. package/src/plugins/builtin/market-valuation/defs.ts +1 -2
  183. package/src/plugins/builtin/market-valuation/sources.ts +1 -3
  184. package/src/plugins/builtin/news/index.tsx +1 -0
  185. package/src/plugins/builtin/news/wire/default-feeds.ts +2 -8
  186. package/src/plugins/builtin/news/wire/feed-config.ts +5 -1
  187. package/src/plugins/builtin/news/wire/persisted-articles.ts +9 -5
  188. package/src/plugins/builtin/news/wire/rss/cli.ts +1 -1
  189. package/src/plugins/builtin/news/wire/rss/managed-feed.ts +19 -0
  190. package/src/plugins/builtin/news/wire/rss/parser.ts +18 -9
  191. package/src/plugins/builtin/news/wire/rss/source.ts +1 -1
  192. package/src/plugins/builtin/options/index.tsx +1 -0
  193. package/src/plugins/builtin/options-positioning/client.ts +5 -0
  194. package/src/plugins/builtin/options-positioning/headless.ts +2 -1
  195. package/src/plugins/builtin/options-positioning/index.tsx +1 -0
  196. package/src/plugins/builtin/options-positioning/pane.tsx +24 -9
  197. package/src/plugins/builtin/options-scenario/client.ts +78 -21
  198. package/src/plugins/builtin/options-scenario/headless.ts +14 -2
  199. package/src/plugins/builtin/options-scenario/model.ts +2 -0
  200. package/src/plugins/builtin/options-scenario/pane.tsx +14 -5
  201. package/src/plugins/builtin/plugin-marketplace/model.ts +5 -0
  202. package/src/plugins/builtin/plugin-marketplace/pane.tsx +4 -2
  203. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +7 -1
  204. package/src/plugins/builtin/portfolio-list/cli/render.ts +13 -13
  205. package/src/plugins/builtin/portfolio-list/column-values.ts +1 -0
  206. package/src/plugins/builtin/portfolio-list/metrics.ts +1 -1
  207. package/src/plugins/builtin/portfolio-list/mutations.ts +71 -0
  208. package/src/plugins/builtin/portfolio-list/pane/index.tsx +26 -14
  209. package/src/plugins/builtin/portfolio-list/summary/index.tsx +18 -9
  210. package/src/plugins/builtin/portfolio-list/summary/totals.ts +48 -7
  211. package/src/plugins/builtin/realized-vol/index.tsx +1 -1
  212. package/src/plugins/builtin/relative-rotation/client.ts +1 -1
  213. package/src/plugins/builtin/research/analyst-model.ts +1 -1
  214. package/src/plugins/builtin/research/event-model.ts +1 -1
  215. package/src/plugins/builtin/research/index.tsx +4 -0
  216. package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
  217. package/src/plugins/builtin/risk-factors/index.tsx +1 -0
  218. package/src/plugins/builtin/risk-factors/pane.tsx +25 -10
  219. package/src/plugins/builtin/seasonality/index.tsx +1 -1
  220. package/src/plugins/builtin/sec/index.tsx +1 -0
  221. package/src/plugins/builtin/shared/pro-feature-wall.tsx +47 -0
  222. package/src/plugins/builtin/short-interest/client.ts +14 -106
  223. package/src/plugins/builtin/short-interest/headless.ts +2 -2
  224. package/src/plugins/builtin/short-interest/index.tsx +7 -6
  225. package/src/plugins/builtin/short-interest/pane.tsx +4 -4
  226. package/src/plugins/builtin/short-volume/index.tsx +6 -1
  227. package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
  228. package/src/plugins/builtin/ticker-detail/pane.tsx +2 -2
  229. package/src/plugins/builtin/time-sales/client.ts +3 -3
  230. package/src/plugins/builtin/time-sales/index.tsx +1 -1
  231. package/src/plugins/builtin/vol-surface/model.ts +1 -1
  232. package/src/plugins/builtin/volatility/model.ts +1 -1
  233. package/src/plugins/bundle.ts +2 -2
  234. package/src/plugins/catalog-manifest.ts +0 -1
  235. package/src/plugins/catalog-ui.ts +1 -1
  236. package/src/plugins/catalog.ts +0 -2
  237. package/src/plugins/host-link.ts +1 -1
  238. package/src/plugins/host-resolver.ts +1 -1
  239. package/src/plugins/loader.ts +6 -5
  240. package/src/plugins/registry/host-actions.ts +6 -1
  241. package/src/plugins/registry/index.ts +1 -0
  242. package/src/plugins/runtime/context.tsx +2 -0
  243. package/src/plugins/runtime/index.tsx +2 -0
  244. package/src/public/__snapshots__/public-api.test.ts.snap +0 -1
  245. package/src/public/market-data.ts +0 -7
  246. package/src/remote/controller-utils.ts +1 -1
  247. package/src/remote/controller.ts +27 -3
  248. package/src/remote/form.ts +20 -0
  249. package/src/remote/resources.ts +7 -0
  250. package/src/remote/schema.ts +25 -3
  251. package/src/remote/semantic-tree.tsx +15 -0
  252. package/src/remote/types.ts +2 -0
  253. package/src/renderers/browser/research-entry.ts +2 -2
  254. package/src/renderers/cloudflare/http-proxy.ts +157 -33
  255. package/src/renderers/cloudflare/proxy-session.ts +270 -0
  256. package/src/renderers/cloudflare/worker.ts +4 -1
  257. package/src/renderers/dom/desktop/controls.tsx +2 -1
  258. package/src/renderers/dom/dialog-host.tsx +17 -8
  259. package/src/renderers/dom/styles.css +4 -0
  260. package/src/renderers/electrobun/bun/application-menu/index.ts +5 -4
  261. package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
  262. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -2
  263. package/src/renderers/electrobun/bun/external-plugins.ts +1 -1
  264. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -6
  265. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +3 -3
  266. package/src/renderers/opentui/dialog-host.tsx +14 -2
  267. package/src/renderers/opentui/start.tsx +2 -2
  268. package/src/renderers/opentui/terminal-media.ts +2 -2
  269. package/src/renderers/opentui/test-utils.tsx +9 -2
  270. package/src/renderers/opentui/toast-host.tsx +1 -1
  271. package/src/shares/portable-layout.ts +4 -6
  272. package/src/sources/gloomberb-cloud/index.ts +23 -24
  273. package/src/sources/gloomberb-cloud/news.ts +3 -3
  274. package/src/sources/history-retention.ts +6 -6
  275. package/src/sources/{yahoo-finance/symbols.ts → listing-symbols.ts} +16 -41
  276. package/src/sources/listing-target.ts +4 -4
  277. package/src/sources/provider-router/cache.ts +16 -6
  278. package/src/sources/provider-router/financials.ts +1 -1
  279. package/src/sources/provider-router/history.ts +3 -2
  280. package/src/state/app/bootstrap.ts +1 -1
  281. package/src/state/app/context/index.tsx +13 -0
  282. package/src/sync/core-contributors.ts +163 -16
  283. package/src/test-support/plugin-runtime.ts +1 -0
  284. package/src/tickers/instrument-kind.ts +1 -1
  285. package/src/tickers/open-target.ts +4 -4
  286. package/src/tickers/search/index.ts +3 -3
  287. package/src/tickers/search/ranking.ts +4 -4
  288. package/src/time-series/resolution.ts +1 -1
  289. package/src/time-series/resolve.ts +1 -1
  290. package/src/types/config.ts +19 -12
  291. package/src/types/financials.ts +5 -5
  292. package/src/types/instrument.ts +1 -1
  293. package/src/types/plugin.ts +10 -3
  294. package/src/types/price-history.ts +1 -1
  295. package/src/ui/dialog-bridge.tsx +50 -0
  296. package/src/ui/dialog-context.ts +24 -0
  297. package/src/ui/dialog-stack.ts +47 -1
  298. package/src/ui/dialog.tsx +2 -10
  299. package/src/ui/host.tsx +6 -1
  300. package/src/ui/index.tsx +7 -2
  301. package/src/utils/latest-financial-period.ts +1 -1
  302. package/src/utils/plugin-proxy-hosts.json +1 -5
  303. package/src/utils/sec.ts +1 -1
  304. package/src/app/pane-template-dialog-wizard.tsx +0 -67
  305. package/src/components/command-bar/multi-select-picker.tsx +0 -225
  306. package/src/components/command-bar/multi-select-runtime.ts +0 -91
  307. package/src/components/command-bar/workflow/body.tsx +0 -164
  308. package/src/components/command-bar/workflow/field-row.tsx +0 -231
  309. package/src/components/command-bar/workflow/route-actions.ts +0 -235
  310. package/src/components/command-bar/workflow/runtime.ts +0 -247
  311. package/src/plugins/builtin/yahoo/index.ts +0 -38
  312. package/src/sources/yahoo-finance/chart-period.ts +0 -138
  313. package/src/sources/yahoo-finance/financials.ts +0 -370
  314. package/src/sources/yahoo-finance/history.ts +0 -150
  315. package/src/sources/yahoo-finance/http.ts +0 -119
  316. package/src/sources/yahoo-finance/mappers.ts +0 -549
  317. package/src/sources/yahoo-finance/names.ts +0 -28
  318. package/src/sources/yahoo-finance/options.ts +0 -190
  319. package/src/sources/yahoo-finance/quote-summary.ts +0 -176
  320. package/src/sources/yahoo-finance/requests.ts +0 -245
  321. package/src/sources/yahoo-finance/snapshots.ts +0 -336
  322. package/src/sources/yahoo-finance/types.ts +0 -198
  323. package/src/sources/yahoo-finance/yahoo-chart-interval.ts +0 -18
  324. package/src/sources/yahoo-finance.ts +0 -339
package/README.md CHANGED
@@ -38,7 +38,7 @@ The desktop app and TUI share the command language and plugin system. The [brows
38
38
  On **macOS (Apple Silicon)**:
39
39
 
40
40
  ```bash
41
- brew install --cask vincelwt/tap/gloomberb
41
+ brew install --cask gloomberb
42
42
  ```
43
43
 
44
44
  On **Windows 11**, [download the installer](https://github.com/gloom-sh/gloomberb/releases/latest/download/stable-win-x64-GloomberbSetup.exe). It supports x64, and ARM64 through x64 emulation.
@@ -117,7 +117,7 @@ When the app hits an uncaught error, a render crash, or a plugin that fails to l
117
117
 
118
118
  The app also counts how often you open each function, from the command bar, a menu or a link in another pane, and which functions are on screen when a workspace is restored at launch. It sends each function's mnemonic (such as `DES` or `GP`) with those two counts, the surface, the app version and the operating system, a minute after the first count, then every 15 minutes, and when you quit. Functions from plugins other than the official gloom-sh ones are sent as `plugin`, so their names never leave your machine. The server adds your plan (signed out, Free or Pro); the counts are never tied to your account.
119
119
 
120
- Neither contains anything from your workspace: no tickers, arguments, portfolios, watchlists, layouts, settings or queries. Both carry a random install id stored in `~/.gloomberb/install-id` (in the browser, in local storage).
120
+ Neither contains anything from your workspace: no tickers, arguments, portfolios, watchlists, layouts, settings or queries. Both carry a random install id stored in `install-id` in the data folder, `~/.gloomberb` by default (in the browser, in local storage).
121
121
 
122
122
  The usage setting also covers command bar searches. When you are signed in, a search you finish in the command bar (you pause typing or run something, never each keystroke) is stored with your account to improve search: its text, the AI suggestions it got and the result you picked. Searches are deleted with your account.
123
123
 
package/README.zh-CN.md CHANGED
@@ -40,7 +40,7 @@
40
40
  在 **macOS(Apple Silicon)** 上:
41
41
 
42
42
  ```bash
43
- brew install --cask vincelwt/tap/gloomberb
43
+ brew install --cask gloomberb
44
44
  ```
45
45
 
46
46
  在 **Windows 11** 上,[下载安装程序](https://github.com/gloom-sh/gloomberb/releases/latest/download/stable-win-x64-GloomberbSetup.exe)。支持 x64,也可通过 x64 仿真在 ARM64 上运行。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gloomberb",
3
- "version": "0.15.5",
3
+ "version": "0.15.7",
4
4
  "packageManager": "bun@1.3.11",
5
5
  "description": "Market research and portfolio tracker for the terminal",
6
6
  "module": "src/public/index.ts",
@@ -6,6 +6,7 @@ import type {
6
6
  AuthUser,
7
7
  BuildoutAccountResponse,
8
8
  BuildoutTokenResponse,
9
+ CalendarFeed,
9
10
  CloudAccountPlan,
10
11
  CloudBrowserHandoffResponse,
11
12
  CloudPricing,
@@ -250,6 +251,33 @@ export class CloudAuthApi {
250
251
  );
251
252
  }
252
253
 
254
+ /** The private calendar feed link, or null until it is first created. */
255
+ async getCalendarFeed(): Promise<CalendarFeed | null> {
256
+ const result = await this.options.request<{ feed: CalendarFeed | null }>(
257
+ "/account/calendar-feed",
258
+ { method: "GET" },
259
+ );
260
+ return result.feed;
261
+ }
262
+
263
+ /** The calendar feed link, created on first use. */
264
+ async ensureCalendarFeed(): Promise<CalendarFeed> {
265
+ const result = await this.options.request<{ feed: CalendarFeed }>(
266
+ "/account/calendar-feed",
267
+ { method: "POST", body: JSON.stringify({}) },
268
+ );
269
+ return result.feed;
270
+ }
271
+
272
+ /** A new calendar feed link; the old one stops working. */
273
+ async rotateCalendarFeed(): Promise<CalendarFeed> {
274
+ const result = await this.options.request<{ feed: CalendarFeed }>(
275
+ "/account/calendar-feed/rotate",
276
+ { method: "POST", body: JSON.stringify({}) },
277
+ );
278
+ return result.feed;
279
+ }
280
+
253
281
  async updateAccountProfile(
254
282
  update: AccountProfileUpdate,
255
283
  ): Promise<AccountProfile> {
@@ -1,3 +1,5 @@
1
+ import type { EarningsEvent } from "../types/data-provider";
2
+ import type { MarketDividendsPayload, MarketHeatmapResult, MarketHeatmapUniverseId, MarketMoversPayload } from "./market-discovery";
1
3
  import type { DebtMaturitiesPayload } from "./debt-maturities";
2
4
  import type { RevenueBreakdownPayload, RevenueBreakdownView } from "./revenue-breakdown";
3
5
  import type { MnaDealPayload, MnaDealsParams, MnaDealsPayload } from "./mna";
@@ -39,11 +41,11 @@ import {
39
41
  cloudJobsPath,
40
42
  cloudJobsPostingsPath,
41
43
  type CloudJobsPostingsParams,
42
- publicProxyStatementPath,
43
- publicFilingEventsPath,
44
- publicRiskReportPath,
45
- publicRiskReportsPath,
46
- publicProxyStatementsPath,
44
+ cloudProxyStatementPath,
45
+ cloudFilingEventsPath,
46
+ cloudRiskReportPath,
47
+ cloudRiskReportsPath,
48
+ cloudProxyStatementsPath,
47
49
  cloudExchangeRatePath,
48
50
  cloudSec13FPath,
49
51
  cloudSecFilingContentPath,
@@ -213,6 +215,31 @@ export class CloudDataApi {
213
215
  );
214
216
  }
215
217
 
218
+ getMarketEarningsCalendar(symbols: string[]): Promise<CloudMarketResponse<Array<Omit<EarningsEvent, "earningsDate" | "earningsCallDate"> & { earningsDate: string; earningsCallDate?: string | null }>>> {
219
+ return this.request(`/market/earnings-calendar?${new URLSearchParams({ symbols: symbols.join(",") })}`);
220
+ }
221
+
222
+ getCloudArticleSummary(url: string): Promise<{ summary: string | null }> {
223
+ return this.request(`/news/article-summary?${new URLSearchParams({ url })}`);
224
+ }
225
+
226
+ getMarketMovers(category: "day_gainers" | "day_losers" | "most_actives", count = 25, refresh = false): Promise<CloudMarketResponse<MarketMoversPayload>> {
227
+ const params = new URLSearchParams({ category, count: String(count), mode: refresh ? "refresh" : "cache-first" });
228
+ return this.request(`/market/movers?${params}`);
229
+ }
230
+
231
+ getMarketTrending(count = 25): Promise<CloudMarketResponse<Array<{ symbol: string }>>> {
232
+ return this.request(`/market/trending?count=${encodeURIComponent(count)}`);
233
+ }
234
+
235
+ getMarketHeatmap(universe: MarketHeatmapUniverseId, count = 80): Promise<CloudMarketResponse<MarketHeatmapResult>> {
236
+ return this.request(`/market/heatmap?${new URLSearchParams({ universe, count: String(count) })}`);
237
+ }
238
+
239
+ getMarketDividends(symbol: string, exchange = ""): Promise<CloudMarketResponse<MarketDividendsPayload>> {
240
+ return this.requestMarketSymbol("/market/dividends", symbol, exchange);
241
+ }
242
+
216
243
  /** Gainers, losers and most active, or the pre-market, after-hours and gap lists with a `side`. */
217
244
  async getCloudMarketScreener<Category extends CloudMarketScreenerCategory | CloudSessionMoversCategory>(
218
245
  category: Category,
@@ -521,7 +548,7 @@ export class CloudDataApi {
521
548
  ticker: string,
522
549
  ): Promise<CloudProxyStatementListPayload> {
523
550
  return this.request<CloudProxyStatementListPayload>(
524
- publicProxyStatementsPath(ticker),
551
+ cloudProxyStatementsPath(ticker),
525
552
  );
526
553
  }
527
554
 
@@ -530,7 +557,7 @@ export class CloudDataApi {
530
557
  year: number,
531
558
  ): Promise<CloudProxyStatementPayload> {
532
559
  return this.request<CloudProxyStatementPayload>(
533
- publicProxyStatementPath(ticker, year),
560
+ cloudProxyStatementPath(ticker, year),
534
561
  );
535
562
  }
536
563
 
@@ -539,13 +566,13 @@ export class CloudDataApi {
539
566
  limit?: number,
540
567
  ): Promise<{ ticker: string; events: CloudFilingEventPayload[] }> {
541
568
  return this.request<{ ticker: string; events: CloudFilingEventPayload[] }>(
542
- publicFilingEventsPath(ticker, limit),
569
+ cloudFilingEventsPath(ticker, limit),
543
570
  );
544
571
  }
545
572
 
546
573
  async getRiskReports(ticker: string): Promise<CloudRiskReportListPayload> {
547
574
  return this.request<CloudRiskReportListPayload>(
548
- publicRiskReportsPath(ticker),
575
+ cloudRiskReportsPath(ticker),
549
576
  );
550
577
  }
551
578
 
@@ -554,7 +581,7 @@ export class CloudDataApi {
554
581
  year: number,
555
582
  ): Promise<CloudRiskReportPayload> {
556
583
  return this.request<CloudRiskReportPayload>(
557
- publicRiskReportPath(ticker, year),
584
+ cloudRiskReportPath(ticker, year),
558
585
  );
559
586
  }
560
587
 
@@ -22,7 +22,7 @@ export interface EstimateObservation {
22
22
  analysts: number | null;
23
23
  range: number | null;
24
24
  relativeRange: number | null;
25
- source: "yahoo" | "yahoo-eps-trend";
25
+ source: "gloom" | "gloom-eps-trend";
26
26
  }
27
27
  interface RevisionBreadth {
28
28
  days: 7 | 30;
@@ -22,7 +22,7 @@ export interface FuturesContract {
22
22
  export interface FuturesCurvePayload {
23
23
  root: string
24
24
  name: string
25
- source: "yahoo" | "cboe"
25
+ source: "gloom" | "cboe"
26
26
  currency: string | null
27
27
  quoteUnit: string | null
28
28
  asOf: string | null
@@ -360,7 +360,7 @@ class GloomApiClient {
360
360
  event: import("./research-activity").ResearchActivity; eventId: string;
361
361
  surface: "web" | "desktop" | "tui" | "cli"; anonymousId?: string;
362
362
  attribution?: Record<string, string>; feature?: import("./research-activity").ResearchFeature;
363
- tab?: string;
363
+ tab?: string; desks?: readonly string[];
364
364
  }): Promise<void> {
365
365
  await this.request("/activity/research", { method: "POST", body: JSON.stringify(payload) });
366
366
  }
@@ -405,6 +405,9 @@ class GloomApiClient {
405
405
  getBuildoutAccount = this.auth.getBuildoutAccount.bind(this.auth);
406
406
  getBuildoutToken = this.auth.getBuildoutToken.bind(this.auth);
407
407
  updateAccountProfile = this.auth.updateAccountProfile.bind(this.auth);
408
+ getCalendarFeed = this.auth.getCalendarFeed.bind(this.auth);
409
+ ensureCalendarFeed = this.auth.ensureCalendarFeed.bind(this.auth);
410
+ rotateCalendarFeed = this.auth.rotateCalendarFeed.bind(this.auth);
408
411
 
409
412
  async getSyncSnapshot(): Promise<CloudSyncSnapshotResponse> {
410
413
  return this.request<CloudSyncSnapshotResponse>("/sync/snapshot", { method: "GET" });
@@ -674,6 +677,12 @@ class GloomApiClient {
674
677
  getCloudQuote = this.data.getCloudQuote.bind(this.data);
675
678
  getCloudQuotesBatch = this.data.getCloudQuotesBatch.bind(this.data);
676
679
  getCloudWorldVenues = this.data.getCloudWorldVenues.bind(this.data);
680
+ getMarketEarningsCalendar = this.data.getMarketEarningsCalendar.bind(this.data);
681
+ getCloudArticleSummary = this.data.getCloudArticleSummary.bind(this.data);
682
+ getMarketMovers = this.data.getMarketMovers.bind(this.data);
683
+ getMarketTrending = this.data.getMarketTrending.bind(this.data);
684
+ getMarketHeatmap = this.data.getMarketHeatmap.bind(this.data);
685
+ getMarketDividends = this.data.getMarketDividends.bind(this.data);
677
686
  getCloudMarketScreener = this.data.getCloudMarketScreener.bind(this.data);
678
687
  getCloudOptionsChain = this.data.getCloudOptionsChain.bind(this.data);
679
688
  getCloudFinancials = this.data.getCloudFinancials.bind(this.data);
@@ -0,0 +1,84 @@
1
+ import type { CloudCorporateActionsPayload, CloudQuotePayload } from "./types";
2
+
3
+ export interface ScreenerQuote {
4
+ symbol: string;
5
+ name: string;
6
+ price: number | null;
7
+ change: number | null;
8
+ changePercent: number | null;
9
+ volume: number | null;
10
+ avgVolume: number | null;
11
+ volumeRatio: number | null; // volume / avgVolume
12
+ marketCap: number | undefined;
13
+ currency: string;
14
+ fiftyTwoWeekHigh: number | undefined;
15
+ fiftyTwoWeekLow: number | undefined;
16
+ dayHigh: number | undefined;
17
+ dayLow: number | undefined;
18
+ exchange: string;
19
+ lastUpdated?: number;
20
+ /** Session-fixed, so the price column reads its decimals from it rather than from each tick. */
21
+ previousClose?: number;
22
+ }
23
+
24
+
25
+ export type MarketHeatmapUniverseId = "us-equity" | "us-etf";
26
+ type MarketHeatmapSource = "gloom";
27
+ type MarketHeatmapSizeKind = "market-cap" | "net-assets";
28
+ export interface MarketHeatmapAsset {
29
+ symbol: string;
30
+ name: string;
31
+ price: number;
32
+ change: number;
33
+ changePercent: number;
34
+ /**
35
+ * Whether the source actually carried a session change. `changePercent` keeps
36
+ * a numeric 0 for the shared screener row shape, so tiles must read this
37
+ * before showing a flat session that was really missing data.
38
+ */
39
+ hasChange: boolean;
40
+ size: number | null;
41
+ sizeKind: MarketHeatmapSizeKind;
42
+ volume: number | null;
43
+ currency: string;
44
+ exchange: string;
45
+ sector: string | null;
46
+ industry: string | null;
47
+ marketState: string | null;
48
+ source: MarketHeatmapSource;
49
+ }
50
+
51
+ export interface MarketHeatmapResult {
52
+ stale?: boolean;
53
+ universe: MarketHeatmapUniverseId;
54
+ source: MarketHeatmapSource;
55
+ fetchedAt: number;
56
+ assets: MarketHeatmapAsset[];
57
+ }
58
+
59
+
60
+ export interface MarketMoversPayload {
61
+ quotes: ScreenerQuote[];
62
+ source: "gloom";
63
+ stale: boolean;
64
+ asOf: string;
65
+ }
66
+
67
+ export interface DividendSummary {
68
+ trailingAnnualDividendRate: number | null;
69
+ trailingAnnualDividendYield: number | null;
70
+ forwardAnnualDividendRate: number | null;
71
+ payoutRatio: number | null;
72
+ exDividendDate: number | null;
73
+ dividendDate: number | null;
74
+ currency: string | null;
75
+ }
76
+
77
+ export interface MarketDividendsPayload {
78
+ stale?: boolean;
79
+ actions: CloudCorporateActionsPayload | null;
80
+ quote: CloudQuotePayload | null;
81
+ summary: DividendSummary | null;
82
+ historyError?: string;
83
+ summaryError?: string;
84
+ }
@@ -311,30 +311,33 @@ export function cloudEarningsTranscriptPath(id: string): string {
311
311
  return `/cloud/transcripts/${encodeURIComponent(id)}`;
312
312
  }
313
313
 
314
- /** Executive compensation reads are open: no account, no plan. */
315
- export function publicProxyStatementsPath(ticker: string): string {
316
- return `/public/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
314
+ /**
315
+ * RISK, EXEC and EK are Pro: these reads need a verified Pro account. The same
316
+ * risk factors and pay are open under /public for the gloom.sh pages.
317
+ */
318
+ export function cloudProxyStatementsPath(ticker: string): string {
319
+ return `/cloud/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
317
320
  }
318
321
 
319
- export function publicFilingEventsPath(ticker: string, limit?: number): string {
322
+ export function cloudFilingEventsPath(ticker: string, limit?: number): string {
320
323
  const search = new URLSearchParams();
321
324
  if (limit != null) search.set("limit", String(limit));
322
325
  return appendQuery(
323
- `/public/events/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`,
326
+ `/cloud/events/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`,
324
327
  search,
325
328
  );
326
329
  }
327
330
 
328
- export function publicRiskReportsPath(ticker: string): string {
329
- return `/public/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
331
+ export function cloudRiskReportsPath(ticker: string): string {
332
+ return `/cloud/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
330
333
  }
331
334
 
332
- export function publicRiskReportPath(ticker: string, year: number): string {
333
- return `/public/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
335
+ export function cloudRiskReportPath(ticker: string, year: number): string {
336
+ return `/cloud/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
334
337
  }
335
338
 
336
- export function publicProxyStatementPath(ticker: string, year: number): string {
337
- return `/public/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
339
+ export function cloudProxyStatementPath(ticker: string, year: number): string {
340
+ return `/cloud/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
338
341
  }
339
342
 
340
343
  export function cloudSecFilingsPath(params: CloudSecFilingsParams): string {
@@ -17,6 +17,12 @@ import { SESSION_COOKIE_NAMES } from "./session-cookie";
17
17
 
18
18
  const DEFAULT_API_URL = "https://api.gloom.sh";
19
19
  const DEFAULT_MARKET_REQUEST_TIMEOUT_MS = 10_000;
20
+ const DEFAULT_RESEARCH_REQUEST_TIMEOUT_MS = 45_000;
21
+ // Research may fill missing sections after a primary read; quote/history reads remain latency bounded.
22
+ const RESEARCH_MARKET_PATHS = new Set([
23
+ "/market/dividends", "/market/short-interest", "/market/movers", "/market/trending",
24
+ "/market/heatmap", "/market/earnings-calendar",
25
+ ]);
20
26
  /** Local status for "this runtime cannot stream", never returned by the server. */
21
27
  export const STREAMING_UNSUPPORTED_STATUS = 0;
22
28
 
@@ -140,6 +146,7 @@ export class CloudApiRequestTransport {
140
146
  private cookieSessionMode = false;
141
147
  private readonly fetchTransport: CloudApiFetchTransport | null;
142
148
  private readonly marketRequestTimeoutMs: number;
149
+ private readonly researchRequestTimeoutMs: number;
143
150
  private readonly connectionHealth: ConnectionHealthRegistry;
144
151
 
145
152
  readonly baseUrl = getCloudApiBaseUrl();
@@ -154,6 +161,7 @@ export class CloudApiRequestTransport {
154
161
  this.fetchTransport = options.fetchTransport ?? null;
155
162
  this.marketRequestTimeoutMs =
156
163
  options.marketRequestTimeoutMs ?? DEFAULT_MARKET_REQUEST_TIMEOUT_MS;
164
+ this.researchRequestTimeoutMs = options.marketRequestTimeoutMs ?? DEFAULT_RESEARCH_REQUEST_TIMEOUT_MS;
157
165
  this.connectionHealth = options.connectionHealth ?? connectionHealth;
158
166
  }
159
167
 
@@ -257,6 +265,8 @@ export class CloudApiRequestTransport {
257
265
  return this.performRequest<T>(path, options, canApplySession);
258
266
  }
259
267
 
268
+ const timeoutMs = RESEARCH_MARKET_PATHS.has(path.split("?")[0]!)
269
+ ? this.researchRequestTimeoutMs : this.marketRequestTimeoutMs;
260
270
  const controller = new AbortController();
261
271
  const callerSignal = options?.signal;
262
272
  const abortFromCaller = () => controller.abort(callerSignal?.reason);
@@ -273,8 +283,8 @@ export class CloudApiRequestTransport {
273
283
  }, canApplySession);
274
284
  return await withDeadline(
275
285
  request,
276
- this.marketRequestTimeoutMs,
277
- `Cloud market request timed out after ${this.marketRequestTimeoutMs}ms: ${path}`,
286
+ timeoutMs,
287
+ `Cloud market request timed out after ${timeoutMs}ms: ${path}`,
278
288
  (error) => controller.abort(error),
279
289
  );
280
290
  } finally {
@@ -318,12 +318,14 @@ function attributionPayload(): Record<string, string> | undefined {
318
318
  /**
319
319
  * Counts milestones once per feature/session/account, never their content.
320
320
  * Native surfaces report anonymously only with an identifier the website
321
- * handed over; they still never mint one of their own.
321
+ * handed over; they still never mint one of their own. `desks` rides on the
322
+ * end of the first-run funnel: the desks picked at "What do you trade?".
322
323
  */
323
324
  export function recordResearchActivity(
324
325
  event: ResearchActivity,
325
326
  feature?: ResearchFeature,
326
327
  tab?: string,
328
+ desks?: readonly string[],
327
329
  ): void {
328
330
  const target = getCurrentPluginTarget();
329
331
  const user = apiClient.getCurrentUser();
@@ -342,6 +344,7 @@ export function recordResearchActivity(
342
344
  attribution: attributionPayload(),
343
345
  feature,
344
346
  tab,
347
+ desks,
345
348
  })
346
349
  .catch(() => {
347
350
  sent.delete(key);
@@ -11,7 +11,7 @@ export interface TapeQuote {
11
11
  timestamp: string;
12
12
  bid: number | null;
13
13
  ask: number | null;
14
- /** Alpaca quote sizes are round lots. */
14
+ /** Quote sizes are round lots. */
15
15
  bidSize: number;
16
16
  askSize: number;
17
17
  bidExchange: string;
@@ -20,7 +20,7 @@ export interface TapeQuote {
20
20
  tape: string;
21
21
  }
22
22
  export interface TapeSnapshot {
23
- source: "Alpaca";
23
+ source: "Gloom Cloud";
24
24
  symbol: string;
25
25
  exchange: string;
26
26
  access: "realtime" | "delayed";
@@ -193,6 +193,14 @@ export interface CloudPricing {
193
193
  yearly: CloudPricingTier;
194
194
  }
195
195
 
196
+ /** The account's private calendar feed link (`/account/calendar-feed`). */
197
+ export interface CalendarFeed {
198
+ url: string;
199
+ createdAt: string;
200
+ /** The last time a calendar app read it, to the hour. */
201
+ lastFetchedAt: string | null;
202
+ }
203
+
196
204
  /** One command-bar prefix described for `/assist/command`. */
197
205
  export interface AssistCommandDescriptor {
198
206
  prefix: string;
@@ -446,6 +454,7 @@ export interface CloudCdsHistoryResponse {
446
454
 
447
455
  interface CloudShortInterestPointPayload {
448
456
  settlementDate: string;
457
+ shortPercentFloat?: number | null;
449
458
  sharesShort: number;
450
459
  previousSharesShort: number | null;
451
460
  averageDailyVolume: number | null;
@@ -455,6 +464,7 @@ interface CloudShortInterestPointPayload {
455
464
  }
456
465
 
457
466
  export interface CloudShortInterestPayload {
467
+ source?: "finra" | "gloom";
458
468
  symbol: string;
459
469
  issueName: string | null;
460
470
  points: CloudShortInterestPointPayload[];
@@ -0,0 +1,33 @@
1
+ import { useCallback, useContext, type ReactNode } from "react";
2
+ import { RemoteUiRegistryProvider, useRemoteUiRegistry } from "../remote/semantic-tree";
3
+ import { AppContext, getEffectiveThemeId, useAppSelector } from "../state/app/context";
4
+ import { ThemeProvider } from "../theme/theme-context";
5
+ import { useRegisterDialogBridge } from "../ui/dialog-bridge";
6
+ import { KeybindingsProvider, useKeybindings } from "./keybindings";
7
+
8
+ function DialogTheme({ children }: { children: ReactNode }) {
9
+ const themeId = useAppSelector(getEffectiveThemeId);
10
+ return <ThemeProvider themeId={themeId}>{children}</ThemeProvider>;
11
+ }
12
+
13
+ /**
14
+ * Gives every dialog what the app gives its panes: the store, the theme, the
15
+ * keybindings and the remote registry, so a form in a dialog reads state and
16
+ * registers nodes like one in the app. Renders nothing.
17
+ */
18
+ export function AppDialogBridge() {
19
+ const store = useContext(AppContext);
20
+ const registry = useRemoteUiRegistry();
21
+ const keybindings = useKeybindings();
22
+ const bridge = useCallback((content: ReactNode) => {
23
+ const withKeybindings = <KeybindingsProvider value={keybindings}>{content}</KeybindingsProvider>;
24
+ const withRegistry = registry
25
+ ? <RemoteUiRegistryProvider registry={registry}>{withKeybindings}</RemoteUiRegistryProvider>
26
+ : withKeybindings;
27
+ return store
28
+ ? <AppContext value={store}><DialogTheme>{withRegistry}</DialogTheme></AppContext>
29
+ : withRegistry;
30
+ }, [keybindings, registry, store]);
31
+ useRegisterDialogBridge(bridge);
32
+ return null;
33
+ }
@@ -6,6 +6,7 @@ import {
6
6
  bringToFront,
7
7
  findDockLeaf,
8
8
  getDockedPaneIds,
9
+ isPaneDetached,
9
10
  isPaneInLayout,
10
11
  } from "../../layout/pane-manager";
11
12
  import type { PluginRegistry } from "../../plugins/registry";
@@ -18,6 +19,7 @@ import {
18
19
  type AppState,
19
20
  } from "../../state/app/context";
20
21
  import { scheduleConfigSave } from "../../state/config-save-scheduler";
22
+ import { pinFollowingPane } from "../../layout/pane-follow";
21
23
  import {
22
24
  createPaneInstance,
23
25
  isTickerPaneId,
@@ -51,6 +53,8 @@ interface AppPaneRuntimeArgs {
51
53
  dialog: DialogApi;
52
54
  dispatch: Dispatch<AppAction>;
53
55
  externalPlugins: readonly LoadedExternalPlugin[];
56
+ /** Desktop main window: raises a detached pane's own window. */
57
+ focusDetachedPane?: (paneId: string) => void;
54
58
  isDetachedWindow: boolean;
55
59
  notify: (body: string, options?: { type?: "info" | "success" | "error" }) => void;
56
60
  persistConfig: (nextConfig: AppState["config"]) => void;
@@ -66,6 +70,7 @@ export function useAppPaneRuntime({
66
70
  dialog,
67
71
  dispatch,
68
72
  externalPlugins,
73
+ focusDetachedPane,
69
74
  isDetachedWindow,
70
75
  notify,
71
76
  persistConfig,
@@ -82,6 +87,7 @@ export function useAppPaneRuntime({
82
87
  const currentState = stateRef.current;
83
88
  const normalizedLayout = normalizePaneLayout(layout, {
84
89
  resolveOrphanSymbol: (instanceId) => resolveTickerForPane(currentState, instanceId),
90
+ pinOrphan: pinFollowingPane,
85
91
  });
86
92
  if (options?.pushHistory !== false) {
87
93
  dispatch({ type: "PUSH_LAYOUT_HISTORY" });
@@ -157,7 +163,9 @@ export function useAppPaneRuntime({
157
163
  persistLayout(nextLayout, { pushHistory: false });
158
164
  }
159
165
  activatePane(paneId);
160
- }, [activatePane, persistLayout, state.config.layout]);
166
+ // Focus in this window's state alone would leave the pane's window behind this one.
167
+ if (isPaneDetached(nextLayout, paneId)) focusDetachedPane?.(paneId);
168
+ }, [activatePane, focusDetachedPane, persistLayout, state.config.layout]);
161
169
 
162
170
  const placePaneInstance = useCallback((
163
171
  instance: PaneInstanceConfig,
@@ -238,7 +246,6 @@ export function useAppPaneRuntime({
238
246
  const { createPaneFromTemplate } = useAppPaneTemplateRuntime({
239
247
  buildPaneInstance,
240
248
  dataProvider,
241
- dialog,
242
249
  dispatch,
243
250
  notify,
244
251
  placePaneInstance,
@@ -32,7 +32,7 @@ export function useAppPaneSettingsRuntime({
32
32
  stateRef,
33
33
  tickerRepository,
34
34
  }: UseAppPaneSettingsRuntimeOptions) {
35
- const openPaneSettings = useCallback(async (paneId?: string) => {
35
+ const openPaneSettings = useCallback(async (paneId?: string, options?: { fieldKey?: string }) => {
36
36
  const targetPaneId = paneId
37
37
  ? resolvePaneTarget(paneId)
38
38
  : stateRef.current.focusedPaneId;
@@ -59,6 +59,7 @@ export function useAppPaneSettingsRuntime({
59
59
  paneId={targetPaneId}
60
60
  pluginRegistry={pluginRegistry}
61
61
  applyFieldValue={applyFieldValue}
62
+ initialFieldKey={options?.fieldKey}
62
63
  />
63
64
  ),
64
65
  });