gloomberb 0.18.3 → 0.18.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (886) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +11 -11
  3. package/bin/{gloomberb → gloom} +3 -1
  4. package/package.json +6 -2
  5. package/src/account/checkout-handoff.tsx +225 -0
  6. package/src/account/device-signin-dialog.tsx +2 -2
  7. package/src/account/device-signin.ts +2 -2
  8. package/src/account/upgrade-dialog.tsx +1 -1
  9. package/src/api-client/askg.ts +2 -2
  10. package/src/api-client/auth.ts +2 -2
  11. package/src/api-client/central-bank-rates.ts +6 -0
  12. package/src/api-client/collections.ts +5 -1
  13. package/src/api-client/cot.ts +2 -0
  14. package/src/api-client/crypto-etf-flows.ts +37 -0
  15. package/src/api-client/crypto-markets.ts +60 -0
  16. package/src/api-client/data.ts +84 -5
  17. package/src/api-client/doe.ts +15 -0
  18. package/src/api-client/equity-screener.ts +28 -0
  19. package/src/api-client/exchange-announcements.ts +38 -0
  20. package/src/api-client/fund-facts.ts +39 -0
  21. package/src/api-client/futures-curve.ts +9 -1
  22. package/src/api-client/hiring.ts +301 -0
  23. package/src/api-client/index.ts +22 -5
  24. package/src/api-client/market-discovery.ts +14 -0
  25. package/src/api-client/members.ts +6 -0
  26. package/src/api-client/mna.ts +6 -0
  27. package/src/api-client/paths.ts +18 -1
  28. package/src/api-client/request.ts +21 -4
  29. package/src/api-client/short-side-publications.ts +37 -0
  30. package/src/api-client/socket.ts +64 -4
  31. package/src/api-client/swap-curve.ts +35 -0
  32. package/src/api-client/themes.ts +7 -1
  33. package/src/api-client/types.ts +90 -2
  34. package/src/app/pane-runtime/plugin-bindings.ts +9 -2
  35. package/src/app/runtime/desktop-deeplink.ts +5 -5
  36. package/src/app/runtime/plugin-bindings.ts +2 -2
  37. package/src/app/runtime/startup.ts +13 -0
  38. package/src/app/star-prompt/status-line.tsx +2 -2
  39. package/src/architecture/core-builtin-allowlist.json +5 -2
  40. package/src/architecture/ui-literals-allowlist.json +3 -3
  41. package/src/architecture/ui-tokens-allowlist.json +1 -1
  42. package/src/brokers/broker-portfolio-sync.ts +37 -0
  43. package/src/brokers/directory.ts +11 -0
  44. package/src/brokers/logos.ts +3 -1
  45. package/src/brokers/signed-in/adapter.ts +304 -26
  46. package/src/brokers/signed-in/client.ts +14 -2
  47. package/src/brokers/signed-in/connect.ts +10 -2
  48. package/src/brokers/sync-broker-instance.ts +9 -1
  49. package/src/capabilities/chart-series.ts +22 -6
  50. package/src/cli/bank-section.ts +1 -1
  51. package/src/cli/base-converter.ts +23 -14
  52. package/src/cli/central-bank-events.ts +1 -1
  53. package/src/cli/command-options.ts +59 -4
  54. package/src/cli/commands/api.ts +9 -6
  55. package/src/cli/commands/broker.ts +2 -2
  56. package/src/cli/commands/command-utils.ts +2 -2
  57. package/src/cli/commands/crypto-hints.ts +7 -20
  58. package/src/cli/commands/fred-series.ts +4 -2
  59. package/src/cli/commands/keybindings.ts +2 -2
  60. package/src/cli/commands/market.ts +1117 -264
  61. package/src/cli/commands/news-hints.ts +2 -2
  62. package/src/cli/commands/news-search.ts +59 -6
  63. package/src/cli/commands/options-leaps.ts +41 -26
  64. package/src/cli/commands/overview.ts +121 -48
  65. package/src/cli/commands/plugins.ts +9 -9
  66. package/src/cli/commands/remote.ts +13 -10
  67. package/src/cli/commands/search.ts +64 -44
  68. package/src/cli/commands/system.ts +27 -19
  69. package/src/cli/commands/themes.ts +1 -1
  70. package/src/cli/commands/ticker.ts +192 -47
  71. package/src/cli/context.ts +3 -2
  72. package/src/cli/desktop-pane-shot-view.ts +2 -2
  73. package/src/cli/desktop-pane-shot.ts +1 -1
  74. package/src/cli/earnings-calendar.ts +4 -4
  75. package/src/cli/entry.ts +18 -1
  76. package/src/cli/errors.ts +20 -2
  77. package/src/cli/exit-codes.ts +1 -1
  78. package/src/cli/export-source.ts +10 -4
  79. package/src/cli/freshness.ts +2 -8
  80. package/src/cli/fx-forward.ts +130 -0
  81. package/src/cli/fx-pair.ts +10 -9
  82. package/src/cli/glossary.ts +64 -20
  83. package/src/cli/help.ts +19 -13
  84. package/src/cli/history-export.ts +126 -0
  85. package/src/cli/history-rows.ts +196 -43
  86. package/src/cli/index-roots.ts +5 -45
  87. package/src/cli/index.ts +24 -18
  88. package/src/cli/known-gaps.ts +118 -25
  89. package/src/cli/listing-arg.ts +300 -41
  90. package/src/cli/name-entries.ts +30 -18
  91. package/src/cli/native-smoke.ts +2 -0
  92. package/src/cli/not-a-ticker.ts +19 -9
  93. package/src/cli/opentui-libc.ts +5 -0
  94. package/src/cli/options.ts +12 -0
  95. package/src/cli/pane-functions/capabilities.ts +75 -20
  96. package/src/cli/pane-functions/catalog.ts +24 -23
  97. package/src/cli/pane-functions/discovery.ts +1 -1
  98. package/src/cli/pane-functions/dom.ts +10 -7
  99. package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
  100. package/src/cli/pane-functions/freshness.ts +174 -23
  101. package/src/cli/pane-functions/function-help.ts +66 -27
  102. package/src/cli/pane-functions/headless.ts +24 -11
  103. package/src/cli/pane-functions/index.ts +18 -16
  104. package/src/cli/pane-functions/options.ts +22 -2
  105. package/src/cli/pane-functions/report-notices.ts +12 -4
  106. package/src/cli/pane-functions/report.ts +5 -5
  107. package/src/cli/pane-functions/resolver.ts +47 -10
  108. package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
  109. package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
  110. package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
  111. package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
  112. package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
  113. package/src/cli/pane-functions/screenshot-payload.ts +453 -0
  114. package/src/cli/pane-functions/screenshot-render.ts +316 -0
  115. package/src/cli/pane-functions/screenshot-types.ts +162 -0
  116. package/src/cli/pane-functions/shot-options.ts +8 -3
  117. package/src/cli/peso-dollar-rates.ts +79 -0
  118. package/src/cli/quote-answer.ts +38 -3
  119. package/src/cli/report-tables.ts +61 -16
  120. package/src/cli/restore-plugins.ts +29 -14
  121. package/src/cli/result.ts +111 -22
  122. package/src/cli/series-search.ts +5 -5
  123. package/src/cli/statement-filings.ts +19 -0
  124. package/src/cli/suffixed-listing-rows.ts +49 -0
  125. package/src/cli/symbol-args.ts +50 -15
  126. package/src/cli/symbol-cells.ts +120 -0
  127. package/src/cli/symbol-list.ts +198 -68
  128. package/src/cli/symbol-rows.ts +131 -25
  129. package/src/cli/ticker-resolution.ts +108 -11
  130. package/src/cli/treasury-yields.ts +5 -5
  131. package/src/cli/types.ts +2 -0
  132. package/src/cli/uncovered-instrument.ts +3 -3
  133. package/src/cli/unknown-command.ts +6 -6
  134. package/src/components/chart/composite/chart-layout.ts +131 -0
  135. package/src/components/chart/composite/composite-chart.tsx +373 -16
  136. package/src/components/chart/composite/interactions.ts +7 -2
  137. package/src/components/chart/composite/legend.tsx +75 -3
  138. package/src/components/chart/composite/levels.ts +5 -0
  139. package/src/components/chart/composite/panel-gestures.ts +41 -0
  140. package/src/components/chart/composite/panel-labels.ts +2 -1
  141. package/src/components/chart/composite/panel-surface.tsx +305 -11
  142. package/src/components/chart/composite/price-axis-labels.tsx +27 -3
  143. package/src/components/chart/composite/rasterizer.ts +44 -19
  144. package/src/components/chart/composite/scene.ts +16 -4
  145. package/src/components/chart/composite/text-renderer.ts +48 -21
  146. package/src/components/chart/composite/toolbar.tsx +52 -5
  147. package/src/components/chart/composite/types.ts +13 -0
  148. package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
  149. package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
  150. package/src/components/chart/composite/use-composite-viewport.ts +12 -3
  151. package/src/components/chart/composite/value-scale.ts +149 -0
  152. package/src/components/chart/composite/volume-profile-paint.ts +6 -3
  153. package/src/components/chart/core/pointer.ts +2 -0
  154. package/src/components/chart-table/index.ts +2 -0
  155. package/src/components/chart-table/read.tsx +74 -0
  156. package/src/components/command-bar/commands/collection-list.ts +41 -19
  157. package/src/components/command-bar/commands/collection.ts +9 -3
  158. package/src/components/command-bar/commands/direct/index.ts +1 -1
  159. package/src/components/command-bar/commands/direct/runtime.ts +3 -2
  160. package/src/components/command-bar/pane-templates/items.ts +59 -6
  161. package/src/components/command-bar/pane-templates/workflow.ts +10 -1
  162. package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
  163. package/src/components/command-bar/routes/root/provider-search.ts +42 -11
  164. package/src/components/command-bar/routes/root/results.ts +18 -4
  165. package/src/components/command-bar/routes/root/runtime.ts +15 -3
  166. package/src/components/command-bar/routes/root/search-providers.ts +25 -2
  167. package/src/components/command-bar/routes/root/selection.ts +6 -1
  168. package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
  169. package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
  170. package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
  171. package/src/components/command-bar/selection-runtime.ts +50 -10
  172. package/src/components/command-bar/surface/index.tsx +24 -2
  173. package/src/components/command-bar/view-model.ts +7 -0
  174. package/src/components/command-bar/workflow/broker.ts +2 -2
  175. package/src/components/command-bar/workflow/collection-actions.ts +46 -7
  176. package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
  177. package/src/components/command-bar/workflow/fields.ts +8 -2
  178. package/src/components/command-bar/workflow/ops.ts +18 -4
  179. package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
  180. package/src/components/command-bar/workflow/submit.ts +3 -2
  181. package/src/components/command-bar/workflow/tickers.ts +5 -1
  182. package/src/components/company-logo.tsx +39 -0
  183. package/src/components/data-table/sections.ts +4 -2
  184. package/src/components/form-modal/confirm.tsx +2 -1
  185. package/src/components/form-modal/request.ts +5 -0
  186. package/src/components/form-modal/routes.ts +4 -1
  187. package/src/components/index.ts +12 -6
  188. package/src/components/layout/header.tsx +7 -6
  189. package/src/components/layout/market-summary.ts +9 -6
  190. package/src/components/layout/pane/capture-status.ts +1 -1
  191. package/src/components/layout/pane/footer/model.ts +11 -5
  192. package/src/components/layout/shell/chrome.ts +19 -6
  193. package/src/components/layout/shell/index.tsx +2 -1
  194. package/src/components/layout/shell/pane/layers.tsx +19 -1
  195. package/src/components/layout/status-bar.tsx +2 -2
  196. package/src/components/market-board/index.tsx +11 -3
  197. package/src/components/onboarding/onboarding-wizard.tsx +1 -0
  198. package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
  199. package/src/components/onboarding/wizard-broker-sync.ts +4 -1
  200. package/src/components/pane-settings-dialog/desktop.tsx +20 -7
  201. package/src/components/pane-settings-dialog/tui.tsx +17 -9
  202. package/src/components/pane-settings-dialog/value.ts +8 -1
  203. package/src/components/pane-settings-dialog.tsx +44 -13
  204. package/src/components/sign-in-code-panel.tsx +27 -19
  205. package/src/components/ui/column-grid.tsx +48 -4
  206. package/src/components/ui/country-flag-art.tsx +180 -0
  207. package/src/components/ui/country-flag.tsx +118 -12
  208. package/src/components/ui/data-table/opentui/index.tsx +61 -2
  209. package/src/components/ui/data-table/opentui/model.ts +109 -2
  210. package/src/components/ui/data-table/types.ts +1 -1
  211. package/src/components/ui/display.tsx +5 -1
  212. package/src/components/ui/index.ts +3 -1
  213. package/src/components/ui/logo-mark.tsx +11 -2
  214. package/src/components/ui/query-bar.tsx +1 -1
  215. package/src/components/ui/row-notes.ts +79 -0
  216. package/src/core/state/app/layout.ts +4 -4
  217. package/src/data/cached-query.ts +8 -1
  218. package/src/data/config/chart-settings.ts +3 -3
  219. package/src/data/config/home.ts +10 -2
  220. package/src/data/config/layout.ts +4 -1
  221. package/src/data/config/store/node.ts +4 -0
  222. package/src/data/config/store/normalize.ts +13 -3
  223. package/src/data/config/store/portfolio-as-of-column.ts +2 -2
  224. package/src/data/json-storage.ts +2 -0
  225. package/src/data/saved-copies.ts +84 -0
  226. package/src/docs/snapshot.json +65 -32
  227. package/src/i18n/es.ts +29 -12
  228. package/src/i18n/ja.ts +29 -12
  229. package/src/i18n/ko.ts +29 -12
  230. package/src/i18n/zh-cn.ts +29 -12
  231. package/src/i18n/zh-tw.ts +29 -12
  232. package/src/layout/desks.ts +1 -1
  233. package/src/layout/launch-layout.ts +1 -1
  234. package/src/layout/pane-manager/floating-actions.ts +5 -3
  235. package/src/layout/pane-manager/floating.ts +43 -1
  236. package/src/layout/pane-manager/index.ts +2 -0
  237. package/src/layout/selected-ticker.ts +74 -0
  238. package/src/market-data/depositary-pair.ts +251 -0
  239. package/src/market-data/futures-board.ts +1 -1
  240. package/src/market-data/futures-contract.ts +124 -40
  241. package/src/market-data/fx-closes.ts +17 -2
  242. package/src/market-data/hooks.tsx +19 -11
  243. package/src/market-data/market/change-basis.ts +49 -7
  244. package/src/market-data/market/freshness.ts +34 -5
  245. package/src/market-data/market/period-return.ts +163 -0
  246. package/src/market-data/market/trading-sessions.ts +13 -0
  247. package/src/market-data/market/year-to-date.ts +8 -13
  248. package/src/market-data/performance.ts +20 -14
  249. package/src/market-data/perpetual-premium.ts +32 -0
  250. package/src/market-data/published-apac-sessions.ts +2 -1
  251. package/src/market-data/published-futures-sessions.ts +69 -0
  252. package/src/market-data/quotes/contributions.ts +5 -1
  253. package/src/market-data/quotes/freshness.ts +42 -0
  254. package/src/market-data/quotes/intraday-bar.ts +37 -0
  255. package/src/market-data/quotes/regular-session-valuation.ts +13 -8
  256. package/src/market-data/quotes/resolution.ts +4 -2
  257. package/src/market-data/tax-equivalent.ts +1 -1
  258. package/src/market-data/ticker-price-returns.ts +3 -1
  259. package/src/news/aggregator.ts +5 -1
  260. package/src/news/news-model.ts +4 -0
  261. package/src/news/types.ts +11 -0
  262. package/src/notifications/app-notifier.ts +1 -1
  263. package/src/plugins/auto-update.ts +2 -2
  264. package/src/plugins/builtin/account-management/index.tsx +1 -0
  265. package/src/plugins/builtin/account-management/pane.tsx +9 -8
  266. package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
  267. package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
  268. package/src/plugins/builtin/alerts/cli.ts +485 -76
  269. package/src/plugins/builtin/alerts/command.ts +5 -10
  270. package/src/plugins/builtin/alerts/event-rows.ts +9 -5
  271. package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
  272. package/src/plugins/builtin/alerts/events.ts +107 -5
  273. package/src/plugins/builtin/alerts/fired-log.ts +78 -0
  274. package/src/plugins/builtin/alerts/format.ts +2 -1
  275. package/src/plugins/builtin/alerts/headless.ts +100 -39
  276. package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
  277. package/src/plugins/builtin/alerts/history-rows.ts +89 -0
  278. package/src/plugins/builtin/alerts/index.tsx +45 -18
  279. package/src/plugins/builtin/alerts/iv-level.ts +365 -0
  280. package/src/plugins/builtin/alerts/levels.ts +3 -3
  281. package/src/plugins/builtin/alerts/pane.tsx +97 -29
  282. package/src/plugins/builtin/alerts/price.ts +35 -0
  283. package/src/plugins/builtin/alerts/quotes.ts +24 -0
  284. package/src/plugins/builtin/alerts/research-builder.ts +84 -11
  285. package/src/plugins/builtin/alerts/research-rules.ts +76 -3
  286. package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
  287. package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
  288. package/src/plugins/builtin/alerts/scheduled.ts +188 -29
  289. package/src/plugins/builtin/alerts/storage.ts +13 -10
  290. package/src/plugins/builtin/alerts/targets.ts +12 -3
  291. package/src/plugins/builtin/analytics/index.tsx +8 -2
  292. package/src/plugins/builtin/analytics/metrics.ts +1 -1
  293. package/src/plugins/builtin/analytics/risk-book.ts +215 -0
  294. package/src/plugins/builtin/analytics/risk-client.ts +13 -6
  295. package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
  296. package/src/plugins/builtin/analytics/risk-math.ts +6 -3
  297. package/src/plugins/builtin/analytics/risk-model.ts +297 -104
  298. package/src/plugins/builtin/analytics/risk-options.ts +17 -2
  299. package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
  300. package/src/plugins/builtin/attention/pane.tsx +6 -2
  301. package/src/plugins/builtin/awards/headless.ts +7 -3
  302. package/src/plugins/builtin/awards/model.ts +18 -0
  303. package/src/plugins/builtin/awards/pane.tsx +6 -3
  304. package/src/plugins/builtin/backtest/headless.ts +3 -3
  305. package/src/plugins/builtin/backtest/rules.ts +41 -5
  306. package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
  307. package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
  308. package/src/plugins/builtin/broker-manager/footer.ts +27 -11
  309. package/src/plugins/builtin/broker-manager/index.tsx +21 -12
  310. package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
  311. package/src/plugins/builtin/broker-manager/model.ts +12 -2
  312. package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
  313. package/src/plugins/builtin/broker-manager/table.ts +28 -12
  314. package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
  315. package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
  316. package/src/plugins/builtin/broker-trading/controller.ts +45 -13
  317. package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
  318. package/src/plugins/builtin/broker-trading/headless.ts +2 -1
  319. package/src/plugins/builtin/broker-trading/index.tsx +7 -1
  320. package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
  321. package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
  322. package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
  323. package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
  324. package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
  325. package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
  326. package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
  327. package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
  328. package/src/plugins/builtin/buildout/cells.tsx +4 -0
  329. package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
  330. package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
  331. package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
  332. package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
  333. package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
  334. package/src/plugins/builtin/catalysts/detail.tsx +3 -2
  335. package/src/plugins/builtin/catalysts/index.tsx +1 -1
  336. package/src/plugins/builtin/catalysts/model.ts +49 -4
  337. package/src/plugins/builtin/catalysts/pane.tsx +6 -8
  338. package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
  339. package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
  340. package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
  341. package/src/plugins/builtin/changelog/index.tsx +1 -0
  342. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
  343. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
  344. package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
  345. package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
  346. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
  347. package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
  348. package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
  349. package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
  350. package/src/plugins/builtin/chart-composer/headless.ts +253 -35
  351. package/src/plugins/builtin/chart-composer/index.tsx +12 -2
  352. package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
  353. package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
  354. package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
  355. package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
  356. package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
  357. package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
  358. package/src/plugins/builtin/chart-composer/settings.ts +31 -19
  359. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
  360. package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
  361. package/src/plugins/builtin/chat/attachments/model.ts +3 -1
  362. package/src/plugins/builtin/chat/content/index.tsx +1 -1
  363. package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
  364. package/src/plugins/builtin/chat/people.ts +1 -1
  365. package/src/plugins/builtin/clinical-trials/client.ts +5 -2
  366. package/src/plugins/builtin/clinical-trials/model.ts +13 -4
  367. package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
  368. package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
  369. package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
  370. package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
  371. package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
  372. package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
  373. package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
  374. package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
  375. package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
  376. package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
  377. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  378. package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
  379. package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
  380. package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
  381. package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
  382. package/src/plugins/builtin/company-attention/building-model.ts +222 -0
  383. package/src/plugins/builtin/company-attention/building.tsx +172 -0
  384. package/src/plugins/builtin/company-attention/client.ts +117 -1
  385. package/src/plugins/builtin/company-attention/evidence.ts +16 -3
  386. package/src/plugins/builtin/company-attention/headless.ts +101 -5
  387. package/src/plugins/builtin/company-attention/index.tsx +6 -3
  388. package/src/plugins/builtin/company-attention/model.ts +33 -7
  389. package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
  390. package/src/plugins/builtin/company-attention/moves.tsx +159 -0
  391. package/src/plugins/builtin/company-attention/pane.tsx +79 -23
  392. package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
  393. package/src/plugins/builtin/company-attention/signals.tsx +160 -0
  394. package/src/plugins/builtin/company-kpis/headless.ts +3 -2
  395. package/src/plugins/builtin/company-kpis/model.ts +2 -2
  396. package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
  397. package/src/plugins/builtin/composite-plugins.ts +2 -1
  398. package/src/plugins/builtin/congress-trades/headless.ts +1 -1
  399. package/src/plugins/builtin/connections/index.ts +1 -0
  400. package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
  401. package/src/plugins/builtin/correlation/headless.ts +5 -3
  402. package/src/plugins/builtin/cot/headless.ts +28 -6
  403. package/src/plugins/builtin/cot/model.ts +12 -0
  404. package/src/plugins/builtin/cot/pane.tsx +3 -2
  405. package/src/plugins/builtin/cpi/headless.ts +5 -1
  406. package/src/plugins/builtin/cpi/pane.tsx +11 -9
  407. package/src/plugins/builtin/credit-boards/model.ts +2 -0
  408. package/src/plugins/builtin/credit-documents/headless.ts +1 -1
  409. package/src/plugins/builtin/crypto-board/client.ts +86 -0
  410. package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
  411. package/src/plugins/builtin/crypto-board/defi.ts +239 -0
  412. package/src/plugins/builtin/crypto-board/headless.ts +117 -6
  413. package/src/plugins/builtin/crypto-board/index.tsx +8 -3
  414. package/src/plugins/builtin/crypto-board/model.ts +40 -8
  415. package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
  416. package/src/plugins/builtin/crypto-board/series.ts +19 -1
  417. package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
  418. package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
  419. package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
  420. package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
  421. package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
  422. package/src/plugins/builtin/debug/index.tsx +1 -0
  423. package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
  424. package/src/plugins/builtin/docs/index.tsx +1 -1
  425. package/src/plugins/builtin/docs/pane.tsx +2 -2
  426. package/src/plugins/builtin/docs/targets.ts +1 -1
  427. package/src/plugins/builtin/doe/client.ts +5 -1
  428. package/src/plugins/builtin/doe/headless.ts +12 -6
  429. package/src/plugins/builtin/doe/model.ts +43 -6
  430. package/src/plugins/builtin/doe/pane.tsx +18 -11
  431. package/src/plugins/builtin/earnings/board-model.ts +13 -6
  432. package/src/plugins/builtin/earnings/board-table.ts +4 -1
  433. package/src/plugins/builtin/earnings/board.tsx +253 -50
  434. package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
  435. package/src/plugins/builtin/earnings/calendar.tsx +338 -0
  436. package/src/plugins/builtin/earnings/client.ts +4 -3
  437. package/src/plugins/builtin/earnings/headless.ts +53 -15
  438. package/src/plugins/builtin/earnings/history-model.ts +53 -36
  439. package/src/plugins/builtin/earnings/index.tsx +15 -22
  440. package/src/plugins/builtin/earnings/model.ts +17 -12
  441. package/src/plugins/builtin/earnings/scope.ts +89 -0
  442. package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
  443. package/src/plugins/builtin/earnings-calls/data.ts +146 -2
  444. package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
  445. package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
  446. package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
  447. package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
  448. package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
  449. package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
  450. package/src/plugins/builtin/econ/calendar-model.ts +132 -20
  451. package/src/plugins/builtin/econ/detail-view.tsx +48 -10
  452. package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
  453. package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
  454. package/src/plugins/builtin/econ/index.tsx +112 -25
  455. package/src/plugins/builtin/econ/print-watch.ts +2 -1
  456. package/src/plugins/builtin/econ/types.ts +32 -1
  457. package/src/plugins/builtin/econ-statistics/client.ts +16 -3
  458. package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
  459. package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
  460. package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
  461. package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
  462. package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
  463. package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
  464. package/src/plugins/builtin/econ-statistics/view.ts +16 -1
  465. package/src/plugins/builtin/equity-screener/client.ts +21 -3
  466. package/src/plugins/builtin/equity-screener/headless.ts +68 -6
  467. package/src/plugins/builtin/equity-screener/live.ts +1 -1
  468. package/src/plugins/builtin/equity-screener/model.ts +6 -0
  469. package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
  470. package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
  471. package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
  472. package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
  473. package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
  474. package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
  475. package/src/plugins/builtin/exposure/headless.ts +51 -6
  476. package/src/plugins/builtin/exposure/index.tsx +28 -2
  477. package/src/plugins/builtin/exposure/model.ts +7 -0
  478. package/src/plugins/builtin/exposure/pane.tsx +6 -1
  479. package/src/plugins/builtin/fear-greed/index.tsx +1 -1
  480. package/src/plugins/builtin/filing-events/index.tsx +1 -1
  481. package/src/plugins/builtin/futures/model.ts +10 -9
  482. package/src/plugins/builtin/futures/returns.ts +8 -36
  483. package/src/plugins/builtin/futures/table.tsx +1 -1
  484. package/src/plugins/builtin/futures-curve/client.ts +40 -9
  485. package/src/plugins/builtin/futures-curve/headless.ts +39 -17
  486. package/src/plugins/builtin/futures-curve/model.ts +258 -69
  487. package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
  488. package/src/plugins/builtin/fx-matrix/client.ts +15 -8
  489. package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
  490. package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
  491. package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
  492. package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
  493. package/src/plugins/builtin/gpu/headless.ts +9 -4
  494. package/src/plugins/builtin/help/index.tsx +13 -3
  495. package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
  496. package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
  497. package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
  498. package/src/plugins/builtin/holders/client.ts +13 -1
  499. package/src/plugins/builtin/holders/format.ts +28 -17
  500. package/src/plugins/builtin/holders/headless.ts +46 -7
  501. package/src/plugins/builtin/holders/index-holders.ts +264 -0
  502. package/src/plugins/builtin/holders/pane.tsx +79 -15
  503. package/src/plugins/builtin/holders/report-rows.ts +35 -7
  504. package/src/plugins/builtin/holders/table-model.ts +2 -1
  505. package/src/plugins/builtin/holders/treemap.tsx +2 -2
  506. package/src/plugins/builtin/insider/headless.ts +1 -1
  507. package/src/plugins/builtin/insider/signals-client.ts +1 -1
  508. package/src/plugins/builtin/insider/signals.tsx +1 -1
  509. package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
  510. package/src/plugins/builtin/iv-history/client.ts +20 -0
  511. package/src/plugins/builtin/iv-history/headless.ts +4 -4
  512. package/src/plugins/builtin/iv-history/index.tsx +1 -1
  513. package/src/plugins/builtin/iv-history/model.ts +13 -4
  514. package/src/plugins/builtin/iv-history/series.ts +3 -1
  515. package/src/plugins/builtin/jobs/lock-note.ts +1 -1
  516. package/src/plugins/builtin/jobs/model.ts +4 -15
  517. package/src/plugins/builtin/jobs/pane.tsx +7 -5
  518. package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
  519. package/src/plugins/builtin/jodi/pane.tsx +10 -4
  520. package/src/plugins/builtin/layout-manager/index.tsx +1 -0
  521. package/src/plugins/builtin/macro-day/headless.ts +20 -7
  522. package/src/plugins/builtin/macro-day/index.tsx +3 -2
  523. package/src/plugins/builtin/macro-day/model.ts +29 -8
  524. package/src/plugins/builtin/macro-day/pane.tsx +46 -10
  525. package/src/plugins/builtin/macro-day/releases.ts +55 -13
  526. package/src/plugins/builtin/market-heatmap/data.ts +9 -2
  527. package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
  528. package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
  529. package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
  530. package/src/plugins/builtin/market-heatmap/model.ts +10 -7
  531. package/src/plugins/builtin/market-movers/client.ts +33 -19
  532. package/src/plugins/builtin/market-movers/headless.ts +8 -2
  533. package/src/plugins/builtin/market-movers/index.tsx +16 -10
  534. package/src/plugins/builtin/market-movers/screener.ts +29 -8
  535. package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
  536. package/src/plugins/builtin/market-movers/session-table.ts +4 -2
  537. package/src/plugins/builtin/market-movers/table.ts +4 -1
  538. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  539. package/src/plugins/builtin/market-valuation/view.ts +5 -0
  540. package/src/plugins/builtin/members/headless.ts +6 -5
  541. package/src/plugins/builtin/members/pane.tsx +11 -4
  542. package/src/plugins/builtin/mna/client.ts +1 -0
  543. package/src/plugins/builtin/mna/detail.tsx +20 -32
  544. package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
  545. package/src/plugins/builtin/mna/distress/model.ts +3 -2
  546. package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
  547. package/src/plugins/builtin/mna/headless.ts +6 -13
  548. package/src/plugins/builtin/mna/model.ts +93 -15
  549. package/src/plugins/builtin/mna/pane.tsx +5 -4
  550. package/src/plugins/builtin/news/headless.ts +12 -6
  551. package/src/plugins/builtin/news/index.tsx +10 -1
  552. package/src/plugins/builtin/news/wire/index.tsx +3 -2
  553. package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
  554. package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
  555. package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
  556. package/src/plugins/builtin/notes/cli.ts +49 -14
  557. package/src/plugins/builtin/openfda/pane.tsx +1 -1
  558. package/src/plugins/builtin/options/carry.ts +2 -2
  559. package/src/plugins/builtin/options/index.tsx +1 -1
  560. package/src/plugins/builtin/options/view.tsx +10 -10
  561. package/src/plugins/builtin/options-calculator/headless.ts +46 -7
  562. package/src/plugins/builtin/options-scenario/client.ts +123 -28
  563. package/src/plugins/builtin/options-scenario/collar.ts +8 -6
  564. package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
  565. package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
  566. package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
  567. package/src/plugins/builtin/options-scenario/csp.ts +101 -21
  568. package/src/plugins/builtin/options-scenario/headless.ts +36 -15
  569. package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
  570. package/src/plugins/builtin/options-scenario/index.tsx +28 -3
  571. package/src/plugins/builtin/options-scenario/model.ts +13 -0
  572. package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
  573. package/src/plugins/builtin/perps/equity-row.tsx +11 -3
  574. package/src/plugins/builtin/perps/freshness.ts +8 -5
  575. package/src/plugins/builtin/perps/headless.ts +3 -1
  576. package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
  577. package/src/plugins/builtin/perps/live-rows.ts +161 -0
  578. package/src/plugins/builtin/perps/markets-section.tsx +154 -0
  579. package/src/plugins/builtin/perps/pane.tsx +36 -17
  580. package/src/plugins/builtin/perps/venue-markets.ts +96 -0
  581. package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
  582. package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
  583. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
  584. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
  585. package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
  586. package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
  587. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
  588. package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
  589. package/src/plugins/builtin/portfolio-list/income.ts +13 -2
  590. package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
  591. package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
  592. package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
  593. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
  594. package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
  595. package/src/plugins/builtin/power/client.ts +4 -1
  596. package/src/plugins/builtin/power/evidence.ts +22 -7
  597. package/src/plugins/builtin/power/gas.tsx +5 -1
  598. package/src/plugins/builtin/power/pane.tsx +8 -1
  599. package/src/plugins/builtin/power/prices.tsx +10 -3
  600. package/src/plugins/builtin/research/analyst-headless.ts +25 -8
  601. package/src/plugins/builtin/research/analyst-model.ts +68 -3
  602. package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
  603. package/src/plugins/builtin/research/event-model.ts +3 -1
  604. package/src/plugins/builtin/research/event-sources.ts +12 -4
  605. package/src/plugins/builtin/research/index.tsx +2 -1
  606. package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
  607. package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
  608. package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
  609. package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
  610. package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
  611. package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
  612. package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
  613. package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
  614. package/src/plugins/builtin/risk-factors/index.tsx +2 -2
  615. package/src/plugins/builtin/scanner/lock-note.ts +1 -1
  616. package/src/plugins/builtin/sec/forms.ts +13 -0
  617. package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
  618. package/src/plugins/builtin/sec/fund-facts.ts +68 -8
  619. package/src/plugins/builtin/sec/headless.ts +85 -8
  620. package/src/plugins/builtin/sec/index.tsx +58 -12
  621. package/src/plugins/builtin/sectors/client.ts +2 -1
  622. package/src/plugins/builtin/sectors/sector-model.ts +11 -15
  623. package/src/plugins/builtin/series-inventory.ts +2 -0
  624. package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
  625. package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
  626. package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
  627. package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
  628. package/src/plugins/builtin/shared/earnings-report.ts +3 -3
  629. package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
  630. package/src/plugins/builtin/shared/job-posting.ts +129 -0
  631. package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
  632. package/src/plugins/builtin/shared/report-freshness.ts +3 -0
  633. package/src/plugins/builtin/shared/research-trading.tsx +21 -0
  634. package/src/plugins/builtin/shared/series-cache.ts +2 -0
  635. package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
  636. package/src/plugins/builtin/short-interest/client.ts +2 -0
  637. package/src/plugins/builtin/short-interest/headless.ts +41 -12
  638. package/src/plugins/builtin/short-interest/index.tsx +23 -1
  639. package/src/plugins/builtin/short-interest/model.ts +70 -19
  640. package/src/plugins/builtin/short-interest/pane.tsx +19 -2
  641. package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
  642. package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
  643. package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
  644. package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
  645. package/src/plugins/builtin/short-interest/schedule.ts +35 -2
  646. package/src/plugins/builtin/short-interest/surface.tsx +11 -4
  647. package/src/plugins/builtin/short-interest/types.ts +9 -0
  648. package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
  649. package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
  650. package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
  651. package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
  652. package/src/plugins/builtin/supply-chain/model.ts +51 -3
  653. package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
  654. package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
  655. package/src/plugins/builtin/themes/headless.ts +8 -5
  656. package/src/plugins/builtin/themes/model.ts +14 -4
  657. package/src/plugins/builtin/themes/pane.tsx +24 -5
  658. package/src/plugins/builtin/thirteenf/headless.ts +5 -5
  659. package/src/plugins/builtin/thirteenf/signals.ts +3 -1
  660. package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
  661. package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
  662. package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
  663. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
  664. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
  665. package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
  666. package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
  667. package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
  668. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
  669. package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
  670. package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
  671. package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
  672. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
  673. package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
  674. package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
  675. package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
  676. package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
  677. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
  678. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
  679. package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
  680. package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
  681. package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
  682. package/src/plugins/builtin/vol-surface/client.ts +5 -4
  683. package/src/plugins/builtin/vol-surface/headless.ts +12 -3
  684. package/src/plugins/builtin/vol-surface/model.ts +4 -2
  685. package/src/plugins/builtin/volatility/model.ts +5 -10
  686. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
  687. package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
  688. package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
  689. package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
  690. package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
  691. package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
  692. package/src/plugins/builtin/world-venue-map/index.ts +3 -26
  693. package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
  694. package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
  695. package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
  696. package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
  697. package/src/plugins/builtin/yield-curve/client.ts +25 -0
  698. package/src/plugins/builtin/yield-curve/curves.ts +7 -4
  699. package/src/plugins/builtin/yield-curve/headless.ts +38 -4
  700. package/src/plugins/builtin/yield-curve/history.ts +4 -3
  701. package/src/plugins/builtin/yield-curve/index.tsx +12 -6
  702. package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
  703. package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
  704. package/src/plugins/bundle.ts +1 -1
  705. package/src/plugins/catalog-browser.ts +2 -1
  706. package/src/plugins/compat.ts +3 -3
  707. package/src/plugins/dependencies.ts +75 -14
  708. package/src/plugins/extracted-plugins.ts +132 -34
  709. package/src/plugins/host-link.ts +149 -34
  710. package/src/plugins/installer.ts +35 -10
  711. package/src/plugins/loader.ts +206 -38
  712. package/src/plugins/manager-node.ts +2 -2
  713. package/src/plugins/marketplace/deactivation.ts +22 -0
  714. package/src/plugins/marketplace/model.ts +2 -2
  715. package/src/plugins/marketplace/packs.ts +1 -1
  716. package/src/plugins/ownership.ts +1 -1
  717. package/src/plugins/peer-retry.ts +155 -0
  718. package/src/plugins/registry/contributions.ts +3 -1
  719. package/src/plugins/registry/index.ts +4 -3
  720. package/src/plugins/registry/plugin-state.ts +3 -0
  721. package/src/plugins/seed-notice.ts +20 -0
  722. package/src/plugins/shortcut-argument.ts +39 -0
  723. package/src/portfolio/allocation.ts +1 -1
  724. package/src/portfolio/collection-name.ts +31 -0
  725. package/src/portfolio/column-values.ts +10 -8
  726. package/src/portfolio/cost-fx.ts +296 -19
  727. package/src/portfolio/manual-lots.ts +75 -0
  728. package/src/portfolio/mutations.ts +60 -22
  729. package/src/portfolio/suffixed-listings.ts +209 -0
  730. package/src/portfolio/totals-currency.ts +24 -0
  731. package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
  732. package/src/public/time-series.ts +11 -8
  733. package/src/remote/schema.ts +1 -1
  734. package/src/renderers/browser/config-host.ts +3 -0
  735. package/src/renderers/browser/main.tsx +23 -3
  736. package/src/renderers/dom/boot-frame-page.ts +187 -0
  737. package/src/renderers/dom/boot-frame.ts +237 -0
  738. package/src/renderers/dom/build-assets.ts +46 -8
  739. package/src/renderers/dom/dom-ui-host.tsx +4 -29
  740. package/src/renderers/dom/host/ascii-text.ts +16 -2
  741. package/src/renderers/dom/host/box.tsx +43 -2
  742. package/src/renderers/dom/host/chart-surface.tsx +2 -0
  743. package/src/renderers/dom/host/hls.chunk.ts +3 -0
  744. package/src/renderers/dom/host/image-surface.tsx +49 -0
  745. package/src/renderers/dom/host/media-surface.tsx +24 -18
  746. package/src/renderers/dom/host/mouse.ts +30 -0
  747. package/src/renderers/dom/host/size-observer.ts +1 -1
  748. package/src/renderers/dom/host/style.ts +1 -1
  749. package/src/renderers/dom/styles.css +76 -0
  750. package/src/renderers/dom/test-utils.tsx +2 -1
  751. package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
  752. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
  753. package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
  754. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
  755. package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
  756. package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
  757. package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
  758. package/src/renderers/electrobun/bun/index.ts +11 -1
  759. package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
  760. package/src/renderers/electrobun/bun/window/create.ts +4 -1
  761. package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
  762. package/src/renderers/electrobun/shared/protocol.ts +6 -1
  763. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
  764. package/src/renderers/electrobun/view/config-host.ts +3 -0
  765. package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
  766. package/src/renderers/electrobun/view/main.tsx +30 -4
  767. package/src/renderers/electrobun/view/news-source.ts +5 -5
  768. package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
  769. package/src/renderers/electrobun/view/ui-host.tsx +1 -1
  770. package/src/renderers/opentui/browser-open.ts +88 -0
  771. package/src/renderers/opentui/host.tsx +5 -14
  772. package/src/renderers/opentui/image/loader.ts +3 -2
  773. package/src/renderers/opentui/native-smoke.ts +10 -1
  774. package/src/renderers/opentui/pane-image/index.ts +2 -1
  775. package/src/renderers/opentui/render-lib.ts +253 -0
  776. package/src/renderers/opentui/render-timing-smoke.ts +1 -1
  777. package/src/renderers/opentui/start.tsx +1 -1
  778. package/src/renderers/share/layout-view.tsx +2 -2
  779. package/src/renderers/share/main.tsx +4 -4
  780. package/src/renderers/share/view.tsx +1 -1
  781. package/src/series/resolve.ts +22 -6
  782. package/src/series/standalone.ts +30 -2
  783. package/src/series/types.ts +8 -1
  784. package/src/shares/api.ts +4 -1
  785. package/src/shares/pane.ts +1 -1
  786. package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
  787. package/src/sources/gloomberb-cloud/index.ts +32 -16
  788. package/src/sources/gloomberb-cloud/news.ts +39 -0
  789. package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
  790. package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
  791. package/src/sources/listing-symbols.ts +37 -0
  792. package/src/sources/provider-errors.ts +16 -2
  793. package/src/sources/provider-router/financial-routes.ts +21 -3
  794. package/src/sources/provider-router/financials.ts +15 -2
  795. package/src/sources/provider-router/history.ts +30 -8
  796. package/src/sources/provider-router/primary.ts +1 -1
  797. package/src/state/app/bootstrap.ts +23 -0
  798. package/src/state/hooks/inline-tickers.ts +30 -5
  799. package/src/sync/controller.ts +1 -1
  800. package/src/sync/core-contributors.ts +46 -14
  801. package/src/team/collections-sync.ts +2 -1
  802. package/src/team/collections.ts +178 -17
  803. package/src/telemetry/crash-reports.ts +17 -4
  804. package/src/test-support/builtin-panes.ts +1 -1
  805. package/src/theme/colors.ts +3 -30
  806. package/src/theme/ui-tokens.ts +37 -1
  807. package/src/tickers/company-name-listing.ts +210 -33
  808. package/src/tickers/index-roots.ts +47 -0
  809. package/src/tickers/instrument-label.ts +5 -1
  810. package/src/tickers/metadata.ts +10 -0
  811. package/src/tickers/perpetual-listing.ts +5 -2
  812. package/src/tickers/search/home-listing.ts +75 -0
  813. package/src/tickers/search/index.ts +76 -27
  814. package/src/tickers/search/ranking.ts +54 -4
  815. package/src/tickers/search/upsert.ts +29 -0
  816. package/src/tickers/terminal-codes.ts +416 -40
  817. package/src/time-series/bar-aggregation.ts +243 -0
  818. package/src/time-series/base-series.ts +307 -0
  819. package/src/time-series/chart-bounds.ts +349 -0
  820. package/src/time-series/chart-seed.ts +142 -0
  821. package/src/time-series/economic.ts +5 -0
  822. package/src/time-series/fundamentals.ts +18 -3
  823. package/src/time-series/history-acquisition.ts +499 -0
  824. package/src/time-series/leverage.ts +100 -0
  825. package/src/time-series/market-resolution.ts +4 -2
  826. package/src/time-series/market.ts +2 -1
  827. package/src/time-series/price-comparison.ts +175 -30
  828. package/src/time-series/range.ts +9 -1
  829. package/src/time-series/resolution.ts +174 -16
  830. package/src/time-series/resolve-context.ts +157 -0
  831. package/src/time-series/resolve.ts +126 -1577
  832. package/src/time-series/series-name.ts +38 -0
  833. package/src/time-series/series-presentation.ts +208 -0
  834. package/src/time-series/spec.ts +11 -6
  835. package/src/time-series/studies.ts +109 -12
  836. package/src/time-series/tail-reconcile.ts +121 -0
  837. package/src/time-series/types.ts +29 -2
  838. package/src/time-series/use-chart-resolution.ts +4 -5
  839. package/src/types/broker.ts +10 -0
  840. package/src/types/config.ts +14 -0
  841. package/src/types/data-provider.ts +14 -0
  842. package/src/types/exchange-rate.ts +6 -0
  843. package/src/types/financials.ts +104 -7
  844. package/src/types/headless.ts +76 -6
  845. package/src/types/instrument.ts +3 -0
  846. package/src/types/plugin.ts +65 -8
  847. package/src/types/price-history.ts +2 -0
  848. package/src/types/ticker.ts +13 -0
  849. package/src/types/trading.ts +59 -1
  850. package/src/ui/ascii-font.ts +13 -1
  851. package/src/ui/host.tsx +6 -1
  852. package/src/updater/command-names.ts +175 -0
  853. package/src/updater/index.ts +10 -5
  854. package/src/utils/calendar-date.ts +32 -15
  855. package/src/utils/cash-runway.ts +241 -0
  856. package/src/utils/central-banks.ts +42 -0
  857. package/src/utils/cli-output.ts +259 -80
  858. package/src/utils/contract-month.ts +16 -0
  859. package/src/utils/crypto-pair.ts +61 -3
  860. package/src/utils/currency-units.ts +29 -0
  861. package/src/utils/datetime-format.ts +10 -0
  862. package/src/utils/debug-log.ts +1 -1
  863. package/src/utils/decimal-comma.ts +39 -6
  864. package/src/utils/exchange-announcements.ts +71 -0
  865. package/src/utils/exchange-rate-snapshot.ts +10 -0
  866. package/src/utils/financial-statements.ts +83 -4
  867. package/src/utils/format.ts +34 -16
  868. package/src/utils/fundamentals.ts +150 -34
  869. package/src/utils/fx-market-hours.ts +10 -1
  870. package/src/utils/latest-financial-period.ts +8 -0
  871. package/src/utils/linux-libc.ts +54 -0
  872. package/src/utils/market-capitalization.ts +111 -15
  873. package/src/utils/max-drawdown.ts +64 -0
  874. package/src/utils/network-failure.ts +83 -0
  875. package/src/utils/option-expiry.ts +139 -7
  876. package/src/utils/price-earnings.ts +11 -5
  877. package/src/utils/price-history.ts +18 -8
  878. package/src/utils/price-window.ts +131 -0
  879. package/src/utils/release-date.ts +47 -0
  880. package/src/utils/sec.ts +3 -0
  881. package/src/utils/throttled-fetch.ts +11 -4
  882. package/src/utils/trailing-eps.ts +67 -0
  883. package/src/utils/typed-text.ts +21 -0
  884. package/src/utils/utc-time.ts +24 -1
  885. package/src/version.ts +6 -0
  886. package/src/cli/pane-functions/screenshot.ts +0 -2122
@@ -26,6 +26,7 @@ import { isFiniteNumber } from "../../../utils/guards";
26
26
  import { volumeProfile } from "../../../time-series/trader-studies";
27
27
  import { extendedHoursSpans, isIntradaySeries } from "./session-shading";
28
28
  import { listingTimeZone } from "../../../market-data/market/trading-sessions";
29
+ import { manualValueRangeApplies, valueScaleKey, valueScaleSlot, type CompositeManualValueScale } from "./value-scale";
29
30
 
30
31
  const DAY_MS = 24 * 60 * 60 * 1000;
31
32
 
@@ -328,11 +329,19 @@ function buildAxisDomain(
328
329
  series: ResolvedSeries[],
329
330
  scale: PanelScale,
330
331
  rows: number,
332
+ manualScale?: CompositeManualValueScale,
331
333
  ): CompositeAxisDomain | undefined {
332
334
  const axisSeries = series.filter((entry) => entry.axis === side);
333
335
  if (axisSeries.length === 0) return undefined;
334
336
  const values = axisSeries.flatMap(seriesDomainValues);
335
- const { min, max } = paddedDomain([...values, ...priorCloseInReach(axisSeries, values)], scale);
337
+ const fitted = paddedDomain([...values, ...priorCloseInReach(axisSeries, values)], scale);
338
+ const scaleKey = valueScaleKey(scale, axisSeries);
339
+ // A range set by hand holds while the axis plots the same series and some
340
+ // of their data is in it; otherwise the axis fits the data again.
341
+ const manual = manualScale && manualScale.key === scaleKey && manualValueRangeApplies(manualScale, fitted, scale)
342
+ ? manualScale
343
+ : null;
344
+ const { min, max } = manual ?? fitted;
336
345
  const first = axisSeries[0]!;
337
346
  return {
338
347
  side,
@@ -346,6 +355,8 @@ function buildAxisDomain(
346
355
  seriesIds: axisSeries.map((entry) => entry.id),
347
356
  maxTicks: compositeAxisMaxTicks(rows),
348
357
  tickRows: rows,
358
+ scaleKey,
359
+ ...(manual ? { manual: true } : {}),
349
360
  };
350
361
  }
351
362
 
@@ -510,7 +521,8 @@ function attachLastPriceMarker(
510
521
  const value = lastCloseOf(projected.points);
511
522
  if (value === null) return;
512
523
  const yRatio = projectCompositeValue(value, domain);
513
- if (yRatio === null) return;
524
+ // An axis scaled by hand can leave the last close off the panel.
525
+ if (yRatio === null || (domain.manual && (yRatio < 0 || yRatio > 1))) return;
514
526
  panel.lastPrice = {
515
527
  seriesId: primary.id,
516
528
  color: primary.color,
@@ -837,8 +849,8 @@ export function buildCompositeChartScene(
837
849
  ? dataSeries.filter((entry) => entry.panelId === panel.id)
838
850
  : panelSeries;
839
851
  const rows = panelHeights.get(panel.id) ?? 1;
840
- const left = buildAxisDomain("left", domainSeries, scale, rows);
841
- const right = buildAxisDomain("right", domainSeries, scale, rows);
852
+ const left = buildAxisDomain("left", domainSeries, scale, rows, options.valueScales?.[valueScaleSlot(panel.id, "left")]);
853
+ const right = buildAxisDomain("right", domainSeries, scale, rows, options.valueScales?.[valueScaleSlot(panel.id, "right")]);
842
854
  const axes: Partial<Record<CompositeAxisSide, CompositeAxisDomain>> = { left, right };
843
855
  return {
844
856
  id: panel.id,
@@ -13,6 +13,7 @@ import type {
13
13
  CompositeProjectedSeries,
14
14
  } from "./types";
15
15
  import { clamp } from "../../../utils/math";
16
+ import { clipSegmentToBand } from "./value-scale";
16
17
 
17
18
  function setCell(rows: string[][], x: number, y: number, value: string): void {
18
19
  const row = rows[y];
@@ -43,16 +44,40 @@ function drawLine(rows: string[][], x0: number, y0: number, x1: number, y1: numb
43
44
  }
44
45
  }
45
46
 
46
- function cellPoint(point: CompositeProjectedPoint, width: number, height: number): { x: number; y: number } {
47
+ /**
48
+ * The cell a point falls in. An axis scaled by hand can put it past the top or
49
+ * bottom row, where `keepY` leaves it for the drawing to clip.
50
+ */
51
+ function cellPoint(point: CompositeProjectedPoint, width: number, height: number, keepY = false): { x: number; y: number } {
52
+ const y = Math.round(point.yRatio * Math.max(height - 1, 0));
47
53
  return {
48
54
  x: clamp(Math.round(point.xRatio * Math.max(width - 1, 0)), 0, Math.max(width - 1, 0)),
49
- y: clamp(Math.round(point.yRatio * Math.max(height - 1, 0)), 0, Math.max(height - 1, 0)),
55
+ y: keepY ? y : clamp(y, 0, Math.max(height - 1, 0)),
50
56
  };
51
57
  }
52
58
 
53
59
  function valueRow(value: number, domain: CompositeAxisDomain, height: number): number | null {
54
60
  const ratio = projectCompositeValue(value, domain);
55
- return ratio === null ? null : clamp(Math.round(ratio * Math.max(height - 1, 0)), 0, Math.max(height - 1, 0));
61
+ if (ratio === null) return null;
62
+ const row = Math.round(ratio * Math.max(height - 1, 0));
63
+ return domain.manual ? row : clamp(row, 0, Math.max(height - 1, 0));
64
+ }
65
+
66
+ /** A line between two cells, the part outside the rows (a hand-scaled axis) left off. */
67
+ function drawRowsLine(rows: string[][], x0: number, y0: number, x1: number, y1: number, mark: string): void {
68
+ const last = rows.length - 1;
69
+ if (y0 >= 0 && y0 <= last && y1 >= 0 && y1 <= last) {
70
+ drawLine(rows, x0, y0, x1, y1, mark);
71
+ return;
72
+ }
73
+ const clipped = clipSegmentToBand(x0, y0, x1, y1, -0.49, last + 0.49);
74
+ if (!clipped) return;
75
+ drawLine(rows, Math.round(clipped[0]), Math.round(clipped[1]), Math.round(clipped[2]), Math.round(clipped[3]), mark);
76
+ }
77
+
78
+ /** Rows from `from` to `to`, both ends kept to the rows there are. */
79
+ function rowSpan(from: number, to: number, height: number): [number, number] {
80
+ return [Math.max(0, Math.min(from, to)), Math.min(height - 1, Math.max(from, to))];
56
81
  }
57
82
 
58
83
  function renderLineLike(
@@ -61,8 +86,9 @@ function renderLineLike(
61
86
  width: number,
62
87
  height: number,
63
88
  cue?: SeriesLineCue,
89
+ keepY = false,
64
90
  ): void {
65
- const points = series.points.map((point) => ({ ...cellPoint(point, width, height), point }));
91
+ const points = series.points.map((point) => ({ ...cellPoint(point, width, height, keepY), point }));
66
92
  if (points.length === 0) return;
67
93
  const step = series.source.style === "step" || series.source.interpolation === "step-after";
68
94
  // Beside other lines, each line keeps its own mark the whole way, steps
@@ -73,10 +99,10 @@ function renderLineLike(
73
99
  const current = points[index]!;
74
100
  if (current.point.breakBefore) continue;
75
101
  if (step) {
76
- drawLine(rows, previous.x, previous.y, current.x, previous.y, mark ?? "─");
77
- drawLine(rows, current.x, previous.y, current.x, current.y, mark ?? "│");
102
+ drawRowsLine(rows, previous.x, previous.y, current.x, previous.y, mark ?? "─");
103
+ drawRowsLine(rows, current.x, previous.y, current.x, current.y, mark ?? "│");
78
104
  } else {
79
- drawLine(rows, previous.x, previous.y, current.x, current.y, mark ?? "•");
105
+ drawRowsLine(rows, previous.x, previous.y, current.x, current.y, mark ?? "•");
80
106
  }
81
107
  }
82
108
  for (let index = 0; index < points.length; index += 1) {
@@ -94,9 +120,10 @@ function renderPoints(
94
120
  series: CompositeProjectedSeries,
95
121
  width: number,
96
122
  height: number,
123
+ keepY: boolean,
97
124
  ): void {
98
125
  for (const point of series.points) {
99
- const cell = cellPoint(point, width, height);
126
+ const cell = cellPoint(point, width, height, keepY);
100
127
  setCell(rows, cell.x, cell.y, "●");
101
128
  }
102
129
  }
@@ -109,14 +136,14 @@ function renderArea(
109
136
  height: number,
110
137
  cue?: SeriesLineCue,
111
138
  ): void {
139
+ const keepY = domain.manual === true;
112
140
  const baseline = valueRow(0, domain, height) ?? height - 1;
113
- const points = series.points.map((point) => cellPoint(point, width, height));
141
+ const points = series.points.map((point) => cellPoint(point, width, height, keepY));
114
142
  for (const point of points) {
115
- const top = Math.min(point.y, baseline);
116
- const bottom = Math.max(point.y, baseline);
143
+ const [top, bottom] = rowSpan(point.y, baseline, height);
117
144
  for (let row = top; row <= bottom; row += 1) setCell(rows, point.x, row, "░");
118
145
  }
119
- renderLineLike(rows, series, width, height, cue);
146
+ renderLineLike(rows, series, width, height, cue, keepY);
120
147
  }
121
148
 
122
149
  /** A band's range as shade between its points' low and high rows, under its line. */
@@ -138,7 +165,7 @@ function renderBand(
138
165
  : { x: cellPoint(projected, width, height).x, top: Math.min(top, bottom), bottom: Math.max(top, bottom) };
139
166
  });
140
167
  const shade = (x: number, top: number, bottom: number) => {
141
- for (let row = Math.round(top); row <= Math.round(bottom); row += 1) {
168
+ for (let row = Math.max(0, Math.round(top)); row <= Math.min(height - 1, Math.round(bottom)); row += 1) {
142
169
  const current = rows[row]?.[x];
143
170
  if (current === " " || current === "·") setCell(rows, x, row, "░");
144
171
  }
@@ -157,7 +184,7 @@ function renderBand(
157
184
  shade(x, previous.top + (current.top - previous.top) * t, previous.bottom + (current.bottom - previous.bottom) * t);
158
185
  }
159
186
  }
160
- renderLineLike(rows, series, width, height, cue);
187
+ renderLineLike(rows, series, width, height, cue, domain.manual === true);
161
188
  }
162
189
 
163
190
  function renderColumns(
@@ -170,7 +197,7 @@ function renderColumns(
170
197
  ): void {
171
198
  const baseline = valueRow(0, domain, height) ?? height - 1;
172
199
  for (const point of series.points) {
173
- const cell = cellPoint(point, width, height);
200
+ const cell = cellPoint(point, width, height, domain.manual);
174
201
  const group = layout.groupByPoint.get(point) ?? {
175
202
  index: 0,
176
203
  count: 1,
@@ -194,8 +221,7 @@ function renderColumns(
194
221
  : Math.round(group.index * (groupWidth - 1) / (group.count - 1));
195
222
  cell.x = groupStart + slot;
196
223
  }
197
- const top = Math.min(cell.y, baseline);
198
- const bottom = Math.max(cell.y, baseline);
224
+ const [top, bottom] = rowSpan(cell.y, baseline, height);
199
225
  for (let row = top; row <= bottom; row += 1) setCell(rows, cell.x, row, "█");
200
226
  }
201
227
  }
@@ -221,9 +247,10 @@ function renderOhlc(
221
247
  const highRow = valueRow(high, domain, height);
222
248
  const lowRow = valueRow(low, domain, height);
223
249
  if (closeRow === null || highRow === null || lowRow === null) continue;
224
- drawLine(rows, x, highRow, x, lowRow, "│");
250
+ drawRowsLine(rows, x, highRow, x, lowRow, "│");
225
251
  if (series.source.style === "candles" && openRow !== null) {
226
- for (let row = Math.min(openRow, closeRow); row <= Math.max(openRow, closeRow); row += 1) {
252
+ const [bodyTop, bodyBottom] = rowSpan(openRow, closeRow, height);
253
+ for (let row = bodyTop; row <= bodyBottom; row += 1) {
227
254
  for (let offset = -halfCandleWidth; offset <= halfCandleWidth; offset += 1) {
228
255
  setCell(rows, x + offset, row, "█");
229
256
  }
@@ -292,10 +319,10 @@ export function renderCompositePanelText(
292
319
  break;
293
320
  case "line":
294
321
  case "step":
295
- renderLineLike(rows, series, plotWidth, height, cue);
322
+ renderLineLike(rows, series, plotWidth, height, cue, domain.manual === true);
296
323
  break;
297
324
  case "points":
298
- renderPoints(rows, series, plotWidth, height);
325
+ renderPoints(rows, series, plotWidth, height, domain.manual === true);
299
326
  break;
300
327
  }
301
328
  }
@@ -7,18 +7,35 @@ import { CHART_TOOLS } from "./tool-catalog";
7
7
  /** Icon cells plus the gap between chips. */
8
8
  export const CHART_TOOLBAR_WIDTH = CHART_TOOLS.length * 3 + (CHART_TOOLS.length - 1);
9
9
 
10
+ /** The bar's own button that folds it away, and the one it folds to. */
11
+ const FOLD_BUTTON = {
12
+ label: "Hide drawing tools (Shift+T)",
13
+ glyph: "\u2039",
14
+ icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M10 3.5 5.5 8l4.5 4.5" fill="none" stroke="#000" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
15
+ };
16
+ const UNFOLD_BUTTON = {
17
+ label: "Show drawing tools (Shift+T)",
18
+ glyph: "\u203a",
19
+ icon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M6 3.5 10.5 8 6 12.5" fill="none" stroke="#000" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
20
+ };
21
+
10
22
  function ChartToolButton({
11
23
  tool,
12
24
  active,
13
25
  isDesktopWeb,
14
26
  onPress,
27
+ role = "composite-chart-tool",
28
+ reveal,
15
29
  }: {
16
- tool: (typeof CHART_TOOLS)[number];
30
+ tool: { label: string; glyph: string; icon: string; shortcut?: string; hint?: string };
17
31
  active: boolean;
18
32
  isDesktopWeb: boolean;
19
33
  onPress: () => void;
34
+ role?: string;
35
+ /** Drawn only while the pointer is over the bar (desktop and web). */
36
+ reveal?: boolean;
20
37
  }) {
21
- const label = `${tool.label} (${tool.shortcut}). ${tool.hint}`;
38
+ const label = tool.shortcut ? `${tool.label} (${tool.shortcut}). ${tool.hint}` : tool.label;
22
39
  const color = active ? themeColors.text : themeColors.textDim;
23
40
  return (
24
41
  <Box
@@ -36,8 +53,9 @@ function ChartToolButton({
36
53
  }}
37
54
  cursor="pointer"
38
55
  data-gloom-interactive="true"
39
- data-gloom-role="composite-chart-tool"
56
+ data-gloom-role={role}
40
57
  data-gloom-label={label}
58
+ data-gloom-reveal={reveal ? "hover" : undefined}
41
59
  data-active={active ? "true" : "false"}
42
60
  title={isDesktopWeb ? label : undefined}
43
61
  // A tool is a toggle button: the icon button family, pressed while it is the chart's tool.
@@ -130,6 +148,8 @@ export function ChartToolbar({
130
148
  drawColor,
131
149
  showColors,
132
150
  levelTool,
151
+ folded,
152
+ onToggleFolded,
133
153
  onArmTool,
134
154
  onPickColor,
135
155
  }: {
@@ -141,6 +161,10 @@ export function ChartToolbar({
141
161
  showColors: boolean;
142
162
  /** The chart's levels can be edited here. */
143
163
  levelTool: boolean;
164
+ /** Hidden by the user: the bar is the one button that brings it back. */
165
+ folded: boolean;
166
+ /** Folds the bar away, from the button it shows under the pointer, or opens it again. */
167
+ onToggleFolded: () => void;
144
168
  onArmTool: (tool: ChartToolKind | null) => void;
145
169
  onPickColor: (color: string) => void;
146
170
  }) {
@@ -166,8 +190,19 @@ export function ChartToolbar({
166
190
  }
167
191
  : undefined}
168
192
  data-gloom-role="composite-chart-toolbar"
193
+ data-gloom-reveal-scope="true"
194
+ data-folded={folded ? "true" : undefined}
169
195
  >
170
- {CHART_TOOLS.filter((tool) => levelTool || tool.kind !== "level").map((tool) => (
196
+ {folded ? (
197
+ <ChartToolButton
198
+ tool={UNFOLD_BUTTON}
199
+ active={false}
200
+ isDesktopWeb={isDesktopWeb}
201
+ onPress={onToggleFolded}
202
+ role="composite-chart-toolbar-toggle"
203
+ />
204
+ ) : null}
205
+ {folded ? null : CHART_TOOLS.filter((tool) => levelTool || tool.kind !== "level").map((tool) => (
171
206
  <ChartToolButton
172
207
  key={tool.kind ?? "pan"}
173
208
  tool={tool}
@@ -177,7 +212,7 @@ export function ChartToolbar({
177
212
  />
178
213
  ))}
179
214
  {/* Colours only take space while something can use them. */}
180
- {showColors ? CHART_DRAWING_COLORS.map((color) => (
215
+ {!folded && showColors ? CHART_DRAWING_COLORS.map((color) => (
181
216
  <ChartColorSwatch
182
217
  key={color}
183
218
  color={color}
@@ -186,6 +221,18 @@ export function ChartToolbar({
186
221
  onPress={() => onPickColor(color)}
187
222
  />
188
223
  )) : null}
224
+ {/* The way to fold the bar shows under the pointer, so a chart at rest
225
+ draws the bar as it always has; the terminal has Shift+T and the menu. */}
226
+ {!folded && isDesktopWeb ? (
227
+ <ChartToolButton
228
+ tool={FOLD_BUTTON}
229
+ active={false}
230
+ isDesktopWeb={isDesktopWeb}
231
+ onPress={onToggleFolded}
232
+ role="composite-chart-toolbar-toggle"
233
+ reveal
234
+ />
235
+ ) : null}
189
236
  </Box>
190
237
  );
191
238
  }
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { CompositeChartLevels } from "./levels";
3
3
  import type { SeriesLineCue } from "./series-cues";
4
+ import type { CompositeValueScales } from "./value-scale";
4
5
  import type {
5
6
  ChartPanelSpec,
6
7
  PanelScale,
@@ -38,6 +39,10 @@ export interface CompositeAxisDomain {
38
39
  /** Rows the labels snap to, one per row, in the terminal. Unset where labels
39
40
  * sit at their exact heights. */
40
41
  tickRows?: number;
42
+ /** What the axis plots, which a range set by hand holds to (see `valueScaleKey`). */
43
+ scaleKey?: string;
44
+ /** The range was stretched or squeezed by hand instead of fitted to the data. */
45
+ manual?: boolean;
41
46
  }
42
47
 
43
48
  export interface CompositeProjectedPoint {
@@ -203,6 +208,8 @@ export interface BuildCompositeChartSceneOptions {
203
208
  * is not time, where the last observation belongs at the right edge.
204
209
  */
205
210
  rightOffsetRatio?: number;
211
+ /** Value axes stretched or squeezed by hand, in place of fitting them to the data. */
212
+ valueScales?: CompositeValueScales;
206
213
  }
207
214
 
208
215
  export interface CompositeChartXMarker {
@@ -329,6 +336,12 @@ export interface CompositeChartProps {
329
336
  * Enter hint, such as "anchor here".
330
337
  */
331
338
  timePick?: { label: string; onPick: (date: Date) => void; onCancel: () => void } | null;
339
+ /**
340
+ * Picks a price on the levels' series instead of panning: a press on its
341
+ * plot hands back the price under the pointer, Enter the price at the
342
+ * keyboard cursor; Esc cancels. `label` is the Enter hint, such as "set limit".
343
+ */
344
+ pricePick?: { label: string; onPick: (value: number) => void; onCancel: () => void } | null;
332
345
  /**
333
346
  * Horizontal price levels on one series' panel. With `onEdit` the level
334
347
  * tool (Shift+H) adds, moves and deletes them by mouse and keyboard.
@@ -59,6 +59,31 @@ export interface KeyboardToolDrag {
59
59
  end: ChartDrawingPoint;
60
60
  }
61
61
 
62
+ /** The chart's own layout: its tool bar, its legend and its panels' heights. */
63
+ export interface CompositeChartLayoutControls {
64
+ /** The bar is saved hidden; it still opens while a tool is in hand. */
65
+ toolbarHidden: boolean;
66
+ toggleToolbar: () => void;
67
+ /** The legend has more than one series, so it can fold to its first. */
68
+ legendCollapsible: boolean;
69
+ legendCollapsed: boolean;
70
+ toggleLegend: () => void;
71
+ /** Two or more panels share the plot, so the keys can move the line between them. */
72
+ panelsResizable: boolean;
73
+ stepTopPanel: (direction: 1 | -1) => void;
74
+ /** Heights were set by hand. */
75
+ panelHeightsSet: boolean;
76
+ resetPanelHeights: () => void;
77
+ /** A panel has the whole plot. */
78
+ panelMaximized: boolean;
79
+ restorePanels: () => void;
80
+ }
81
+
82
+ /** Shift with one of the arrows, and no other modifier. */
83
+ function isShiftedArrow(event: { name?: string; shift?: boolean; ctrl?: boolean; meta?: boolean; alt?: boolean }, ...names: string[]): boolean {
84
+ return event.shift === true && !event.ctrl && !event.meta && !event.alt && names.includes(event.name ?? "");
85
+ }
86
+
62
87
  /** Shift and a letter, whether or not the terminal reports the shift itself. */
63
88
  function isShiftedLetter(event: { name?: string; shift?: boolean; ctrl?: boolean; meta?: boolean; alt?: boolean }, letter: string): boolean {
64
89
  if (event.ctrl || event.meta || event.alt) return false;
@@ -76,6 +101,7 @@ export function useCompositeChartKeyboard({
76
101
  pin,
77
102
  onActivate,
78
103
  timePick,
104
+ pricePick,
79
105
  levels,
80
106
  visibleLegendSeries,
81
107
  visibleSeriesIds,
@@ -83,6 +109,7 @@ export function useCompositeChartKeyboard({
83
109
  isSeriesToggleable,
84
110
  navigationFrame,
85
111
  activeUserViewport,
112
+ scaledByHand,
86
113
  panViewportByRatio,
87
114
  zoomViewport,
88
115
  setViewportRange,
@@ -94,6 +121,7 @@ export function useCompositeChartKeyboard({
94
121
  addDrawing,
95
122
  removeDrawing,
96
123
  pickDrawColor,
124
+ layout,
97
125
  }: {
98
126
  focused: boolean;
99
127
  interactive: boolean;
@@ -106,6 +134,7 @@ export function useCompositeChartKeyboard({
106
134
  pin: { pinned: boolean; toggle: () => void } | null;
107
135
  onActivate: CompositeChartProps["onActivate"];
108
136
  timePick: CompositeChartProps["timePick"];
137
+ pricePick: CompositeChartProps["pricePick"];
109
138
  levels: CompositeChartProps["levels"];
110
139
  visibleLegendSeries: ResolvedSeries[];
111
140
  visibleSeriesIds: ReadonlySet<string>;
@@ -113,6 +142,8 @@ export function useCompositeChartKeyboard({
113
142
  isSeriesToggleable: CompositeChartProps["isSeriesToggleable"];
114
143
  navigationFrame: CompositeNavigationFrame | null;
115
144
  activeUserViewport: CompositeViewportRange | null;
145
+ /** A value axis was stretched or squeezed by hand, which `resetViewport` also fits again. */
146
+ scaledByHand: boolean;
116
147
  panViewportByRatio: (shiftRatio: number) => void;
117
148
  zoomViewport: (zoomFactor: number, anchorRatio?: number) => void;
118
149
  setViewportRange: (range: CompositeViewportRange) => void;
@@ -124,6 +155,7 @@ export function useCompositeChartKeyboard({
124
155
  addDrawing: (drawing: ChartDrawing) => void;
125
156
  removeDrawing: () => void;
126
157
  pickDrawColor: (color: string) => void;
158
+ layout: CompositeChartLayoutControls;
127
159
  }) {
128
160
  const [legendKeyboardIndex, setLegendKeyboardIndex] = useState<number | null>(null);
129
161
  const [armedTool, setArmedTool] = useState<ChartToolKind | null>(null);
@@ -187,8 +219,8 @@ export function useCompositeChartKeyboard({
187
219
  if (wasFocusedRef.current && !focused) setEntered(false);
188
220
  wasFocusedRef.current = focused;
189
221
  }, [focused]);
190
- // A time is picked with the arrows and Enter.
191
- const picking = !!timePick;
222
+ // A time or a price is picked with the arrows and Enter.
223
+ const picking = !!timePick || !!pricePick;
192
224
  useEffect(() => {
193
225
  if (picking) setEntered(true);
194
226
  }, [picking]);
@@ -287,6 +319,8 @@ export function useCompositeChartKeyboard({
287
319
  };
288
320
  const stepLegend = (direction: -1 | 1) => {
289
321
  onActivate?.();
322
+ // The series stepped to must be on screen.
323
+ if (layout.legendCollapsed) layout.toggleLegend();
290
324
  setLegendKeyboardIndex((current) => (
291
325
  current === null
292
326
  ? direction > 0 ? 0 : visibleLegendSeries.length - 1
@@ -298,9 +332,9 @@ export function useCompositeChartKeyboard({
298
332
  onActivate?.();
299
333
  onToggleSeries?.(legendEntry.id);
300
334
  };
301
- /** A level at the keyboard cursor's price, or the last price without a cursor. */
302
- const addLevelAtCursor = () => {
303
- if (!levels?.onEdit || !levelHost || !scene) return;
335
+ /** The levels' series price at the keyboard cursor, or the last price without a cursor. */
336
+ const priceAtCursor = (): number | null => {
337
+ if (!levels || !levelHost || !scene) return null;
304
338
  const { panel, domain } = levelHost;
305
339
  const date = keyboardCursorDateRef.current ?? scene.dates.at(-1) ?? null;
306
340
  // The levels' own series, not whichever one the panel lists first.
@@ -308,8 +342,13 @@ export function useCompositeChartKeyboard({
308
342
  const value = (date ? resolveMeasureValueAt(pricePanel, date.getTime()) : null)
309
343
  ?? (panel.lastPrice?.seriesId === levels.seriesId ? panel.lastPrice.value : null)
310
344
  ?? unprojectCompositeValue(0.5, domain);
311
- if (value === null) return;
312
- const rounded = roundLevelValue(value, domain);
345
+ return value === null ? null : roundLevelValue(value, domain);
346
+ };
347
+ /** A level at the keyboard cursor's price, or the last price without a cursor. */
348
+ const addLevelAtCursor = () => {
349
+ if (!levels?.onEdit) return;
350
+ const rounded = priceAtCursor();
351
+ if (rounded === null) return;
313
352
  onActivate?.();
314
353
  // Enter again at the same cursor picks the level already there.
315
354
  const existing = levelItems.find((level) => level.editable && level.value === rounded);
@@ -342,7 +381,8 @@ export function useCompositeChartKeyboard({
342
381
  setSelectedLevelId(ordered[next]!.id);
343
382
  };
344
383
  const removeSelectedLevel = () => {
345
- if (!selectedLevel?.editable) return;
384
+ // An order's line moves here; it is cancelled where the order is.
385
+ if (!selectedLevel?.editable || selectedLevel.draggable) return;
346
386
  levels?.onEdit?.({ kind: "remove", id: selectedLevel.id });
347
387
  setSelectedLevelId(null);
348
388
  };
@@ -403,6 +443,13 @@ export function useCompositeChartKeyboard({
403
443
  else chartActionsRef.current.pick();
404
444
  return;
405
445
  }
446
+ // Esc ends a price pick even with nothing drawn yet; Enter needs a price at the cursor.
447
+ if (pricePick && (scene || isPlainKey(event, "escape")) && isPlainKey(event, "return", "enter", "escape")) {
448
+ consume();
449
+ if (event.name === "escape") pricePick.onCancel();
450
+ else chartActionsRef.current.pickPrice();
451
+ return;
452
+ }
406
453
  if (zoned && !entered && isPlainKey(event, "down", "return", "enter")) {
407
454
  consume();
408
455
  enterChart();
@@ -424,7 +471,7 @@ export function useCompositeChartKeyboard({
424
471
  stepLevel(event.name === "[" ? -1 : 1);
425
472
  return;
426
473
  }
427
- if (toolsActive && selectedLevel?.editable && levelsEditable && isPlainKey(event, "backspace", "delete")) {
474
+ if (toolsActive && selectedLevel?.editable && !selectedLevel.draggable && levelsEditable && isPlainKey(event, "backspace", "delete")) {
428
475
  consume();
429
476
  removeSelectedLevel();
430
477
  return;
@@ -453,6 +500,21 @@ export function useCompositeChartKeyboard({
453
500
  setKeyboardPlacement((current) => current && moveKeyboardPlacement(current, { level }));
454
501
  return;
455
502
  }
503
+ if (toolsActive && isShiftedLetter(event, "t")) {
504
+ consume();
505
+ layout.toggleToolbar();
506
+ return;
507
+ }
508
+ if (legendKeysActive && layout.legendCollapsible && isShiftedLetter(event, "l")) {
509
+ consume();
510
+ layout.toggleLegend();
511
+ return;
512
+ }
513
+ if (toolsActive && layout.panelsResizable && isShiftedArrow(event, "up", "down")) {
514
+ consume();
515
+ layout.stepTopPanel(event.name === "up" ? 1 : -1);
516
+ return;
517
+ }
456
518
  if (isPlainKey(event, "[", "]") && (drawingKeysActive || legendKeysActive)) {
457
519
  consume();
458
520
  const direction = event.name === "[" ? -1 : 1;
@@ -579,6 +641,10 @@ export function useCompositeChartKeyboard({
579
641
  const date = keyboardCursorDateRef.current ?? scene?.dates.at(-1) ?? null;
580
642
  if (date) timePick?.onPick(date);
581
643
  },
644
+ pickPrice: () => {
645
+ const value = priceAtCursor();
646
+ if (value !== null) pricePick?.onPick(value);
647
+ },
582
648
  start: armedTool === "level" ? addLevelAtCursor : startKeyboardPlacement,
583
649
  finish: finishKeyboardPlacement,
584
650
  stepLevel,
@@ -596,6 +662,7 @@ export function useCompositeChartKeyboard({
596
662
  },
597
663
  leave: leaveChart,
598
664
  togglePin: () => pin?.toggle(),
665
+ layout,
599
666
  };
600
667
  const chartActionsRef = useRef(chartActions);
601
668
  chartActionsRef.current = chartActions;
@@ -608,17 +675,27 @@ export function useCompositeChartKeyboard({
608
675
  const armedHints = armedTool ? KEYBOARD_TOOL_HINTS[armedTool] : null;
609
676
  const placing = !!keyboardPlacement;
610
677
  const legendEntryVisible = !!legendEntry && visibleSeriesIds.has(legendEntry.id);
611
- const resettable = !!activeUserViewport;
612
- const timePickLabel = timePick?.label ?? null;
678
+ const resettable = !!activeUserViewport || scaledByHand;
679
+ const timePickLabel = timePick?.label ?? (levelHost ? pricePick?.label : null) ?? null;
680
+ const pickingPrice = !timePick && !!pricePick;
613
681
  const levelActionHint = selectedLevel?.actionable && levels?.action ? levels.action : null;
614
682
  const levelToolKeys = toolsActive && armedTool === "level" && levelsEditable;
615
- const canDeleteLevel = toolsActive && levelsEditable && !!selectedLevel?.editable;
683
+ const canDeleteLevel = toolsActive && levelsEditable && !!selectedLevel?.editable && !selectedLevel.draggable;
616
684
  const pinState = pin ? pin.pinned : null;
685
+ // Hidden as it shows: a saved hidden bar is open while a tool is in hand.
686
+ const toolbarHidden = layout.toolbarHidden && armedTool === null;
687
+ const {
688
+ legendCollapsible,
689
+ legendCollapsed,
690
+ panelsResizable,
691
+ panelHeightsSet,
692
+ panelMaximized,
693
+ } = layout;
617
694
  usePaneFooter(keyboardId, () => {
618
695
  if (!keyboardActive || !scene) return null;
619
696
  const hints: PaneHint[] = [];
620
697
  if (timePickLabel) {
621
- hints.push({ id: "chart-pick", key: "Enter", label: timePickLabel, onPress: () => chartActionsRef.current.pick() });
698
+ hints.push({ id: "chart-pick", key: "Enter", label: timePickLabel, onPress: () => pickingPrice ? chartActionsRef.current.pickPrice() : chartActionsRef.current.pick() });
622
699
  } else if (toolsActive && armedHints) {
623
700
  hints.push(placing
624
701
  ? { id: "chart-tool", key: "Enter", label: armedHints.finish, title: armedHints.finishTitle, onPress: () => chartActionsRef.current.finish() }
@@ -686,6 +763,29 @@ export function useCompositeChartKeyboard({
686
763
  });
687
764
  }
688
765
  if (resettable) menu.push({ id: "chart-reset", label: "Reset Zoom", accelerator: "0", onSelect: () => chartActionsRef.current.reset() });
766
+ menu.push({
767
+ id: "chart-toolbar",
768
+ label: toolbarHidden ? "Show Drawing Tools" : "Hide Drawing Tools",
769
+ accelerator: "Shift+T",
770
+ onSelect: () => chartActionsRef.current.layout.toggleToolbar(),
771
+ });
772
+ if (panelsResizable) {
773
+ menu.push({ id: "chart-panel-taller", label: "Taller Top Panel", accelerator: "Shift+Up", onSelect: () => chartActionsRef.current.layout.stepTopPanel(1) });
774
+ menu.push({ id: "chart-panel-shorter", label: "Shorter Top Panel", accelerator: "Shift+Down", onSelect: () => chartActionsRef.current.layout.stepTopPanel(-1) });
775
+ }
776
+ if (panelMaximized) {
777
+ menu.push({ id: "chart-panels-restore", label: "Show All Panels", onSelect: () => chartActionsRef.current.layout.restorePanels() });
778
+ } else if (panelHeightsSet) {
779
+ menu.push({ id: "chart-panels-reset", label: "Reset Panel Heights", onSelect: () => chartActionsRef.current.layout.resetPanelHeights() });
780
+ }
781
+ }
782
+ if (legendKeysActive && legendCollapsible) {
783
+ menu.push({
784
+ id: "chart-legend",
785
+ label: legendCollapsed ? "Expand Legend" : "Collapse Legend",
786
+ accelerator: "Shift+L",
787
+ onSelect: () => chartActionsRef.current.layout.toggleLegend(),
788
+ });
689
789
  }
690
790
  if (legendKeysActive && anyLegendToggleable && !drawingKeysActive) {
691
791
  menu.push({ id: "chart-series-next", label: "Next Series", accelerator: "]", onSelect: () => chartActionsRef.current.stepLegend(1) });
@@ -706,6 +806,7 @@ export function useCompositeChartKeyboard({
706
806
  !!scene,
707
807
  selectedDrawingId,
708
808
  timePickLabel,
809
+ pickingPrice,
709
810
  levelActionHint,
710
811
  levelToolKeys,
711
812
  levelItems.length,
@@ -713,6 +814,12 @@ export function useCompositeChartKeyboard({
713
814
  levelsEditable,
714
815
  toolsActive,
715
816
  pinState,
817
+ toolbarHidden,
818
+ legendCollapsible,
819
+ legendCollapsed,
820
+ panelsResizable,
821
+ panelHeightsSet,
822
+ panelMaximized,
716
823
  ]);
717
824
 
718
825
  return {