gloomberb 0.16.0 → 0.16.2

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 (691) hide show
  1. package/README.md +2 -1
  2. package/package.json +2 -1
  3. package/src/api-client/beneficial-owners.ts +92 -0
  4. package/src/api-client/data.ts +44 -11
  5. package/src/api-client/errors.ts +12 -0
  6. package/src/api-client/geo.ts +363 -0
  7. package/src/api-client/index.ts +5 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/members.ts +26 -0
  10. package/src/api-client/paths.ts +30 -1
  11. package/src/api-client/perps.ts +41 -0
  12. package/src/api-client/request.ts +5 -2
  13. package/src/api-client/types.ts +9 -1
  14. package/src/app/global-shortcuts.ts +14 -6
  15. package/src/app/keybindings/actions.ts +1 -1
  16. package/src/app/runtime/update.ts +38 -2
  17. package/src/app.tsx +10 -6
  18. package/src/brokers/account-cache.ts +24 -0
  19. package/src/cli/commands/command-utils.ts +8 -0
  20. package/src/cli/commands/crypto-hints.ts +75 -0
  21. package/src/cli/commands/market.ts +414 -106
  22. package/src/cli/commands/overview.ts +77 -32
  23. package/src/cli/commands/ticker.ts +101 -43
  24. package/src/cli/desktop-pane-shot.ts +34 -4
  25. package/src/cli/freshness.ts +61 -0
  26. package/src/cli/help.ts +1 -0
  27. package/src/cli/helpers.ts +4 -8
  28. package/src/cli/index.ts +12 -2
  29. package/src/cli/listing-arg.ts +321 -0
  30. package/src/cli/pane-functions/access-gate.ts +42 -0
  31. package/src/cli/pane-functions/catalog.ts +28 -1
  32. package/src/cli/pane-functions/data.ts +3 -1
  33. package/src/cli/pane-functions/dom.ts +20 -2
  34. package/src/cli/pane-functions/freshness.ts +400 -0
  35. package/src/cli/pane-functions/function-help.ts +36 -22
  36. package/src/cli/pane-functions/headless.ts +39 -11
  37. package/src/cli/pane-functions/index.ts +15 -4
  38. package/src/cli/pane-functions/options.ts +3 -0
  39. package/src/cli/pane-functions/report.ts +4 -0
  40. package/src/cli/pane-functions/resolver.ts +35 -7
  41. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  42. package/src/cli/pane-functions/screenshot.ts +7 -3
  43. package/src/cli/result.ts +41 -27
  44. package/src/cli/ticker-resolution.ts +7 -5
  45. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  46. package/src/components/chart/composite/drawing-store.ts +59 -0
  47. package/src/components/chart/composite/legend.tsx +319 -0
  48. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  49. package/src/components/chart/composite/panel-gestures.ts +59 -0
  50. package/src/components/chart/composite/panel-labels.ts +107 -0
  51. package/src/components/chart/composite/panel-surface.tsx +876 -0
  52. package/src/components/chart/composite/tool-catalog.ts +98 -0
  53. package/src/components/chart/composite/toolbar.tsx +186 -0
  54. package/src/components/chart/composite/tools.ts +8 -0
  55. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  56. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  57. package/src/components/command-bar/commands/collection.ts +5 -1
  58. package/src/components/command-bar/list/model.ts +5 -0
  59. package/src/components/command-bar/list/view.tsx +16 -3
  60. package/src/components/command-bar/pane-templates/workflow.ts +1 -0
  61. package/src/components/command-bar/routes/root/command-items.ts +9 -2
  62. package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
  63. package/src/components/command-bar/routes/root/provider-search.ts +19 -5
  64. package/src/components/command-bar/routes/root/runtime.ts +14 -5
  65. package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
  66. package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
  67. package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
  68. package/src/components/command-bar/routing/actions.ts +2 -0
  69. package/src/components/command-bar/selection-runtime.ts +38 -0
  70. package/src/components/command-bar/surface/index.tsx +7 -2
  71. package/src/components/command-bar/workflow/ops.ts +1 -1
  72. package/src/components/command-bar/workflow/tickers.ts +6 -0
  73. package/src/components/data-table/view.tsx +29 -10
  74. package/src/components/feedback-dialog.tsx +2 -1
  75. package/src/components/form-modal/field-row.tsx +2 -2
  76. package/src/components/index.ts +2 -2
  77. package/src/components/layout/detached-pane-shell.tsx +6 -3
  78. package/src/components/layout/floating-pane.tsx +6 -0
  79. package/src/components/layout/header.tsx +24 -7
  80. package/src/components/layout/missing-pane.tsx +2 -2
  81. package/src/components/layout/pane/content.tsx +23 -10
  82. package/src/components/layout/pane/error-boundary.tsx +103 -0
  83. package/src/components/layout/pane/footer/registration.tsx +68 -23
  84. package/src/components/layout/pane/header.tsx +61 -28
  85. package/src/components/layout/pane/index.tsx +6 -0
  86. package/src/components/layout/pane/title.ts +31 -7
  87. package/src/components/layout/shell/drag/index.ts +6 -5
  88. package/src/components/layout/shell/drag/runtime.ts +3 -0
  89. package/src/components/layout/shell/index.tsx +6 -0
  90. package/src/components/layout/shell/menu.ts +2 -1
  91. package/src/components/layout/shell/pane/actions.ts +2 -1
  92. package/src/components/layout/shell/pane/layers.tsx +29 -10
  93. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
  94. package/src/components/layout/shell/ticker-link-menu.ts +23 -9
  95. package/src/components/metric-treemap/heat-surface.tsx +745 -0
  96. package/src/components/metric-treemap/heat-tiles.ts +228 -0
  97. package/src/components/metric-treemap/index.tsx +2 -0
  98. package/src/components/metric-treemap/layout.ts +8 -0
  99. package/src/components/metric-treemap/scene.ts +432 -0
  100. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  101. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  102. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  103. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  104. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  105. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
  106. package/src/components/ticker/list-table-view.tsx +13 -1
  107. package/src/components/toggle-list.tsx +38 -12
  108. package/src/components/ui/country-flag-art.tsx +449 -0
  109. package/src/components/ui/country-flag.tsx +41 -0
  110. package/src/components/ui/data-table/types.ts +13 -0
  111. package/src/components/ui/fields.tsx +8 -0
  112. package/src/components/ui/icon.tsx +2 -0
  113. package/src/components/ui/index.ts +4 -0
  114. package/src/components/ui/multi-select/dialog.tsx +108 -22
  115. package/src/components/ui/range-track.tsx +53 -0
  116. package/src/components/ui/status.tsx +8 -2
  117. package/src/components/ui/tabs.tsx +11 -4
  118. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  119. package/src/core/state/app/types.ts +10 -1
  120. package/src/data/config/store/normalize.ts +17 -1
  121. package/src/i18n/es.ts +24 -4
  122. package/src/i18n/ja.ts +24 -4
  123. package/src/i18n/ko.ts +24 -4
  124. package/src/i18n/zh-cn.ts +24 -4
  125. package/src/i18n/zh-tw.ts +24 -4
  126. package/src/layout/ticker-navigation.ts +28 -2
  127. package/src/market-data/coordinator/chart.ts +1 -1
  128. package/src/market-data/coordinator/quotes.ts +23 -4
  129. package/src/market-data/fx-closes.ts +72 -0
  130. package/src/market-data/market/freshness.ts +78 -6
  131. package/src/market-data/market/session-close-note.ts +57 -0
  132. package/src/market-data/market/status.ts +151 -0
  133. package/src/market-data/published-apac-sessions.ts +66 -0
  134. package/src/market-data/quotes/contributions.ts +8 -0
  135. package/src/market-data/quotes/freshness.ts +36 -0
  136. package/src/market-data/quotes/resolution.ts +24 -8
  137. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  138. package/src/market-data/quotes/time.ts +16 -0
  139. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  140. package/src/plugins/builtin/alerts/cli.ts +10 -5
  141. package/src/plugins/builtin/alerts/index.tsx +1 -0
  142. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  143. package/src/plugins/builtin/analytics/risk-client.ts +330 -79
  144. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  145. package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
  146. package/src/plugins/builtin/analytics/risk-math.ts +33 -13
  147. package/src/plugins/builtin/analytics/risk-model.ts +282 -64
  148. package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
  149. package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
  150. package/src/plugins/builtin/attention/headless.ts +6 -4
  151. package/src/plugins/builtin/attention/index.tsx +1 -1
  152. package/src/plugins/builtin/attention/pane.tsx +1 -1
  153. package/src/plugins/builtin/awards/headless.ts +1 -0
  154. package/src/plugins/builtin/awards/pane.tsx +1 -1
  155. package/src/plugins/builtin/backtest/headless.ts +1 -0
  156. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  157. package/src/plugins/builtin/buildout/cells.tsx +15 -12
  158. package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
  159. package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
  160. package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
  161. package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
  162. package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
  163. package/src/plugins/builtin/buildout/index.tsx +1 -0
  164. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  165. package/src/plugins/builtin/catalysts/index.tsx +2 -2
  166. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  167. package/src/plugins/builtin/cds/headless.ts +2 -0
  168. package/src/plugins/builtin/cds/index.tsx +1 -0
  169. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  170. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  171. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  172. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  173. package/src/plugins/builtin/chat/channels.ts +19 -3
  174. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  175. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  176. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  177. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  178. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  179. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  180. package/src/plugins/builtin/chat/index.tsx +1 -0
  181. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  182. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  183. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  184. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  185. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  186. package/src/plugins/builtin/chat/message/types.ts +14 -2
  187. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  188. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  189. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  190. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  191. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  192. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  193. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  194. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  195. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  196. package/src/plugins/builtin/company-attention/pane.tsx +1 -1
  197. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  198. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  199. package/src/plugins/builtin/correlation/compute.ts +59 -16
  200. package/src/plugins/builtin/correlation/geo.ts +34 -0
  201. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  202. package/src/plugins/builtin/correlation/headless.ts +42 -8
  203. package/src/plugins/builtin/correlation/history.ts +2 -0
  204. package/src/plugins/builtin/correlation/index.tsx +68 -14
  205. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  206. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  207. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  208. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  209. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  210. package/src/plugins/builtin/correlation/settings.ts +1 -1
  211. package/src/plugins/builtin/cot/headless.ts +6 -3
  212. package/src/plugins/builtin/cot/index.tsx +3 -3
  213. package/src/plugins/builtin/cot/model.ts +36 -3
  214. package/src/plugins/builtin/cpi/headless.ts +4 -0
  215. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  216. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  217. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  218. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  219. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  220. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  221. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  222. package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
  223. package/src/plugins/builtin/dividend-yield/client.ts +4 -2
  224. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  225. package/src/plugins/builtin/doe/headless.ts +7 -0
  226. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  227. package/src/plugins/builtin/earnings/client.ts +2 -2
  228. package/src/plugins/builtin/earnings/headless.ts +5 -0
  229. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  230. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  231. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  232. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  233. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  234. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  235. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  236. package/src/plugins/builtin/econ/index.tsx +1 -0
  237. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  238. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  239. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  240. package/src/plugins/builtin/executives/index.tsx +1 -0
  241. package/src/plugins/builtin/exposure/headless.ts +3 -1
  242. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  243. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  244. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  245. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  246. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  247. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  248. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  249. package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
  250. package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
  251. package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
  252. package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
  253. package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
  254. package/src/plugins/builtin/gpu/headless.ts +7 -3
  255. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  256. package/src/plugins/builtin/gpu/model.ts +27 -1
  257. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  258. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  259. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  260. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  261. package/src/plugins/builtin/holders/headless.ts +139 -5
  262. package/src/plugins/builtin/holders/index.tsx +10 -3
  263. package/src/plugins/builtin/holders/pane.tsx +20 -3
  264. package/src/plugins/builtin/holders/report-header.ts +95 -0
  265. package/src/plugins/builtin/holders/table-model.ts +20 -5
  266. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  267. package/src/plugins/builtin/holders/types.ts +2 -1
  268. package/src/plugins/builtin/insider/headless.ts +2 -0
  269. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  270. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  271. package/src/plugins/builtin/jobs/headless.ts +1 -0
  272. package/src/plugins/builtin/jobs/index.tsx +1 -0
  273. package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
  274. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  275. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  276. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  277. package/src/plugins/builtin/market-heatmap/data.ts +30 -2
  278. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  279. package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
  280. package/src/plugins/builtin/market-heatmap/live.ts +88 -0
  281. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  282. package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
  283. package/src/plugins/builtin/market-movers/client.ts +3 -2
  284. package/src/plugins/builtin/market-movers/headless.ts +10 -1
  285. package/src/plugins/builtin/market-movers/screener.ts +18 -5
  286. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  287. package/src/plugins/builtin/members/client.ts +53 -0
  288. package/src/plugins/builtin/members/headless.ts +35 -0
  289. package/src/plugins/builtin/members/index.tsx +20 -0
  290. package/src/plugins/builtin/members/model.ts +68 -0
  291. package/src/plugins/builtin/members/pane.tsx +175 -0
  292. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  293. package/src/plugins/builtin/mna/headless.ts +1 -0
  294. package/src/plugins/builtin/mna/index.tsx +2 -1
  295. package/src/plugins/builtin/mna/pane.tsx +5 -2
  296. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  297. package/src/plugins/builtin/news/headless.ts +2 -0
  298. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  299. package/src/plugins/builtin/notes/cli.ts +14 -6
  300. package/src/plugins/builtin/notes/index.tsx +1 -0
  301. package/src/plugins/builtin/openfda/index.tsx +1 -0
  302. package/src/plugins/builtin/options/index.tsx +2 -1
  303. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  304. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  305. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  306. package/src/plugins/builtin/pe-band/client.ts +74 -2
  307. package/src/plugins/builtin/pe-band/headless.ts +26 -8
  308. package/src/plugins/builtin/pe-band/model.ts +102 -22
  309. package/src/plugins/builtin/pe-band/pane.tsx +34 -16
  310. package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
  311. package/src/plugins/builtin/perps/client.ts +66 -5
  312. package/src/plugins/builtin/perps/equity-identity.ts +16 -0
  313. package/src/plugins/builtin/perps/equity-row.tsx +6 -4
  314. package/src/plugins/builtin/perps/headless.ts +144 -16
  315. package/src/plugins/builtin/perps/index.tsx +6 -6
  316. package/src/plugins/builtin/perps/model.ts +189 -12
  317. package/src/plugins/builtin/perps/pane.tsx +248 -47
  318. package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
  319. package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
  320. package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
  321. package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
  322. package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
  323. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  324. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  325. package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
  326. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  327. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  328. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  329. package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
  330. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  331. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  332. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  333. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  334. package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
  335. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
  336. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
  337. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  338. package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
  339. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  340. package/src/plugins/builtin/power/headless.ts +3 -1
  341. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  342. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  343. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  344. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  345. package/src/plugins/builtin/research/events-headless.ts +2 -0
  346. package/src/plugins/builtin/research/headless.ts +2 -0
  347. package/src/plugins/builtin/research/index.tsx +1 -0
  348. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  349. package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
  350. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  351. package/src/plugins/builtin/research-search/index.tsx +1 -0
  352. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  353. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  354. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  355. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  356. package/src/plugins/builtin/scanner/headless.ts +14 -0
  357. package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
  358. package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
  359. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  360. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  361. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  362. package/src/plugins/builtin/sec/forms.ts +12 -0
  363. package/src/plugins/builtin/sec/headless.ts +2 -0
  364. package/src/plugins/builtin/sectors/client.ts +1 -0
  365. package/src/plugins/builtin/sectors/headless.ts +9 -1
  366. package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
  367. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  368. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  369. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  370. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  371. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  372. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  373. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  374. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  375. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  376. package/src/plugins/builtin/social-mentions/index.tsx +1 -1
  377. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  378. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  379. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  380. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  381. package/src/plugins/builtin/themes/headless.ts +3 -0
  382. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  383. package/src/plugins/builtin/thirteenf/index.tsx +2 -1
  384. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  385. package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
  386. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  387. package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
  388. package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
  389. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
  390. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
  391. package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
  392. package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
  393. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
  394. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
  395. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  396. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  397. package/src/plugins/builtin/vol-surface/index.tsx +1 -1
  398. package/src/plugins/builtin/volatility/headless.ts +6 -1
  399. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  400. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
  401. package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
  402. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  403. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  404. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  405. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  406. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  407. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  408. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  409. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
  410. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  411. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  412. package/src/plugins/builtin/world-venue-map/index.ts +67 -4
  413. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
  414. package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
  415. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  416. package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
  417. package/src/plugins/builtin/world-venue-map/model.ts +7 -4
  418. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  564. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  565. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  566. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  567. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  568. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  569. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  570. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  571. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  572. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  573. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  574. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  575. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  576. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  577. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  578. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  579. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  580. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  581. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  582. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  583. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  584. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  585. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  586. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  587. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  588. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  589. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  590. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  591. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  592. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  593. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  594. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  595. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  596. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  597. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  598. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  599. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  600. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  601. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  602. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  603. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  604. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  605. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  606. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  607. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  608. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  609. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  610. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  611. package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
  612. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  613. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  614. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  615. package/src/plugins/catalog-browser.ts +2 -0
  616. package/src/plugins/catalog-manifest.ts +1 -0
  617. package/src/plugins/catalog-ui.ts +3 -1
  618. package/src/plugins/catalog.ts +1 -1
  619. package/src/plugins/host-link.ts +33 -1
  620. package/src/plugins/installer.ts +48 -12
  621. package/src/plugins/loader.ts +30 -3
  622. package/src/plugins/manager-node.ts +15 -5
  623. package/src/plugins/registry/index.ts +1 -1
  624. package/src/plugins/registry/pane-settings.ts +26 -7
  625. package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
  626. package/src/renderers/dom/build-assets.ts +81 -3
  627. package/src/renderers/dom/data-table/row.tsx +52 -16
  628. package/src/renderers/dom/desktop/controls.tsx +7 -3
  629. package/src/renderers/dom/desktop/icons.tsx +1 -0
  630. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  631. package/src/renderers/dom/desktop/popover.tsx +73 -14
  632. package/src/renderers/dom/host/box.tsx +69 -26
  633. package/src/renderers/dom/host/input.tsx +14 -3
  634. package/src/renderers/dom/host/tabs.tsx +37 -1
  635. package/src/renderers/dom/styles.css +41 -7
  636. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
  638. package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
  639. package/src/renderers/electrobun/bun/index.ts +73 -6
  640. package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
  641. package/src/renderers/electrobun/shared/protocol.ts +3 -0
  642. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  643. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
  644. package/src/renderers/electrobun/view/main.tsx +7 -1
  645. package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
  646. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  647. package/src/renderers/electrobun/view/update-host.ts +45 -21
  648. package/src/renderers/opentui/host.tsx +5 -0
  649. package/src/sources/gloomberb-cloud/index.ts +25 -4
  650. package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
  651. package/src/sources/provider-router/cached-routes.ts +4 -1
  652. package/src/sources/provider-router/financials.ts +11 -8
  653. package/src/sources/provider-router/history.ts +15 -10
  654. package/src/sources/sec-registrant.ts +75 -0
  655. package/src/state/app/context/index.tsx +24 -8
  656. package/src/state/hooks/quote-streaming.ts +41 -26
  657. package/src/sync/core-contributors.ts +4 -0
  658. package/src/telemetry/benign-window-error.ts +7 -0
  659. package/src/telemetry/crash-reports-dom.ts +2 -0
  660. package/src/telemetry/crash-reports.ts +4 -1
  661. package/src/test-support/cli-context.ts +10 -2
  662. package/src/test-support/daily-nav.ts +25 -0
  663. package/src/theme/heat-colors.ts +357 -2
  664. package/src/tickers/instrument-kind.ts +34 -7
  665. package/src/tickers/search/asset-classes.ts +24 -9
  666. package/src/tickers/search/index.ts +44 -11
  667. package/src/tickers/search/ranking.ts +23 -3
  668. package/src/time-series/resolve.ts +1 -1
  669. package/src/time-series/use-chart-resolution.ts +1 -1
  670. package/src/types/context-menu.ts +6 -0
  671. package/src/types/data-provider.ts +2 -0
  672. package/src/types/financials.ts +5 -0
  673. package/src/types/headless.ts +79 -2
  674. package/src/types/plugin.ts +38 -6
  675. package/src/types/ticker.ts +15 -0
  676. package/src/ui/context-menu.tsx +1 -0
  677. package/src/ui/host.tsx +16 -0
  678. package/src/updater/index.ts +38 -13
  679. package/src/utils/async-deadline.ts +21 -0
  680. package/src/utils/cli-output.ts +5 -1
  681. package/src/utils/crypto-pair.ts +41 -0
  682. package/src/utils/currency-units.ts +14 -0
  683. package/src/utils/depositary-receipt.ts +26 -0
  684. package/src/utils/exchanges.ts +72 -0
  685. package/src/utils/fire-and-forget.ts +24 -0
  686. package/src/utils/format.ts +13 -0
  687. package/src/utils/price-earnings.ts +70 -3
  688. package/src/utils/price-history.ts +58 -13
  689. package/src/utils/rpc-timeout-error.ts +27 -0
  690. package/src/utils/sec.ts +13 -1
  691. package/src/utils/utc-time.ts +79 -0
@@ -1,4 +1,4 @@
1
- import { Box, Text, useUiCapabilities } from "../../../ui";
1
+ import { Box, Text, useUiCapabilities, type InputRenderable } from "../../../ui";
2
2
  import { TextAttributes } from "../../../ui";
3
3
  import { useShortcut, useViewport } from "../../../react/input";
4
4
  import { type AlertContext, useDialog, useDialogKeyboard } from "../../../ui/dialog";
@@ -18,6 +18,7 @@ import { isDetailBackNavigationKey } from "../../../utils/back-navigation";
18
18
  import { isPlainKeyboardEvent } from "../../../utils/keyboard";
19
19
  import { ToggleList } from "../../toggle-list";
20
20
  import { Button } from "../button";
21
+ import { TextField } from "../fields";
21
22
  import { listCursorMove } from "../list-view";
22
23
  import { DialogFrame } from "../frame";
23
24
  import { Popover } from "../popover";
@@ -64,6 +65,13 @@ export interface MultiSelectDialogContentProps extends AlertContext {
64
65
  emptyLabel?: string;
65
66
  idPrefix?: string;
66
67
  rowAction?: MultiSelectRowAction;
68
+ /**
69
+ * For a long list: a filter box over the rows (typing narrows them by label
70
+ * and description), each description beside its label and, when ordered,
71
+ * each selection's position at the row's end. The keyboard stays with the
72
+ * box: arrows move, Space picks, [ and ] reorder, Enter is done.
73
+ */
74
+ searchable?: boolean;
67
75
  }
68
76
 
69
77
  export interface MultiSelectDialogButtonProps {
@@ -82,6 +90,8 @@ export interface MultiSelectDialogButtonProps {
82
90
  onOpenChange?: (open: boolean) => void;
83
91
  /** Opens the dialog on desktop too, since the popover menu has no row actions. */
84
92
  rowAction?: MultiSelectRowAction;
93
+ /** A filter box over the rows; opens the dialog on desktop too, since the popover menu has none. */
94
+ searchable?: boolean;
85
95
  }
86
96
 
87
97
  export interface MultiSelectPopoverAnchorPoint {
@@ -118,6 +128,26 @@ function stopMouseEvent(event?: DialogTriggerEvent) {
118
128
  const DESKTOP_ROW_HEIGHT = 1.35;
119
129
  /** Terminal rows the dialog spends around its list: frame, title, buttons. */
120
130
  const TERMINAL_DIALOG_CHROME_ROWS = 10;
131
+ /** Cells a searchable list shows on the desktop and web; the rest scrolls. */
132
+ const DESKTOP_SEARCHABLE_LIST_CELLS = 16;
133
+
134
+ /** A key that types a character: the filter box takes it. */
135
+ function isTextKey(event: { sequence?: string; ctrl?: boolean; meta?: boolean; alt?: boolean }): boolean {
136
+ return event.sequence?.length === 1 && event.sequence >= " " && event.sequence !== "\u007f"
137
+ && !event.ctrl && !event.meta && !event.alt;
138
+ }
139
+
140
+ function matchesFilter(option: MultiSelectOption, needle: string): boolean {
141
+ return `${option.label} ${option.description ?? ""}`.toLowerCase().includes(needle);
142
+ }
143
+
144
+ /** The picks in their order, then every other option in the order given. */
145
+ function selectedFirstOptions(options: readonly MultiSelectOption[], selectedValues: readonly string[]): MultiSelectOption[] {
146
+ const byValue = new Map(options.map((option) => [option.value, option]));
147
+ const picked = selectedValues.flatMap((value) => byValue.get(value) ?? []);
148
+ const chosen = new Set(picked.map((option) => option.value));
149
+ return [...picked, ...options.filter((option) => !chosen.has(option.value))];
150
+ }
121
151
 
122
152
  type FocusedNode = { blur?(): void; closest?(selector: string): unknown };
123
153
 
@@ -219,19 +249,32 @@ export function MultiSelectDialogContent({
219
249
  ordered = false,
220
250
  idPrefix,
221
251
  rowAction,
252
+ searchable = false,
222
253
  }: MultiSelectDialogContentProps) {
223
254
  const isDesktopWeb = useUiCapabilities().nativePaneChrome === true;
224
255
  const optionByValue = useMemo(() => new Map(options.map((option) => [option.value, option])), [options]);
225
256
  const [selectedValues, setSelectedValues] = useState(() => normalizeDialogSelectedValues(options, selectedValuesProp, ordered));
226
257
  const [displayValues, setDisplayValues] = useState(() => getMultiSelectDisplayValues(options, selectedValuesProp, ordered));
227
258
  const knownSelectedValues = selectedValues.filter((value) => optionByValue.has(value));
259
+ // A long ordered list reads as the list being built on top, the rest below;
260
+ // a short one keeps every option in its row and swaps the picks among them.
261
+ const selectedFirst = searchable && ordered;
228
262
  const displayOptions = useMemo(
229
- () => orderMultiSelectOptionsForDisplay(options, displayValues),
230
- [displayValues, options],
263
+ () => (selectedFirst
264
+ ? selectedFirstOptions(options, selectedValues)
265
+ : orderMultiSelectOptionsForDisplay(options, displayValues)),
266
+ [displayValues, options, selectedFirst, selectedValues],
267
+ );
268
+ const [filter, setFilter] = useState("");
269
+ const filterRef = useRef<InputRenderable | null>(null);
270
+ const needle = searchable ? filter.trim().toLowerCase() : "";
271
+ const visibleOptions = useMemo(
272
+ () => (needle ? displayOptions.filter((option) => matchesFilter(option, needle)) : displayOptions),
273
+ [displayOptions, needle],
231
274
  );
232
275
  const [selectedOptionId, setSelectedOptionId] = useState(options[0]?.value ?? "");
233
- const selectedIndex = Math.max(0, displayOptions.findIndex((option) => option.value === selectedOptionId));
234
- const selectedOption = displayOptions[selectedIndex];
276
+ const selectedIndex = Math.max(0, visibleOptions.findIndex((option) => option.value === selectedOptionId));
277
+ const selectedOption = visibleOptions[selectedIndex];
235
278
  const selectedOptionValue = selectedOption?.value ?? "";
236
279
  const selectedValueOrder = knownSelectedValues.indexOf(selectedOptionValue);
237
280
  const canMoveUp = ordered && selectedValueOrder > 0;
@@ -258,7 +301,14 @@ export function MultiSelectDialogContent({
258
301
  setSelectedOptionId(displayOptions[0]?.value ?? "");
259
302
  }, [displayOptions, selectedOptionId]);
260
303
 
261
- const toggleItems = displayOptions.map((option) => {
304
+ // A touch screen would raise its keyboard over the list the moment it opens.
305
+ useEffect(() => {
306
+ if (!searchable || (globalThis as { matchMedia?: (query: string) => { matches: boolean } }).matchMedia?.("(pointer: coarse)").matches) return;
307
+ const timer = setTimeout(() => filterRef.current?.focus?.(), 0);
308
+ return () => clearTimeout(timer);
309
+ }, [searchable]);
310
+
311
+ const toggleItems = visibleOptions.map((option) => {
262
312
  const order = knownSelectedValues.indexOf(option.value);
263
313
  const orderDescription = ordered && order >= 0
264
314
  ? `Order ${order + 1} of ${knownSelectedValues.length}.`
@@ -269,15 +319,19 @@ export function MultiSelectDialogContent({
269
319
  label: labelOverrides[option.value] ?? option.label,
270
320
  disabled: option.disabled,
271
321
  enabled: selectedValues.includes(option.value),
272
- description: [option.description, orderDescription].filter((entry): entry is string => !!entry).join(" "),
322
+ description: searchable
323
+ ? option.description
324
+ : [option.description, orderDescription].filter((entry): entry is string => !!entry).join(" "),
325
+ detail: searchable && ordered && order >= 0 ? String(order + 1) : undefined,
273
326
  };
274
327
  });
275
328
  const viewport = useViewport();
276
329
  // A short terminal would clip rows under the dialog's edge: the list scrolls
277
- // in whatever height is left.
330
+ // in whatever height is left. The height follows the whole list, not the rows
331
+ // the filter leaves, so typing does not make the dialog jump.
278
332
  const listHeight = isDesktopWeb
279
- ? Math.min(12, Math.max(5, displayOptions.length * DESKTOP_ROW_HEIGHT))
280
- : Math.max(3, Math.min(12, Math.max(6, toggleItems.length), viewport.height - TERMINAL_DIALOG_CHROME_ROWS));
333
+ ? Math.min(searchable ? DESKTOP_SEARCHABLE_LIST_CELLS : 12, Math.max(5, displayOptions.length * DESKTOP_ROW_HEIGHT))
334
+ : Math.max(3, Math.min(12, Math.max(6, displayOptions.length), viewport.height - TERMINAL_DIALOG_CHROME_ROWS - (searchable ? 2 : 0)));
281
335
  const pageSize = Math.floor(listHeight / (isDesktopWeb ? DESKTOP_ROW_HEIGHT : 1)) - 1;
282
336
 
283
337
  const applySelectedValues = async (nextValues: string[], nextDisplayValues = displayValues) => {
@@ -296,16 +350,23 @@ export function MultiSelectDialogContent({
296
350
 
297
351
  const toggleOption = async (option: MultiSelectOption | undefined) => {
298
352
  if (!option || option.disabled) return;
299
- await applySelectedValues(ordered
353
+ const nextValues = ordered
300
354
  ? toggleOrderedMultiSelectValue(options, selectedValues, option.value)
301
- : toggleMultiSelectValue(options, selectedValues, option.value));
355
+ : toggleMultiSelectValue(options, selectedValues, option.value);
356
+ const row = visibleOptions.findIndex((entry) => entry.value === option.value);
357
+ await applySelectedValues(nextValues);
358
+ if (!selectedFirst) return;
359
+ // The row moved between the picks and the rest. The cursor stays on its
360
+ // line, so Space picks or drops a row and moves on to the next.
361
+ const next = selectedFirstOptions(options, nextValues).filter((entry) => !needle || matchesFilter(entry, needle));
362
+ setSelectedOptionId(next[Math.min(Math.max(row, 0), next.length - 1)]?.value ?? option.value);
302
363
  };
303
364
 
304
365
  const moveOption = async (direction: "up" | "down") => {
305
366
  if (!ordered || !selectedOption) return;
306
367
  await applySelectedValues(
307
368
  moveMultiSelectValue(options, selectedValues, selectedOption.value, direction),
308
- moveMultiSelectDisplayValue(displayValues, knownSelectedValues, selectedOption.value, direction),
369
+ selectedFirst ? displayValues : moveMultiSelectDisplayValue(displayValues, knownSelectedValues, selectedOption.value, direction),
309
370
  );
310
371
  };
311
372
 
@@ -318,11 +379,24 @@ export function MultiSelectDialogContent({
318
379
  };
319
380
 
320
381
  useDialogKeyboard((event) => {
382
+ if (searchable) {
383
+ // The box owns every key that types or edits text; the list keeps the rest.
384
+ const typing = event.targetEditable === true;
385
+ const editsText = isTextKey(event) ? event.sequence !== " " && event.name !== "[" && event.name !== "]"
386
+ : typing && ["backspace", "delete", "left", "right", "home", "end"].includes(event.name ?? "");
387
+ const backsUp = !typing && filter !== "" && (event.name === "backspace" || event.name === "delete");
388
+ if (editsText || backsUp) {
389
+ // A click on a row or button took the focus; the first key typed brings it back.
390
+ if (!typing) filterRef.current?.focus?.();
391
+ return;
392
+ }
393
+ if (isSpaceKey(event)) event.preventDefault();
394
+ }
321
395
  event.stopPropagation();
322
396
  const move = listCursorMove(event, pageSize);
323
397
  if (move) {
324
- if (isDesktopWeb) releaseFocusOutsideList();
325
- setSelectedOptionId(displayOptions[move(displayOptions, selectedIndex)]?.value ?? selectedOptionId);
398
+ if (isDesktopWeb && !searchable) releaseFocusOutsideList();
399
+ setSelectedOptionId(visibleOptions[move(visibleOptions, selectedIndex)]?.value ?? selectedOptionId);
326
400
  } else if (isSpaceKey(event)) {
327
401
  void toggleOption(selectedOption).catch(() => {});
328
402
  } else if (event.name === "[" && ordered) {
@@ -334,15 +408,24 @@ export function MultiSelectDialogContent({
334
408
  } else if (event.name === "enter" || event.name === "return" || event.name === "escape" || isDetailBackNavigationKey(event)) {
335
409
  dismiss();
336
410
  }
337
- }, dialogId);
411
+ }, searchable ? { scope: dialogId, allowEditable: true } : dialogId);
338
412
 
339
413
  return (
340
414
  <DialogFrame title={title} showTitleDivider={!isDesktopWeb}>
341
415
  <Box
342
416
  flexDirection="column"
343
417
  gap={1}
344
- style={isDesktopWeb ? { minWidth: 520 } : undefined}
418
+ style={isDesktopWeb ? { minWidth: "min(520px, calc(100vw - 96px))" } : undefined}
345
419
  >
420
+ {searchable && (
421
+ <TextField
422
+ inputRef={filterRef}
423
+ value={filter}
424
+ placeholder="Filter"
425
+ focused
426
+ onChange={setFilter}
427
+ />
428
+ )}
346
429
  <ToggleList
347
430
  items={toggleItems}
348
431
  selectedIdx={selectedIndex}
@@ -350,11 +433,12 @@ export function MultiSelectDialogContent({
350
433
  height={listHeight}
351
434
  scrollable
352
435
  showSelectedDescription={false}
436
+ showDescriptions={searchable}
353
437
  rowIdPrefix={idPrefix ? `${idPrefix}:option` : undefined}
354
438
  rowGap={isDesktopWeb ? 0 : undefined}
355
439
  rowHeight={isDesktopWeb ? DESKTOP_ROW_HEIGHT : undefined}
356
440
  surface={isDesktopWeb ? "plain" : undefined}
357
- onSelect={(index) => setSelectedOptionId(displayOptions[index]?.value ?? selectedOptionId)}
441
+ onSelect={(index) => setSelectedOptionId(visibleOptions[index]?.value ?? selectedOptionId)}
358
442
  onToggle={(id) => {
359
443
  setSelectedOptionId(id);
360
444
  void toggleOption(optionByValue.get(id)).catch(() => {});
@@ -364,7 +448,7 @@ export function MultiSelectDialogContent({
364
448
  flexDirection="row"
365
449
  gap={1}
366
450
  justifyContent={isDesktopWeb ? "flex-end" : undefined}
367
- style={isDesktopWeb ? { paddingTop: 6 } : undefined}
451
+ style={isDesktopWeb ? { paddingTop: 6, flexWrap: "wrap" } : undefined}
368
452
  >
369
453
  {ordered && (
370
454
  <>
@@ -403,6 +487,7 @@ function MultiSelectDialogButtonInner({
403
487
  shortcutActive = false,
404
488
  onOpenChange,
405
489
  rowAction,
490
+ searchable = false,
406
491
  }: MultiSelectDialogButtonProps, ref: ForwardedRef<MultiSelectDialogButtonHandle>) {
407
492
  const isDesktopWeb = useUiCapabilities().nativePaneChrome === true;
408
493
  const dialog = useDialog();
@@ -415,7 +500,7 @@ function MultiSelectDialogButtonInner({
415
500
  const openDialog = useCallback((event?: DialogTriggerEvent, anchorPoint?: MultiSelectPopoverAnchorPoint) => {
416
501
  stopMouseEvent(event);
417
502
  if (disabled) return;
418
- if (isDesktopWeb && !ordered && !rowAction) {
503
+ if (isDesktopWeb && !ordered && !rowAction && !searchable) {
419
504
  setPopoverAnchorPoint(anchorPoint ?? null);
420
505
  setPopoverOpen(true);
421
506
  onOpenChange?.(true);
@@ -435,10 +520,11 @@ function MultiSelectDialogButtonInner({
435
520
  emptyLabel={emptyLabel}
436
521
  idPrefix={idPrefix}
437
522
  rowAction={rowAction}
523
+ searchable={searchable}
438
524
  />
439
525
  ),
440
526
  }).catch(() => {}).finally(() => onOpenChange?.(false));
441
- }, [dialog, disabled, emptyLabel, idPrefix, isDesktopWeb, label, onChange, onOpenChange, options, ordered, rowAction, selectedValues, title]);
527
+ }, [dialog, disabled, emptyLabel, idPrefix, isDesktopWeb, label, onChange, onOpenChange, options, ordered, rowAction, searchable, selectedValues, title]);
442
528
 
443
529
  const closePopover = useCallback(() => {
444
530
  setPopoverOpen(false);
@@ -521,7 +607,7 @@ function MultiSelectDialogButtonInner({
521
607
  );
522
608
  }
523
609
 
524
- if (isDesktopWeb && !ordered && !rowAction) {
610
+ if (isDesktopWeb && !ordered && !rowAction && !searchable) {
525
611
  return (
526
612
  <Popover
527
613
  open={popoverOpen}
@@ -0,0 +1,53 @@
1
+ import { useThemeColors } from "../../theme/theme-context";
2
+ import { Box, Text, useUiCapabilities } from "../../ui";
3
+
4
+ export interface RangeTrackProps {
5
+ /** Where the value sits between the low and the high, 0 to 1. */
6
+ position: number;
7
+ /** Cells the track spans. */
8
+ width: number;
9
+ markerColor: string;
10
+ /**
11
+ * Mark a value past either end with an arrow at that end (a square on the
12
+ * desktop) instead of pinning the dot there, so it does not read as the low
13
+ * or the high itself.
14
+ */
15
+ outside?: boolean;
16
+ }
17
+
18
+ /**
19
+ * Where a value sits between a low and a high (a day range, a 52-week range):
20
+ * a rule with a dot on it. The caller draws the endpoints. The terminal draws
21
+ * a box-drawing rule; the desktop draws a real line and dot, never glyphs.
22
+ */
23
+ export function RangeTrack({ position, width, markerColor, outside = false }: RangeTrackProps) {
24
+ const colors = useThemeColors();
25
+ const isDesktopWeb = useUiCapabilities().nativePaneChrome === true;
26
+ const past = !outside ? null : position < 0 ? "below" : position > 1 ? "above" : null;
27
+ const at = position > 0 ? Math.min(1, position) : 0;
28
+ if (width <= 0) return null;
29
+ if (isDesktopWeb) {
30
+ return (
31
+ <Box width={width} height={1} flexShrink={0} style={{ position: "relative", justifyContent: "center" }} data-gloom-role="range-track">
32
+ <Box style={{ position: "absolute", left: 0, right: 0, height: "2px", borderRadius: "1px", backgroundColor: colors.border }} />
33
+ <Box style={{
34
+ position: "absolute",
35
+ left: `${at * 100}%`,
36
+ width: "8px",
37
+ height: "8px",
38
+ marginLeft: "-4px",
39
+ borderRadius: past ? "1px" : "50%",
40
+ backgroundColor: markerColor,
41
+ }} />
42
+ </Box>
43
+ );
44
+ }
45
+ const marker = Math.min(width - 1, Math.round(at * (width - 1)));
46
+ return (
47
+ <Box width={width} height={1} flexShrink={0} flexDirection="row">
48
+ <Text fg={colors.border}>{"─".repeat(marker)}</Text>
49
+ <Text fg={markerColor}>{past === "below" ? "◂" : past === "above" ? "▸" : "●"}</Text>
50
+ <Text fg={colors.border}>{"─".repeat(width - marker - 1)}</Text>
51
+ </Box>
52
+ );
53
+ }
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { t, tf } from "../../i18n";
3
3
  import { useThemeColors } from "../../theme/theme-context";
4
- import { Box, Text } from "../../ui";
4
+ import { Box, Text, useUiCapabilities } from "../../ui";
5
5
  import { Spinner } from "./loading";
6
6
  import { ButtonActionScope } from "./action-scope";
7
7
 
@@ -15,13 +15,19 @@ export interface EmptyStateProps {
15
15
 
16
16
  export function EmptyState({ title, message, hint, actions, status = "empty" }: EmptyStateProps) {
17
17
  const colors = useThemeColors();
18
+ const { nativePaneChrome } = useUiCapabilities();
18
19
  // Provider messages must wrap at narrow pane widths rather than lose their tail.
19
20
  return (
20
21
  <Box flexDirection="column" data-gloom-status={status} data-gloom-ui="empty-state">
21
22
  <Box><Text fg={status === "error" ? colors.negative : colors.textDim} wrapText>{t(title)}</Text></Box>
22
23
  {message && <Box><Text fg={colors.textMuted} wrapText>{t(message)}</Text></Box>}
23
24
  {hint && <Box><Text fg={colors.textMuted} wrapText>{t(hint)}</Text></Box>}
24
- {actions && <Box flexDirection="row" gap={1} marginTop={1}><ButtonActionScope>{actions}</ButtonActionScope></Box>}
25
+ {/* Wraps in a narrow pane rather than clipping the second action; a terminal wraps without a blank row. */}
26
+ {actions && (
27
+ <Box flexDirection="row" flexWrap="wrap" gap={1} rowGap={nativePaneChrome ? undefined : 0} marginTop={1}>
28
+ <ButtonActionScope>{actions}</ButtonActionScope>
29
+ </Box>
30
+ )}
25
31
  </Box>
26
32
  );
27
33
  }
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
2
- import { usePaneArrowClaim, usePaneMenuItems } from "../layout/pane/footer/registration";
2
+ import { usePaneMenuItems, usePaneTabStripKeys } from "../layout/pane/footer/registration";
3
3
  import type { ContextMenuItem } from "../../types/context-menu";
4
4
  import { useShortcut } from "../../react/input";
5
5
  import { Box, ScrollBox, Text, useNativeRenderer, useUiHost } from "../../ui";
@@ -43,6 +43,8 @@ export interface TabsProps {
43
43
  addLabel?: string;
44
44
  onAdd?: () => void;
45
45
  onReorder?: (fromValue: string, toValue: string) => void;
46
+ /** A press that moves, on a tab that is not reordered. Desktop title-bar tabs use it to move the window. */
47
+ onDrag?: () => void;
46
48
  focused?: boolean;
47
49
  keyboardNavigation?: boolean;
48
50
  /**
@@ -67,12 +69,17 @@ export function Tabs({
67
69
  addLabel = "+",
68
70
  onAdd,
69
71
  onReorder,
70
- focused = false,
72
+ onDrag,
73
+ focused: paneFocused = false,
71
74
  keyboardNavigation = true,
72
75
  paneMenu = true,
73
76
  scrollable = true,
74
77
  scrollId,
75
78
  }: TabsProps) {
79
+ // While a chart the user moved into holds the keys, the strip draws as
80
+ // unfocused, so it shows where the arrows went.
81
+ const stripKeys = usePaneTabStripKeys(keyboardNavigation, paneFocused);
82
+ const focused = paneFocused && !stripKeys.held;
76
83
  const language = useAppLanguage();
77
84
  const colors = useThemeColors();
78
85
  const tabs = useMemo(() => rawTabs.map((tab) => (
@@ -213,8 +220,7 @@ export function Tabs({
213
220
  event.stopPropagation();
214
221
  selectAdjacentTab(1);
215
222
  }
216
- }, { enabled: focused && keyboardNavigation });
217
- usePaneArrowClaim(focused && keyboardNavigation);
223
+ }, { enabled: stripKeys.active });
218
224
 
219
225
  if (NativeTabs) {
220
226
  return (
@@ -229,6 +235,7 @@ export function Tabs({
229
235
  addLabel={addLabel}
230
236
  onAdd={onAdd}
231
237
  onReorder={onReorder}
238
+ onDrag={onDrag}
232
239
  focused={focused}
233
240
  palette={palette}
234
241
  />
@@ -1,10 +1,10 @@
1
1
  import { useEffect, useRef, useState } from "react";
2
- import { Box, Text, Textarea, type InputRenderable, type TextareaRenderable } from "../../ui";
2
+ import { Box, Text, Textarea, useUiCapabilities, type InputRenderable, type TextareaRenderable } from "../../ui";
3
3
  import { t } from "../../i18n";
4
4
  import { useDialogKeyboard, type PromptContext } from "../../ui/dialog";
5
5
  import { useThemeColors } from "../../theme/theme-context";
6
6
  import { Button } from "./button";
7
- import { TextField } from "./fields";
7
+ import { FRAMED_TEXTAREA_DESKTOP_STYLE, TextField } from "./fields";
8
8
  import { DialogFrame } from "./frame";
9
9
 
10
10
  export interface TextPromptDialogProps extends PromptContext<string> {
@@ -48,6 +48,7 @@ export function TextPromptDialog({
48
48
  footer,
49
49
  }: TextPromptDialogProps) {
50
50
  const colors = useThemeColors();
51
+ const { nativePaneChrome } = useUiCapabilities();
51
52
  const inputRef = useRef<InputRenderable | null>(null);
52
53
  const textareaRef = useRef<TextareaRenderable | null>(null);
53
54
  const [value, setValue] = useState(initialValue);
@@ -97,6 +98,7 @@ export function TextPromptDialog({
97
98
  backgroundColor={colors.panel}
98
99
  flexGrow={1}
99
100
  wrapText
101
+ {...(nativePaneChrome ? { style: FRAMED_TEXTAREA_DESKTOP_STYLE } : {})}
100
102
  keyBindings={[
101
103
  { name: "return", action: "submit" },
102
104
  { name: "linefeed", action: "submit" },
@@ -45,10 +45,18 @@ interface CommandBarRunQueryLaunchRequest extends CommandBarLaunchRequestBase {
45
45
  query: string;
46
46
  }
47
47
 
48
+ /** The add row opened the bar so the chosen venue joins this collection. */
49
+ interface CommandBarAddListingLaunchRequest extends CommandBarLaunchRequestBase {
50
+ kind: "add-listing";
51
+ collectionId: string;
52
+ collectionKind: "watchlist" | "portfolio";
53
+ }
54
+
48
55
  /** Forms open in their own modal (`openFormModal`), so the bar launches only its own screens. */
49
56
  type CommandBarLaunch =
50
57
  | { kind: "ticker-search"; query?: string }
51
- | { kind: "run-query"; query: string };
58
+ | { kind: "run-query"; query: string }
59
+ | { kind: "add-listing"; collectionId: string; collectionKind: "watchlist" | "portfolio" };
52
60
 
53
61
  export interface AppState {
54
62
  config: AppConfig;
@@ -74,6 +82,7 @@ export interface AppState {
74
82
  commandBarLaunchRequest:
75
83
  | CommandBarTickerSearchLaunchRequest
76
84
  | CommandBarRunQueryLaunchRequest
85
+ | CommandBarAddListingLaunchRequest
77
86
  | null;
78
87
  themePreview: string | null;
79
88
  refreshing: Set<string>;
@@ -311,7 +311,23 @@ function sanitizePortfolios(value: unknown, fallback: Portfolio[]): Portfolio[]
311
311
  && typeof (entry as Portfolio).name === "string"
312
312
  && typeof (entry as Portfolio).currency === "string",
313
313
  )
314
- .map((entry) => ({ ...entry }));
314
+ .map(sanitizePortfolioAllocation);
315
+ }
316
+
317
+ /** Cash and target weights the portfolio commands write; anything else is dropped. */
318
+ function sanitizePortfolioAllocation(entry: Portfolio): Portfolio {
319
+ const { cash, targetWeights, ...portfolio } = entry;
320
+ const next: Portfolio = { ...portfolio };
321
+ if (isRecord(cash) && typeof cash.amount === "number" && Number.isFinite(cash.amount)
322
+ && typeof cash.currency === "string" && /^[A-Z]{3}$/.test(cash.currency)) {
323
+ next.cash = { amount: cash.amount, currency: cash.currency };
324
+ }
325
+ if (isRecord(targetWeights)) {
326
+ const weights = Object.entries(targetWeights).filter((weight): weight is [string, number] =>
327
+ !!weight[0].trim() && typeof weight[1] === "number" && Number.isFinite(weight[1]) && weight[1] >= 0 && weight[1] <= 100);
328
+ if (weights.length > 0) next.targetWeights = Object.fromEntries(weights);
329
+ }
330
+ return next;
315
331
  }
316
332
 
317
333
  function sanitizeWatchlists(value: unknown, fallback: Watchlist[]): Watchlist[] {
package/src/i18n/es.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * fixed-width terminal layouts stay readable.
6
6
  */
7
7
  export const es: Record<string, string> = {
8
+ "NAV · as of {date}": "NAV · al {date}",
8
9
  // ── Common UI ────────────────────────────────────────────────
9
10
  "Back": "Atrás",
10
11
  "Done": "Listo",
@@ -377,7 +378,6 @@ export const es: Record<string, string> = {
377
378
  "Price trigger alerts with notifications": "Alertas de precio con notificaciones",
378
379
  "Create a price alert from a symbol, condition, and target price": "Crear una alerta de precio con símbolo, condición y precio objetivo",
379
380
  "Public market heatmap for the largest US stocks and ETFs.": "Mapa de calor de las mayores acciones y ETF de EE. UU.",
380
- "Largest US stocks and ETFs, sized by market cap or assets and colored by daily move.": "Mayores acciones y ETF de EE. UU., dimensionados por capitalización o activos y coloreados por variación diaria.",
381
381
  "Top gainers, losers, most active, and trending tickers": "Mayores alzas, bajas, más activos y tickers en tendencia",
382
382
  "Top gainers, losers, most active, and trending tickers.": "Mayores alzas, bajas, más activos y tickers en tendencia.",
383
383
  "S&P 500 sector and industry performance via ETF proxies": "Rendimiento sectorial e industrial del S&P 500 vía ETF",
@@ -524,7 +524,7 @@ export const es: Record<string, string> = {
524
524
  "Quit the terminal app.": "Salir de la aplicación de terminal.",
525
525
  "Copy the active terminal selection.": "Copiar la selección activa del terminal.",
526
526
  "Paste clipboard text into the active input.": "Pegar el portapapeles en la entrada activa.",
527
- "Install an available app update when one is shown.": "Instalar una actualización disponible cuando se muestre.",
527
+ "Restart into a downloaded app update, or retry one that failed.": "Reinicia con una actualización descargada o reintenta una fallida.",
528
528
  "Close the focused pane, docked or floating.": "Cerrar el panel activo, anclado o flotante.",
529
529
  "Close all floating panes.": "Cerrar todos los paneles flotantes.",
530
530
  "Edit settings for the focused pane.": "Editar los ajustes del panel activo.",
@@ -823,7 +823,22 @@ export const es: Record<string, string> = {
823
823
  "Recent users": "Usuarios recientes",
824
824
  "No recent users": "Sin usuarios recientes",
825
825
  "Enter at least one @username.": "Ingresa al menos un @username.",
826
- "Could not start conversation.": "No se pudo iniciar la conversación.",
826
+ "@{username} only takes DMs from people they have written to first.": "@{username} solo acepta DM de personas a las que escribió primero.",
827
+ "@{username} does not take DMs.": "@{username} no acepta DM.",
828
+ "@{username} was not found.": "No se encontró a @{username}.",
829
+ "{usernames} were not found.": "No se encontró a {usernames}.",
830
+ "One of those users was not found.": "No se encontró a uno de esos usuarios.",
831
+ "Someone in that group only takes DMs from people they have written to first.": "Alguien de ese grupo solo acepta DM de personas a las que escribió primero.",
832
+ "Could not start the conversation (error {status}).": "No se pudo iniciar la conversación (error {status}).",
833
+ "Could not start the conversation. Check your connection and try again.": "No se pudo iniciar la conversación. Revisa tu conexión e inténtalo de nuevo.",
834
+ "no DMs": "sin DM",
835
+ "Only takes DMs from people they have written to first.": "Solo acepta DM de personas a las que escribió primero.",
836
+ "Does not take DMs.": "No acepta DM.",
837
+ "Message @{username}": "Enviar mensaje a @{username}",
838
+ "Open DM with @{username}": "Abrir DM con @{username}",
839
+ "Message": "Mensaje",
840
+ "Open DM": "Abrir DM",
841
+ "Show Profile": "Ver perfil",
827
842
  "Starting": "Iniciando",
828
843
  "Start": "Iniciar",
829
844
 
@@ -943,7 +958,9 @@ export const es: Record<string, string> = {
943
958
 
944
959
  // ── Main dashboard ──────────────────────────────────────────
945
960
  "Installing update...": "Instalando actualización...",
946
- "Update installed, restart to apply": "Actualización instalada; reinicia para aplicar",
961
+ "Update ready, restart to apply": "Actualización lista; reinicia para aplicar",
962
+ "Update ready": "Actualización lista",
963
+ "Restart": "Reiniciar",
947
964
  "Checking for updates...": "Buscando actualizaciones...",
948
965
  "Downloading v{version}: {percent}%": "Descargando v{version}: {percent}%",
949
966
  "Update failed: {error}": "Error al actualizar: {error}",
@@ -958,6 +975,9 @@ export const es: Record<string, string> = {
958
975
  "Minimize": "Minimizar",
959
976
  "Maximize": "Maximizar",
960
977
  "Pane unavailable.": "Panel no disponible.",
978
+ "{title} stopped working.": "{title} dejó de funcionar.",
979
+ "Reload pane": "Recargar panel",
980
+ "Close pane": "Cerrar panel",
961
981
  "Cash & Margin": "Efectivo y margen",
962
982
  "No non-zero cash balances.": "Sin saldos de efectivo distintos de cero.",
963
983
  "adding...": "agregando...",
package/src/i18n/ja.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * fixed-width terminal layouts stay readable.
6
6
  */
7
7
  export const ja: Record<string, string> = {
8
+ "NAV · as of {date}": "NAV · {date}時点",
8
9
  // ── Common UI ────────────────────────────────────────────────
9
10
  "Back": "戻る",
10
11
  "Done": "完了",
@@ -378,7 +379,6 @@ export const ja: Record<string, string> = {
378
379
  "Price trigger alerts with notifications": "通知付きの価格トリガーアラート",
379
380
  "Create a price alert from a symbol, condition, and target price": "銘柄コード、条件、目標価格から価格アラートを作成",
380
381
  "Public market heatmap for the largest US stocks and ETFs.": "米国大型株と ETF の市場ヒートマップ。",
381
- "Largest US stocks and ETFs, sized by market cap or assets and colored by daily move.": "米国大型株と ETF を時価総額・資産規模で表示し、日次騰落率で色分けします。",
382
382
  "Top gainers, losers, most active, and trending tickers": "値上がり、値下がり、出来高、注目銘柄",
383
383
  "Top gainers, losers, most active, and trending tickers.": "値上がり、値下がり、出来高、注目銘柄。",
384
384
  "S&P 500 sector and industry performance via ETF proxies": "ETF を使った S&P 500 のセクター・業種別騰落率",
@@ -525,7 +525,7 @@ export const ja: Record<string, string> = {
525
525
  "Quit the terminal app.": "ターミナル アプリを終了します。",
526
526
  "Copy the active terminal selection.": "アクティブな端末の選択をコピーします。",
527
527
  "Paste clipboard text into the active input.": "クリップボードのテキストをアクティブな入力に貼り付けます。",
528
- "Install an available app update when one is shown.": "利用可能なアプリのアップデートが表示されたら、それをインストールします。",
528
+ "Restart into a downloaded app update, or retry one that failed.": "ダウンロード済みのアップデートで再起動するか、失敗したアップデートを再試行します。",
529
529
  "Close the focused pane, docked or floating.": "フォーカスされたペインをドッキングまたはフローティング状態で閉じます。",
530
530
  "Close all floating panes.": "すべてのフローティング ペインを閉じます。",
531
531
  "Edit settings for the focused pane.": "フォーカスされたペインの設定を編集します。",
@@ -837,7 +837,22 @@ export const ja: Record<string, string> = {
837
837
  "Recent users": "最近のユーザー",
838
838
  "No recent users": "最近のユーザーはいません",
839
839
  "Enter at least one @username.": "@username を 1 件以上入力してください。",
840
- "Could not start conversation.": "会話を開始できませんでした。",
840
+ "@{username} only takes DMs from people they have written to first.": "@{username} は自分から先にメッセージを送った相手の DM だけを受け付けています。",
841
+ "@{username} does not take DMs.": "@{username} は DM を受け付けていません。",
842
+ "@{username} was not found.": "@{username} が見つかりません。",
843
+ "{usernames} were not found.": "{usernames} が見つかりません。",
844
+ "One of those users was not found.": "見つからないユーザーがいます。",
845
+ "Someone in that group only takes DMs from people they have written to first.": "このグループには、自分から先にメッセージを送った相手の DM だけを受け付けている人がいます。",
846
+ "Could not start the conversation (error {status}).": "会話を開始できませんでした (エラー {status})。",
847
+ "Could not start the conversation. Check your connection and try again.": "会話を開始できませんでした。接続を確認して、もう一度お試しください。",
848
+ "no DMs": "DM 不可",
849
+ "Only takes DMs from people they have written to first.": "自分から先にメッセージを送った相手の DM だけを受け付けています。",
850
+ "Does not take DMs.": "DM を受け付けていません。",
851
+ "Message @{username}": "@{username} にメッセージ",
852
+ "Open DM with @{username}": "@{username} との DM を開く",
853
+ "Message": "メッセージ",
854
+ "Open DM": "DM を開く",
855
+ "Show Profile": "プロフィールを表示",
841
856
  "Starting": "開始中",
842
857
  "Start": "開始",
843
858
 
@@ -957,7 +972,9 @@ export const ja: Record<string, string> = {
957
972
 
958
973
  // ── Main dashboard ──────────────────────────────────────────
959
974
  "Installing update...": "アップデートをインストール中...",
960
- "Update installed, restart to apply": "アップデートがインストールされました。適用するには再起動してください",
975
+ "Update ready, restart to apply": "アップデートの準備ができました。適用するには再起動してください",
976
+ "Update ready": "アップデートの準備完了",
977
+ "Restart": "再起動",
961
978
  "Checking for updates...": "アップデートを確認中...",
962
979
  "Downloading v{version}: {percent}%": "v{version} をダウンロード中: {percent}%",
963
980
  "Update failed: {error}": "更新に失敗しました: {error}",
@@ -972,6 +989,9 @@ export const ja: Record<string, string> = {
972
989
  "Minimize": "最小化",
973
990
  "Maximize": "最大化",
974
991
  "Pane unavailable.": "ペインが使用できません。",
992
+ "{title} stopped working.": "{title} が動作を停止しました。",
993
+ "Reload pane": "ペインを再読み込み",
994
+ "Close pane": "ペインを閉じる",
975
995
  "Cash & Margin": "現金・証拠金",
976
996
  "No non-zero cash balances.": "現金残高はありません。",
977
997
  "adding...": "追加中...",