gloomberb 0.16.1 → 0.16.3

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 (643) 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 +26 -8
  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 +2 -0
  8. package/src/api-client/market-discovery.ts +10 -0
  9. package/src/api-client/paths.ts +30 -1
  10. package/src/api-client/perps.ts +37 -0
  11. package/src/api-client/request.ts +5 -2
  12. package/src/api-client/types.ts +2 -0
  13. package/src/brokers/account-cache.ts +69 -0
  14. package/src/cli/command-options.ts +74 -0
  15. package/src/cli/commands/command-utils.ts +37 -0
  16. package/src/cli/commands/crypto-hints.ts +75 -0
  17. package/src/cli/commands/market.ts +560 -136
  18. package/src/cli/commands/overview.ts +136 -48
  19. package/src/cli/commands/ticker.ts +220 -67
  20. package/src/cli/desktop-pane-shot.ts +37 -4
  21. package/src/cli/freshness.ts +61 -0
  22. package/src/cli/help.ts +27 -6
  23. package/src/cli/helpers.ts +4 -8
  24. package/src/cli/history-rows.ts +187 -15
  25. package/src/cli/index.ts +23 -8
  26. package/src/cli/listing-arg.ts +321 -0
  27. package/src/cli/options.ts +5 -1
  28. package/src/cli/pane-functions/access-gate.ts +42 -0
  29. package/src/cli/pane-functions/capabilities.ts +5 -0
  30. package/src/cli/pane-functions/catalog.ts +28 -1
  31. package/src/cli/pane-functions/data.ts +3 -1
  32. package/src/cli/pane-functions/dom.ts +87 -16
  33. package/src/cli/pane-functions/freshness.ts +400 -0
  34. package/src/cli/pane-functions/function-help.ts +31 -22
  35. package/src/cli/pane-functions/headless.ts +201 -41
  36. package/src/cli/pane-functions/index.ts +24 -6
  37. package/src/cli/pane-functions/options.ts +3 -0
  38. package/src/cli/pane-functions/report.ts +12 -1
  39. package/src/cli/pane-functions/resolver.ts +63 -9
  40. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  41. package/src/cli/pane-functions/screenshot.ts +11 -3
  42. package/src/cli/registry.ts +6 -3
  43. package/src/cli/report-tables.ts +460 -0
  44. package/src/cli/result.ts +53 -29
  45. package/src/cli/ticker-resolution.ts +7 -5
  46. package/src/components/chart/composite/composite-chart.tsx +88 -2536
  47. package/src/components/chart/composite/drawing-store.ts +59 -0
  48. package/src/components/chart/composite/legend.tsx +319 -0
  49. package/src/components/chart/composite/panel-bitmap.ts +139 -0
  50. package/src/components/chart/composite/panel-gestures.ts +59 -0
  51. package/src/components/chart/composite/panel-labels.ts +107 -0
  52. package/src/components/chart/composite/panel-surface.tsx +876 -0
  53. package/src/components/chart/composite/tool-catalog.ts +98 -0
  54. package/src/components/chart/composite/toolbar.tsx +186 -0
  55. package/src/components/chart/composite/tools.ts +8 -0
  56. package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
  57. package/src/components/chart/composite/use-composite-viewport.ts +143 -0
  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/ticker-search/actions.ts +5 -0
  62. package/src/components/command-bar/workflow/ops.ts +1 -1
  63. package/src/components/command-bar/workflow/tickers.ts +6 -0
  64. package/src/components/data-table/export.ts +6 -51
  65. package/src/components/data-table/view.tsx +32 -11
  66. package/src/components/feedback-dialog.tsx +2 -1
  67. package/src/components/form-modal/field-row.tsx +2 -2
  68. package/src/components/layout/detached-pane-shell.tsx +6 -3
  69. package/src/components/layout/pane/content.tsx +23 -10
  70. package/src/components/layout/pane/error-boundary.tsx +103 -0
  71. package/src/components/layout/pane/footer/registration.tsx +68 -23
  72. package/src/components/layout/pane/header.tsx +11 -11
  73. package/src/components/layout/shell/active-drag.ts +67 -35
  74. package/src/components/layout/shell/cursor-occlusion.ts +6 -5
  75. package/src/components/layout/shell/drag/index.ts +12 -7
  76. package/src/components/layout/shell/drag/live.ts +122 -0
  77. package/src/components/layout/shell/drag/overlays.tsx +179 -35
  78. package/src/components/layout/shell/drag/runtime.ts +62 -50
  79. package/src/components/layout/shell/drag/slide.ts +10 -0
  80. package/src/components/layout/shell/index.tsx +37 -51
  81. package/src/components/layout/shell/menu.ts +2 -1
  82. package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
  83. package/src/components/layout/shell/native/surfaces.ts +30 -14
  84. package/src/components/layout/shell/pane/actions.ts +2 -1
  85. package/src/components/layout/shell/pane/layers.tsx +419 -168
  86. package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
  87. package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
  88. package/src/components/metric-treemap/heat-surface.tsx +43 -16
  89. package/src/components/metric-treemap/heat-tiles.ts +18 -0
  90. package/src/components/metric-treemap/layout.ts +2 -0
  91. package/src/components/onboarding/onboarding-keyboard.ts +311 -0
  92. package/src/components/onboarding/onboarding-wizard.tsx +101 -788
  93. package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
  94. package/src/components/onboarding/use-onboarding-progress.ts +298 -0
  95. package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
  96. package/src/components/ticker/list-table-view.tsx +13 -1
  97. package/src/components/ui/fields.tsx +8 -0
  98. package/src/components/ui/range-track.tsx +10 -3
  99. package/src/components/ui/status.tsx +8 -2
  100. package/src/components/ui/tabs.tsx +7 -4
  101. package/src/components/ui/text-prompt-dialog.tsx +4 -2
  102. package/src/data/config/store/normalize.ts +17 -1
  103. package/src/data/json-persistence.ts +17 -3
  104. package/src/data/json-storage.ts +2 -0
  105. package/src/data/memory-resource-store.ts +46 -0
  106. package/src/i18n/es.ts +19 -1
  107. package/src/i18n/ja.ts +19 -1
  108. package/src/i18n/ko.ts +19 -1
  109. package/src/i18n/zh-cn.ts +19 -1
  110. package/src/i18n/zh-tw.ts +19 -1
  111. package/src/market-data/coordinator/chart.ts +1 -1
  112. package/src/market-data/coordinator/quotes.ts +23 -4
  113. package/src/market-data/fx-closes.ts +72 -0
  114. package/src/market-data/market/freshness.ts +123 -6
  115. package/src/market-data/market/session-close-note.ts +57 -0
  116. package/src/market-data/market/status.ts +151 -0
  117. package/src/market-data/published-apac-sessions.ts +66 -0
  118. package/src/market-data/quotes/contributions.ts +2 -0
  119. package/src/market-data/quotes/freshness.ts +5 -0
  120. package/src/market-data/quotes/resolution.ts +2 -0
  121. package/src/market-data/quotes/screener-live-quotes.ts +49 -4
  122. package/src/plugins/builtin/account-management/pane.tsx +4 -0
  123. package/src/plugins/builtin/alerts/cli.ts +10 -5
  124. package/src/plugins/builtin/alerts/index.tsx +1 -0
  125. package/src/plugins/builtin/analytics/metrics.ts +8 -3
  126. package/src/plugins/builtin/analytics/pane-model.ts +10 -6
  127. package/src/plugins/builtin/analytics/risk-client.ts +191 -66
  128. package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
  129. package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
  130. package/src/plugins/builtin/analytics/risk-model.ts +45 -17
  131. package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
  132. package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
  133. package/src/plugins/builtin/attention/headless.ts +6 -4
  134. package/src/plugins/builtin/attention/index.tsx +1 -1
  135. package/src/plugins/builtin/attention/pane.tsx +2 -2
  136. package/src/plugins/builtin/awards/headless.ts +1 -0
  137. package/src/plugins/builtin/awards/pane.tsx +1 -1
  138. package/src/plugins/builtin/backtest/headless.ts +1 -0
  139. package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
  140. package/src/plugins/builtin/buildout/index.tsx +1 -0
  141. package/src/plugins/builtin/catalysts/detail.tsx +1 -1
  142. package/src/plugins/builtin/catalysts/headless.ts +3 -1
  143. package/src/plugins/builtin/cds/headless.ts +2 -0
  144. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
  145. package/src/plugins/builtin/chart-composer/headless.ts +38 -3
  146. package/src/plugins/builtin/chart-composer/index.tsx +3 -1
  147. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
  148. package/src/plugins/builtin/chat/channels.ts +19 -3
  149. package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
  150. package/src/plugins/builtin/chat/content/footer.tsx +15 -6
  151. package/src/plugins/builtin/chat/content/index.tsx +120 -21
  152. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
  153. package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
  154. package/src/plugins/builtin/chat/direct-messages.ts +200 -0
  155. package/src/plugins/builtin/chat/index.tsx +1 -0
  156. package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
  157. package/src/plugins/builtin/chat/message/header.tsx +16 -6
  158. package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
  159. package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
  160. package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
  161. package/src/plugins/builtin/chat/message/types.ts +14 -2
  162. package/src/plugins/builtin/chat/profile-popover.ts +18 -13
  163. package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
  164. package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
  165. package/src/plugins/builtin/cloud/plugin.tsx +1 -0
  166. package/src/plugins/builtin/cloud/team/module.tsx +1 -0
  167. package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
  168. package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
  169. package/src/plugins/builtin/comment-letters/index.tsx +1 -0
  170. package/src/plugins/builtin/company-attention/headless.ts +5 -1
  171. package/src/plugins/builtin/company-attention/pane.tsx +2 -2
  172. package/src/plugins/builtin/company-kpis/headless.ts +1 -0
  173. package/src/plugins/builtin/congress-trades/headless.ts +1 -0
  174. package/src/plugins/builtin/correlation/compute.ts +59 -16
  175. package/src/plugins/builtin/correlation/geo.ts +34 -0
  176. package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
  177. package/src/plugins/builtin/correlation/headless.ts +42 -8
  178. package/src/plugins/builtin/correlation/history.ts +2 -0
  179. package/src/plugins/builtin/correlation/index.tsx +68 -14
  180. package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
  181. package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
  182. package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
  183. package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
  184. package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
  185. package/src/plugins/builtin/correlation/settings.ts +1 -1
  186. package/src/plugins/builtin/cot/headless.ts +6 -3
  187. package/src/plugins/builtin/cot/index.tsx +3 -3
  188. package/src/plugins/builtin/cot/model.ts +36 -3
  189. package/src/plugins/builtin/cpi/headless.ts +4 -0
  190. package/src/plugins/builtin/credit-boards/headless.ts +2 -0
  191. package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
  192. package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
  193. package/src/plugins/builtin/credit-documents/headless.ts +2 -0
  194. package/src/plugins/builtin/crypto-board/headless.ts +3 -0
  195. package/src/plugins/builtin/custom-view/loader.ts +1 -1
  196. package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
  197. package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
  198. package/src/plugins/builtin/doe/headless.ts +7 -0
  199. package/src/plugins/builtin/doe/range-bar.tsx +7 -37
  200. package/src/plugins/builtin/earnings/headless.ts +5 -0
  201. package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
  202. package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
  203. package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
  204. package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
  205. package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
  206. package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
  207. package/src/plugins/builtin/econ/index.tsx +1 -0
  208. package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
  209. package/src/plugins/builtin/equity-screener/headless.ts +2 -0
  210. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  211. package/src/plugins/builtin/executives/index.tsx +1 -0
  212. package/src/plugins/builtin/exposure/headless.ts +3 -1
  213. package/src/plugins/builtin/fear-greed/headless.ts +2 -0
  214. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  215. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  216. package/src/plugins/builtin/futures-curve/headless.ts +39 -10
  217. package/src/plugins/builtin/futures-curve/index.tsx +3 -3
  218. package/src/plugins/builtin/futures-curve/model.ts +188 -4
  219. package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
  220. package/src/plugins/builtin/gpu/headless.ts +7 -3
  221. package/src/plugins/builtin/gpu/ladder.tsx +26 -30
  222. package/src/plugins/builtin/gpu/model.ts +27 -1
  223. package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
  224. package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
  225. package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
  226. package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
  227. package/src/plugins/builtin/holders/client.ts +3 -6
  228. package/src/plugins/builtin/holders/format.ts +31 -1
  229. package/src/plugins/builtin/holders/headless.ts +161 -6
  230. package/src/plugins/builtin/holders/index.tsx +10 -3
  231. package/src/plugins/builtin/holders/pane.tsx +42 -16
  232. package/src/plugins/builtin/holders/report-header.ts +136 -0
  233. package/src/plugins/builtin/holders/table-model.ts +20 -5
  234. package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
  235. package/src/plugins/builtin/holders/types.ts +2 -1
  236. package/src/plugins/builtin/insider/headless.ts +2 -0
  237. package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
  238. package/src/plugins/builtin/iv-history/headless.ts +4 -1
  239. package/src/plugins/builtin/jobs/headless.ts +1 -0
  240. package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
  241. package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
  242. package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
  243. package/src/plugins/builtin/macro-day/headless.ts +2 -0
  244. package/src/plugins/builtin/market-halts/index.tsx +1 -0
  245. package/src/plugins/builtin/market-heatmap/data.ts +2 -0
  246. package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
  247. package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
  248. package/src/plugins/builtin/market-heatmap/model.ts +146 -0
  249. package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
  250. package/src/plugins/builtin/market-movers/headless.ts +2 -0
  251. package/src/plugins/builtin/market-valuation/headless.ts +2 -0
  252. package/src/plugins/builtin/members/client.ts +20 -3
  253. package/src/plugins/builtin/members/headless.ts +5 -3
  254. package/src/plugins/builtin/members/model.ts +10 -2
  255. package/src/plugins/builtin/members/pane.tsx +23 -6
  256. package/src/plugins/builtin/mna/distress/headless.ts +1 -0
  257. package/src/plugins/builtin/mna/headless.ts +1 -0
  258. package/src/plugins/builtin/money-markets/headless.ts +1 -0
  259. package/src/plugins/builtin/news/headless.ts +2 -0
  260. package/src/plugins/builtin/news/wire/index.tsx +8 -1
  261. package/src/plugins/builtin/notes/cli.ts +14 -6
  262. package/src/plugins/builtin/notes/index.tsx +1 -0
  263. package/src/plugins/builtin/openfda/index.tsx +1 -0
  264. package/src/plugins/builtin/options-calculator/headless.ts +2 -0
  265. package/src/plugins/builtin/options-positioning/headless.ts +3 -0
  266. package/src/plugins/builtin/options-scenario/headless.ts +5 -0
  267. package/src/plugins/builtin/pe-band/client.ts +48 -3
  268. package/src/plugins/builtin/pe-band/headless.ts +25 -7
  269. package/src/plugins/builtin/pe-band/model.ts +92 -16
  270. package/src/plugins/builtin/pe-band/pane.tsx +33 -16
  271. package/src/plugins/builtin/perps/client.ts +50 -3
  272. package/src/plugins/builtin/perps/headless.ts +144 -16
  273. package/src/plugins/builtin/perps/index.tsx +6 -6
  274. package/src/plugins/builtin/perps/model.ts +189 -12
  275. package/src/plugins/builtin/perps/pane.tsx +249 -48
  276. package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
  277. package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
  278. package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
  279. package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
  280. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
  281. package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
  282. package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
  283. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
  284. package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
  285. package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
  286. package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
  287. package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
  288. package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
  289. package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
  290. package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
  291. package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
  292. package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
  293. package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
  294. package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
  295. package/src/plugins/builtin/power/headless.ts +3 -1
  296. package/src/plugins/builtin/rate-path/headless.ts +2 -0
  297. package/src/plugins/builtin/realized-vol/headless.ts +2 -0
  298. package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
  299. package/src/plugins/builtin/research/analyst-headless.ts +3 -0
  300. package/src/plugins/builtin/research/events-headless.ts +2 -0
  301. package/src/plugins/builtin/research/headless.ts +2 -0
  302. package/src/plugins/builtin/research/index.tsx +1 -0
  303. package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
  304. package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
  305. package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
  306. package/src/plugins/builtin/research-search/index.tsx +1 -0
  307. package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
  308. package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
  309. package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
  310. package/src/plugins/builtin/risk-factors/headless.ts +2 -0
  311. package/src/plugins/builtin/scanner/flow-history.ts +2 -13
  312. package/src/plugins/builtin/scanner/headless.ts +14 -0
  313. package/src/plugins/builtin/seasonality/headless.ts +2 -0
  314. package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
  315. package/src/plugins/builtin/sec/filing-content.ts +42 -17
  316. package/src/plugins/builtin/sec/forms.ts +12 -0
  317. package/src/plugins/builtin/sec/headless.ts +2 -0
  318. package/src/plugins/builtin/sectors/client.ts +1 -0
  319. package/src/plugins/builtin/sectors/headless.ts +9 -1
  320. package/src/plugins/builtin/sectors/sector-model.ts +2 -0
  321. package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
  322. package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
  323. package/src/plugins/builtin/shared/members-menu.tsx +260 -0
  324. package/src/plugins/builtin/shared/report-freshness.ts +57 -0
  325. package/src/plugins/builtin/shared/research-cells.tsx +4 -9
  326. package/src/plugins/builtin/short-interest/headless.ts +2 -0
  327. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  328. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  329. package/src/plugins/builtin/short-volume/pane.tsx +1 -1
  330. package/src/plugins/builtin/social-mentions/headless.ts +1 -0
  331. package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
  332. package/src/plugins/builtin/supply-chain/headless.ts +7 -1
  333. package/src/plugins/builtin/supply-chain/index.tsx +10 -1
  334. package/src/plugins/builtin/supply-chain/model.ts +27 -2
  335. package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
  336. package/src/plugins/builtin/themes/headless.ts +3 -0
  337. package/src/plugins/builtin/themes/pane.tsx +3 -0
  338. package/src/plugins/builtin/thirteenf/headless.ts +110 -25
  339. package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
  340. package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
  341. package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
  342. package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
  343. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  344. package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
  345. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
  346. package/src/plugins/builtin/time-sales/headless.ts +5 -1
  347. package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
  348. package/src/plugins/builtin/volatility/headless.ts +6 -1
  349. package/src/plugins/builtin/world-indices/headless.ts +2 -0
  350. package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
  351. package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
  352. package/src/plugins/builtin/world-venue-map/client.ts +45 -0
  353. package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
  354. package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
  355. package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
  356. package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
  357. package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
  358. package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
  359. package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
  360. package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
  361. package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
  362. package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
  363. package/src/plugins/builtin/world-venue-map/index.ts +69 -6
  364. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
  365. package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
  366. package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
  367. package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
  368. package/src/plugins/builtin/world-venue-map/model.ts +23 -4
  369. package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
  370. package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
  371. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
  372. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
  373. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
  374. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
  375. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
  376. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
  377. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
  378. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
  379. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
  380. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
  381. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
  382. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
  383. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
  384. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
  385. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
  386. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
  387. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
  388. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
  389. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
  390. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
  391. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
  392. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
  393. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
  394. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
  395. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
  396. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
  397. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
  398. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
  399. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
  400. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
  401. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
  402. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
  403. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
  404. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
  405. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
  406. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
  407. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
  408. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
  409. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
  410. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
  411. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
  412. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
  413. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
  414. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
  415. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
  416. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
  417. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
  418. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
  419. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
  420. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
  421. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
  422. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
  423. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
  424. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
  425. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
  426. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
  427. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
  428. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
  429. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
  430. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
  431. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
  432. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
  433. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
  434. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
  435. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
  436. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
  437. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
  438. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
  439. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
  440. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
  441. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
  442. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
  443. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
  444. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
  445. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
  446. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
  447. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
  448. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
  449. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
  450. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
  451. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
  452. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
  453. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
  454. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
  455. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
  456. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
  457. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
  458. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
  459. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
  460. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
  461. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
  462. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
  463. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
  464. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
  465. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
  466. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
  467. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
  468. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
  469. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
  470. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
  471. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
  472. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
  473. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
  474. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
  475. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
  476. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
  477. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
  478. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
  479. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
  480. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
  481. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
  482. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
  483. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
  484. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
  485. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
  486. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
  487. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
  488. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
  489. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
  490. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
  491. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
  492. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
  493. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
  494. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
  495. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
  496. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
  497. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
  498. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
  499. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
  500. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
  501. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
  502. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
  503. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
  504. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
  505. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
  506. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
  507. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
  508. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
  509. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
  510. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
  511. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
  512. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
  513. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
  514. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
  515. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
  516. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
  517. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
  518. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
  519. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
  520. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
  521. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
  522. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
  523. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
  524. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
  525. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
  526. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
  527. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
  528. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
  529. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
  530. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
  531. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
  532. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
  533. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
  534. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
  535. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
  536. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
  537. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
  538. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
  539. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
  540. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
  541. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
  542. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
  543. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
  544. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
  545. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
  546. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
  547. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
  548. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
  549. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
  550. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
  551. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
  552. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
  553. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
  554. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
  555. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
  556. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
  557. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
  558. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
  559. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
  560. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
  561. package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
  562. package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
  563. package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
  564. package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
  565. package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
  566. package/src/plugins/builtin/yield-curve/headless.ts +16 -0
  567. package/src/plugins/loader.ts +13 -1
  568. package/src/plugins/registry/pane-settings.ts +1 -0
  569. package/src/renderers/browser/app-services.ts +3 -1
  570. package/src/renderers/dom/build-assets.ts +81 -3
  571. package/src/renderers/dom/data-table/dom.ts +31 -0
  572. package/src/renderers/dom/data-table/index.tsx +5 -0
  573. package/src/renderers/dom/data-table/row.tsx +2 -0
  574. package/src/renderers/dom/desktop/controls.tsx +7 -3
  575. package/src/renderers/dom/desktop/list-view.tsx +35 -10
  576. package/src/renderers/dom/desktop/popover.tsx +73 -14
  577. package/src/renderers/dom/host/box.tsx +113 -17
  578. package/src/renderers/dom/host/drag-shield.ts +24 -0
  579. package/src/renderers/dom/host/input.tsx +14 -3
  580. package/src/renderers/dom/host/live-frame.ts +54 -0
  581. package/src/renderers/dom/host/mouse.ts +8 -1
  582. package/src/renderers/dom/host/scroll-box.tsx +6 -5
  583. package/src/renderers/dom/host/tabs.tsx +3 -2
  584. package/src/renderers/dom/styles.css +16 -9
  585. package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
  586. package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
  587. package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
  588. package/src/renderers/electrobun/shared/protocol.ts +10 -1
  589. package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
  590. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
  591. package/src/renderers/electrobun/view/host/native.ts +0 -10
  592. package/src/renderers/electrobun/view/host/window-move.ts +28 -0
  593. package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
  594. package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
  595. package/src/renderers/electrobun/view/ui-host.tsx +2 -5
  596. package/src/renderers/opentui/host.tsx +5 -0
  597. package/src/renderers/opentui/ui-host.tsx +7 -1
  598. package/src/sources/gloomberb-cloud/index.ts +25 -4
  599. package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
  600. package/src/sources/provider-router/batches.ts +3 -3
  601. package/src/sources/provider-router/cached-routes.ts +4 -1
  602. package/src/sources/provider-router/financial-routes.ts +2 -2
  603. package/src/sources/provider-router/financials.ts +76 -12
  604. package/src/sources/provider-router/history.ts +15 -10
  605. package/src/sources/provider-router/primary.ts +2 -2
  606. package/src/sources/sec-registrant.ts +75 -0
  607. package/src/state/app/context/index.tsx +24 -8
  608. package/src/state/hooks/quote-streaming.ts +41 -26
  609. package/src/state/pane-scroll-registry.tsx +67 -35
  610. package/src/sync/core-contributors.ts +4 -0
  611. package/src/telemetry/crash-reports.ts +4 -1
  612. package/src/test-support/cli-context.ts +10 -2
  613. package/src/test-support/margin-account.ts +108 -0
  614. package/src/theme/heat-colors.ts +266 -84
  615. package/src/time-series/resolution.ts +15 -0
  616. package/src/time-series/resolve.ts +1 -1
  617. package/src/time-series/use-chart-resolution.ts +1 -1
  618. package/src/types/context-menu.ts +6 -0
  619. package/src/types/data-provider.ts +2 -0
  620. package/src/types/financials.ts +35 -3
  621. package/src/types/headless.ts +79 -2
  622. package/src/types/plugin.ts +20 -1
  623. package/src/types/ticker.ts +15 -0
  624. package/src/ui/host.tsx +26 -0
  625. package/src/ui/index.tsx +8 -3
  626. package/src/ui/scroll-box-axis.ts +26 -0
  627. package/src/updater/index.ts +9 -11
  628. package/src/utils/async-deadline.ts +21 -0
  629. package/src/utils/cli-output.ts +5 -1
  630. package/src/utils/crypto-pair.ts +41 -0
  631. package/src/utils/currency-units.ts +19 -0
  632. package/src/utils/depositary-receipt.ts +70 -0
  633. package/src/utils/display-number.ts +63 -0
  634. package/src/utils/exchanges.ts +72 -0
  635. package/src/utils/fire-and-forget.ts +24 -0
  636. package/src/utils/format.ts +13 -0
  637. package/src/utils/fundamentals.ts +17 -1
  638. package/src/utils/price-earnings.ts +70 -3
  639. package/src/utils/price-history-integrity.ts +19 -6
  640. package/src/utils/price-history.ts +58 -13
  641. package/src/utils/rpc-timeout-error.ts +27 -0
  642. package/src/utils/sec.ts +13 -1
  643. package/src/utils/utc-time.ts +79 -0
@@ -71,7 +71,12 @@ export interface HeadlessPaneContext {
71
71
  settings?: Record<string, unknown>;
72
72
  capabilities?: CapabilityInvoker;
73
73
  /** Read one local portfolio without passing holdings through a remote endpoint. */
74
- resolvePortfolio?: (id: string) => Promise<{ portfolio: import("./ticker").Portfolio; tickers: import("./ticker").TickerRecord[] } | null>;
74
+ resolvePortfolio?: (id: string) => Promise<{
75
+ portfolio: import("./ticker").Portfolio;
76
+ tickers: import("./ticker").TickerRecord[];
77
+ /** The broker account the portfolio was last synced with, as saved on this device. */
78
+ account?: import("./trading").BrokerAccount | null;
79
+ } | null>;
75
80
  /** Read locally remembered watchlist membership. */
76
81
  resolveWatchlist?: (id: string) => Promise<import("./ticker").TickerRecord[] | null>;
77
82
  /** Resolve locally remembered exchange identities without coupling plugins to storage. */
@@ -97,6 +102,63 @@ export interface HeadlessPaneEntry {
97
102
  formatted?: string;
98
103
  }
99
104
 
105
+ /**
106
+ * How current a report's data is (docs/usage.md#how-current-a-report-is):
107
+ * - `live`: a real-time feed, such as a streaming venue or a real-time quote.
108
+ * - `delayed`: a feed held back on purpose, by `delayMinutes` when known.
109
+ * - `stale`: a feed or scheduled release whose newest observation is older
110
+ * than that kind of data allows.
111
+ * - `not-a-feed`: data that is not a feed at all (filings, fundamentals,
112
+ * calendars, statistics releases, calculators, local portfolio data). It
113
+ * never reads stale just because it is old.
114
+ */
115
+ export type HeadlessFreshnessStatus = "live" | "delayed" | "stale" | "not-a-feed";
116
+
117
+ /**
118
+ * What a report can cite about its data. Every field is optional: the report
119
+ * fills what is missing from the result itself (quote `dataSource`,
120
+ * `delayMinutes`, `stale`, `asOf`/`observedAt`/`lastUpdated` fields, the last
121
+ * point of each series), so a pane declares only what that would get wrong.
122
+ */
123
+ export interface HeadlessPaneFreshness {
124
+ /**
125
+ * Who a reader would cite: the venue, exchange or agency for primary data
126
+ * ("SEC EDGAR", "Hyperliquid"), "Gloom Cloud" for aggregated market data,
127
+ * "Local data" or "Your inputs". Never a data vendor or an internal provider id.
128
+ */
129
+ source?: string;
130
+ /** Newest observation in the data. A `YYYY-MM-DD` string reads as a date without a time. */
131
+ asOf?: string | number | Date | null;
132
+ /** Oldest observation, mentioned when it is far older than `asOf`; `null` when the rows are a history. */
133
+ oldest?: string | number | Date | null;
134
+ /**
135
+ * The row field that says when each row was observed, when it is not one of
136
+ * the standard names (`asOf`, `observedAt`, `lastUpdated`...). The report is
137
+ * then dated by that field alone, not by metadata stamps.
138
+ */
139
+ observedKey?: string;
140
+ status?: HeadlessFreshnessStatus;
141
+ /** How far a delayed feed is held back, in minutes. */
142
+ delayMinutes?: number;
143
+ /** What not-a-feed data is, in a few words: "filed data", "monthly release", "your inputs". */
144
+ basis?: string;
145
+ /** The newest observation is stale once it is older than this many minutes. */
146
+ maxAgeMinutes?: number;
147
+ /**
148
+ * The rows' and metadata's own `stale` flags mean something other than "this
149
+ * value is out of date" (a historical marker, a cache state), so the report
150
+ * judges staleness from the schedule alone.
151
+ */
152
+ ignoreStaleFlags?: boolean;
153
+ /**
154
+ * `daily`: one observation per US trading day, stale once more than one
155
+ * completed session has passed after the newest (a day's lag is allowed).
156
+ */
157
+ cadence?: "daily";
158
+ /** The newest observation is stale once this time (the next scheduled release) has passed by a day. */
159
+ nextExpectedAt?: string | number | Date | null;
160
+ }
161
+
100
162
  interface HeadlessPaneResultBase {
101
163
  /** False when usable output does not fully cover the requested inputs/depth. */
102
164
  complete?: boolean;
@@ -104,8 +166,17 @@ interface HeadlessPaneResultBase {
104
166
  symbols?: string[];
105
167
  /** Missing inputs must remain visible even when other inputs returned rows. */
106
168
  unavailableSymbols?: string[];
169
+ /** Failures: a source that did not answer, or a value that could not be computed. */
107
170
  errors?: string[];
171
+ /**
172
+ * Caveats about a report that did load: what it leaves out, what it assumes,
173
+ * how a value was marked. One sentence each. They never make a report fail;
174
+ * `complete: false` says when the report does not cover what was asked.
175
+ */
176
+ notes?: string[];
108
177
  metadata?: Record<string, unknown>;
178
+ /** What this load knows about its data's source and age; overrides the definition's `freshness`. */
179
+ freshness?: HeadlessPaneFreshness;
109
180
  }
110
181
 
111
182
  export interface HeadlessRowsResult extends HeadlessPaneResultBase {
@@ -185,8 +256,14 @@ export interface HeadlessPaneDefinition<Shape extends HeadlessPaneShape = Headle
185
256
  description?: string;
186
257
  argument: HeadlessPaneArgumentDef;
187
258
  options: HeadlessPaneOptionDef[];
259
+ /** What is true of every load: its source, and whether it is a feed. */
260
+ freshness?: HeadlessPaneFreshness;
188
261
  columns?: HeadlessPaneColumn[];
189
- describe?: string | ((args: HeadlessPaneLoadArgs) => string);
262
+ /**
263
+ * The report title. A report passes the loaded result, so a title can name
264
+ * what the load resolved (the view an `auto` query became, a fund's name).
265
+ */
266
+ describe?: string | ((args: HeadlessPaneLoadArgs, result?: HeadlessPaneResult) => string);
190
267
  load(
191
268
  args: HeadlessPaneLoadArgs,
192
269
  ctx: HeadlessPaneContext,
@@ -1,10 +1,11 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { AppTickerRepositoryPort } from "../core/app-service-ports";
3
- import type { HeadlessPaneDefinition } from "./headless";
3
+ import type { HeadlessPaneDefinition, HeadlessPaneFreshness } from "./headless";
4
4
 
5
5
  export type {
6
6
  HeadlessBundleResult,
7
7
  HeadlessBundleSection,
8
+ HeadlessFreshnessStatus,
8
9
  HeadlessPaneApiClient,
9
10
  HeadlessPaneArgumentDef,
10
11
  HeadlessPaneArgumentKind,
@@ -12,6 +13,7 @@ export type {
12
13
  HeadlessPaneContext,
13
14
  HeadlessPaneDefinition,
14
15
  HeadlessPaneEntry,
16
+ HeadlessPaneFreshness,
15
17
  HeadlessPaneLoadArgs,
16
18
  HeadlessPaneOptionDef,
17
19
  HeadlessPaneOptionType,
@@ -124,6 +126,12 @@ export interface PaneDef {
124
126
  tickerFollower?: boolean | ((pane: PaneInstanceConfig) => boolean);
125
127
  /** Renderer-neutral data model used by CLI functions, automation, and hosted tools. */
126
128
  headless?: HeadlessPaneDefinition;
129
+ /**
130
+ * Source and status a rendered-view report (`fn` on a pane without a
131
+ * `headless` model) cites, when "Gloom Cloud" with the state the footer
132
+ * shows would be wrong: local data, a calculator, filed records.
133
+ */
134
+ reportFreshness?: Pick<HeadlessPaneFreshness, "source" | "status" | "basis">;
127
135
  /** Add an Excel-compatible CSV action for the pane's single active DataTable. */
128
136
  tableExport?: true;
129
137
  settings?: PaneSettingsDef | ((context: PaneSettingsContext) => PaneSettingsDef | null);
@@ -146,6 +154,12 @@ export interface PaneQuickSettingDef {
146
154
  * it off picks the field's other option.
147
155
  */
148
156
  onValue?: string;
157
+ /**
158
+ * Shows the control only where it changes something, for a setting that
159
+ * applies to some of what the pane can show. The field stays in the
160
+ * settings dialog either way.
161
+ */
162
+ visible?: (context: PaneSettingsContext) => boolean;
149
163
  }
150
164
 
151
165
  export interface PaneSettingsContext {
@@ -264,6 +278,11 @@ interface PaneTemplateShortcut {
264
278
  aliases?: readonly string[];
265
279
  argPlaceholder?: string;
266
280
  argKind?: "text" | "ticker" | "ticker-list";
281
+ /**
282
+ * For a ticker list, entries kept as typed instead of resolved as tickers:
283
+ * CORR keeps map series (`GEO:HORMUZ`) beside its tickers.
284
+ */
285
+ keepArgToken?: (token: string) => boolean;
267
286
  argOptional?: boolean;
268
287
  /**
269
288
  * With no argument typed and none to infer from the active ticker, open
@@ -56,6 +56,21 @@ export interface Portfolio {
56
56
  lastSyncedAt?: number;
57
57
  /** Set on paper portfolios shared with a team; the server holds the items. */
58
58
  teamId?: string;
59
+ /**
60
+ * Cash held beside the positions, entered by hand. A broker account that
61
+ * reports its own cash is shown instead of this.
62
+ */
63
+ cash?: PortfolioCash;
64
+ /**
65
+ * Target weights in percent of the total value, cash included, keyed by
66
+ * ticker symbol; `CASH` is the cash line.
67
+ */
68
+ targetWeights?: Record<string, number>;
69
+ }
70
+
71
+ export interface PortfolioCash {
72
+ amount: number;
73
+ currency: string;
59
74
  }
60
75
 
61
76
  export interface Watchlist {
package/src/ui/host.tsx CHANGED
@@ -108,6 +108,12 @@ export interface SyntaxStyleLike {
108
108
  }): number;
109
109
  }
110
110
 
111
+ /** Where a drag has a box this frame: an offset in cells from where it is laid out. */
112
+ export interface LiveBoxFrame {
113
+ dx: number;
114
+ dy: number;
115
+ }
116
+
111
117
  export interface BoxRenderable {
112
118
  x?: number;
113
119
  y?: number;
@@ -117,6 +123,12 @@ export interface BoxRenderable {
117
123
  absoluteY?: number;
118
124
  absoluteBounds?: { x: number; y: number; width: number; height: number };
119
125
  getBoundingClientRect?: () => { x: number; y: number; width: number; height: number };
126
+ /**
127
+ * Desktop only: draws the box at `frame` by restyling its own element, with
128
+ * no render, until it is called with null. The offset rides the compositor,
129
+ * so it costs no layout or repaint.
130
+ */
131
+ setLiveFrame?: (frame: LiveBoxFrame | null) => void;
120
132
  [key: string]: unknown;
121
133
  }
122
134
 
@@ -461,6 +473,20 @@ export interface HostPopoverProps {
461
473
  trigger: ReactNode;
462
474
  children: ReactNode;
463
475
  anchorPoint?: { x: number; y: number } | null;
476
+ /**
477
+ * Opens beside this element instead of the trigger, such as a name the
478
+ * pointer is on: below it with the left edges aligned, above it when there
479
+ * is no room below, and kept inside the boundary. A Box ref is one. Read
480
+ * each time the popover places itself, so it follows the element when the
481
+ * page scrolls.
482
+ */
483
+ anchor?: BoxRenderable | null;
484
+ /** `pane` also keeps the popover inside the pane it opens from. Default `viewport`. */
485
+ boundary?: "viewport" | "pane";
486
+ /** The pointer came onto the popover, e.g. to keep a hover card open while it is used. */
487
+ onPointerEnter?: () => void;
488
+ /** The pointer left the popover. */
489
+ onPointerLeave?: () => void;
464
490
  placement?: "bottom-start" | "bottom-end";
465
491
  minWidth?: number | string;
466
492
  maxWidth?: number | string;
package/src/ui/index.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createElement, forwardRef, useCallback, useRef, type ComponentProps } from "react";
2
2
  import { useForwardedScrollBoxRef, useRegisterPaneScrollBox } from "../state/pane-scroll-registry";
3
3
  import { useUiHost, type UiHost } from "./host";
4
+ import { scrollBoxScrollsVertically } from "./scroll-box-axis";
4
5
  import { useRemoteUiNode } from "../remote/semantic-tree";
5
6
  import { assignRef } from "../react/assign-ref";
6
7
  import {
@@ -48,6 +49,7 @@ export type {
48
49
  MediaSurfaceHandle,
49
50
  MediaSurfaceProps,
50
51
  InputRenderable,
52
+ LiveBoxFrame,
51
53
  NativeCursorState,
52
54
  NativeRendererHost,
53
55
  NativePostProcessFn,
@@ -128,8 +130,11 @@ export const ScrollBox = forwardRef<any, ComponentProps<UiHost["ScrollBox"]>>((p
128
130
  const { ScrollBox: HostScrollBox } = useUiHost();
129
131
  const localRef = useForwardedScrollBoxRef<any>(ref);
130
132
  const rawProps = props as Record<string, unknown>;
133
+ // The same rule the hosts scroll by: a ScrollBox that omits scrollY scrolls,
134
+ // so it is a scrollbox to the remote tree and to the pane scroll keys.
135
+ const scrollsVertically = scrollBoxScrollsVertically(props);
131
136
  const remoteNodeId = useRemoteUiNode(
132
- props.scrollY === true
137
+ scrollsVertically
133
138
  ? {
134
139
  role: remotePropRole(rawProps, "scrollbox"),
135
140
  label: remotePropLabel(rawProps),
@@ -150,7 +155,7 @@ export const ScrollBox = forwardRef<any, ComponentProps<UiHost["ScrollBox"]>>((p
150
155
  ...remoteMetadataFromProps(rawProps),
151
156
  width: rawProps.width,
152
157
  height: rawProps.height,
153
- scrollY: props.scrollY === true,
158
+ scrollY: true,
154
159
  scrollTop: localRef.current?.scrollTop,
155
160
  viewportHeight: localRef.current?.viewport?.height,
156
161
  },
@@ -158,7 +163,7 @@ export const ScrollBox = forwardRef<any, ComponentProps<UiHost["ScrollBox"]>>((p
158
163
  : null,
159
164
  );
160
165
  useRegisterPaneScrollBox(localRef, {
161
- enabled: props.scrollY === true,
166
+ enabled: scrollsVertically,
162
167
  onScrollActivity: typeof props.onMouseScroll === "function"
163
168
  ? props.onMouseScroll as (event: { scroll: { direction: "up" | "down"; delta: number } }) => void
164
169
  : undefined,
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Which axes a ScrollBox scrolls on, decided from its props. The terminal and
3
+ * DOM hosts and the pane keyboard scroll registration all read it here, so a
4
+ * ScrollBox that omits `scrollY` behaves the same everywhere: it scrolls
5
+ * vertically, with the wheel and with the arrows, PageUp, PageDown, Home and
6
+ * End. Pass `scrollY={false}` to turn that off.
7
+ */
8
+ interface ScrollBoxAxisProps {
9
+ scrollX?: unknown;
10
+ scrollY?: unknown;
11
+ height?: unknown;
12
+ }
13
+
14
+ /**
15
+ * A one-row strip that only scrolls sideways: tab bars, table headers and
16
+ * chart legends. It is not a vertical scroller even though `scrollY` is
17
+ * omitted.
18
+ */
19
+ export function isHeaderStripScrollBox(props: ScrollBoxAxisProps): boolean {
20
+ return props.scrollX === true && props.scrollY !== true && props.height === 1;
21
+ }
22
+
23
+ /** Whether the ScrollBox scrolls vertically: unless `scrollY` is false, and never a header strip. */
24
+ export function scrollBoxScrollsVertically(props: ScrollBoxAxisProps): boolean {
25
+ return props.scrollY !== false && !isHeaderStripScrollBox(props);
26
+ }
@@ -1,7 +1,7 @@
1
1
  import { compareSemver } from "../utils/semver";
2
2
  import { GITHUB_LATEST_RELEASE_API_URL } from "./github-releases";
3
3
 
4
- function getRuntimeProcess(): Pick<NodeJS.Process, "platform" | "arch" | "argv" | "execPath"> | null {
4
+ function getRuntimeProcess(): Pick<NodeJS.Process, "platform" | "arch" | "argv" | "execPath" | "getBuiltinModule"> | null {
5
5
  return (globalThis as { process?: NodeJS.Process }).process ?? null;
6
6
  }
7
7
 
@@ -414,17 +414,15 @@ export async function performUpdate(
414
414
  let unlinkUpdatePath: ((path: string) => void) | null = null;
415
415
 
416
416
  try {
417
- const fsModulePath = "fs";
418
- const zlibModulePath = "zlib";
419
- const cryptoModulePath = "crypto";
420
- const {
421
- renameSync,
422
- unlinkSync,
423
- chmodSync,
424
- } = await import(fsModulePath) as typeof import("fs");
417
+ // Not import(): Bun folds even a specifier held in a variable and bundles
418
+ // browser polyfills for all three into the web and desktop view builds,
419
+ // which never reach this path. Self-update only runs in the compiled
420
+ // terminal binary, where the process is always there.
421
+ const runtime = getRuntimeProcess()!;
422
+ const { renameSync, unlinkSync, chmodSync } = runtime.getBuiltinModule("fs");
425
423
  unlinkUpdatePath = unlinkSync;
426
- const { gunzipSync } = await import(zlibModulePath) as typeof import("zlib");
427
- const { createHash } = await import(cryptoModulePath) as typeof import("crypto");
424
+ const { gunzipSync } = runtime.getBuiltinModule("zlib");
425
+ const { createHash } = runtime.getBuiltinModule("crypto");
428
426
 
429
427
  onProgress({ phase: "downloading", percent: 0 });
430
428
 
@@ -58,3 +58,24 @@ export function abortable<T>(promise: Promise<T>, signal: AbortSignal | undefine
58
58
  promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
59
59
  });
60
60
  }
61
+
62
+ /**
63
+ * Aborts when the caller's signal does or after `timeoutMs`, whichever comes
64
+ * first, with that signal's reason. Wired by hand because AbortSignal.any is
65
+ * missing from the older system WebViews the desktop app runs in.
66
+ */
67
+ export function signalWithTimeout(signal: AbortSignal | undefined, timeoutMs: number): AbortSignal {
68
+ const timeout = AbortSignal.timeout(timeoutMs);
69
+ if (!signal) return timeout;
70
+ if (signal.aborted) return signal;
71
+ const controller = new AbortController();
72
+ const fromCaller = () => controller.abort(signal.reason);
73
+ const fromTimeout = () => controller.abort(timeout.reason);
74
+ signal.addEventListener("abort", fromCaller, { once: true });
75
+ timeout.addEventListener("abort", fromTimeout, { once: true });
76
+ controller.signal.addEventListener("abort", () => {
77
+ signal.removeEventListener("abort", fromCaller);
78
+ timeout.removeEventListener("abort", fromTimeout);
79
+ }, { once: true });
80
+ return controller.signal;
81
+ }
@@ -8,6 +8,8 @@ export interface CliTableColumn {
8
8
  maxWidth?: number;
9
9
  /** Dropped, rightmost first, before other columns are shortened to fit a terminal. */
10
10
  optional?: boolean;
11
+ /** Among optional columns, a higher priority is dropped sooner; equal ones go rightmost first. */
12
+ dropPriority?: number;
11
13
  /** False keeps the column whole when fitting, for identifiers a user types into the next command. */
12
14
  shrink?: boolean;
13
15
  }
@@ -301,7 +303,9 @@ export function renderTable(columns: CliTableColumn[], rows: string[][], options
301
303
  let truncate = false;
302
304
  if (available != null && tableWidth(shown.map((entry) => entry.width)) > available) {
303
305
  while (tableWidth(shown.map((entry) => entry.width)) > available) {
304
- const dropped = shown.findLast((entry) => entry.column.optional);
306
+ const dropped = shown.reduce<(typeof shown)[number] | undefined>((pick, entry) => (
307
+ entry.column.optional && (!pick || (entry.column.dropPriority ?? 0) >= (pick.column.dropPriority ?? 0)) ? entry : pick
308
+ ), undefined);
305
309
  if (!dropped) break;
306
310
  shown = shown.filter((entry) => entry !== dropped);
307
311
  }
@@ -0,0 +1,41 @@
1
+ import { canonicalExchange, parsePublicTickerKey } from "./exchanges";
2
+
3
+ // The fiat codes a pair against USD is read as FX for, never as a coin. The
4
+ // list Cloud reads: it serves these pairs by the same rule, so a copy judged
5
+ // here as current or stale agrees with the answer it was fetched from.
6
+ const FIAT_CURRENCY_CODES = new Set([
7
+ "USD", "EUR", "JPY", "GBP", "CHF", "CAD", "AUD", "NZD", "CNY", "CNH", "HKD", "SGD", "SEK", "NOK", "DKK",
8
+ "ZAR", "INR", "BRL", "MXN", "KRW", "TWD", "ILS", "PLN", "TRY", "CZK", "HUF",
9
+ ]);
10
+
11
+ const USD_COIN_PAIR = /^([A-Z0-9]+)[-/]USD$/;
12
+
13
+ /** A coin quoted in dollars (BTC-USD, ETH/USD). EUR-USD is spot FX, not a coin. */
14
+ function isUsdCoinPair(symbol: string): boolean {
15
+ const base = USD_COIN_PAIR.exec(symbol.trim().toUpperCase())?.[1];
16
+ return base !== undefined && !FIAT_CURRENCY_CODES.has(base);
17
+ }
18
+
19
+ /**
20
+ * A series that trades around the clock: anything on the crypto venue (CCC), or
21
+ * a coin quoted in dollars whether or not the caller named that venue. A bare
22
+ * BTC-USD is the coin, not a US listing; a bare BTC (no quote) is a US fund.
23
+ */
24
+ export function isRoundTheClockCoin(symbol?: string, exchange?: string): boolean {
25
+ const parsed = symbol ? parsePublicTickerKey(symbol) : null;
26
+ if (canonicalExchange(parsed?.exchange ?? exchange) === "CCC" || canonicalExchange(exchange) === "CCC") return true;
27
+ return !!parsed && isUsdCoinPair(parsed.symbol);
28
+ }
29
+
30
+ // A base-quote pair such as BTC-USD or SOL-EUR. Equities with a share-class dash (BRK-B) and
31
+ // currency pairs (EURUSD=X) do not match.
32
+ const CRYPTO_PAIR = /^[A-Z0-9]{1,15}-(?:USD|EUR|GBP|USDT|USDC|BTC)$/;
33
+
34
+ /**
35
+ * Wider than isUsdCoinPair, for the hint under a pair that will not load: it
36
+ * also takes pairs quoted in other currencies and in coins, and does not tell
37
+ * a fiat base from a coin.
38
+ */
39
+ export function isCryptoPairSymbol(symbol: string): boolean {
40
+ return CRYPTO_PAIR.test(symbol);
41
+ }
@@ -6,6 +6,25 @@ const SUB_UNIT_CURRENCIES: Record<string, { currency: string; divisor: number }>
6
6
  ZAc: { currency: "ZAR", divisor: 100 },
7
7
  };
8
8
 
9
+ const SUB_UNIT_NAMES: Record<string, string> = {
10
+ GBp: "pence",
11
+ GBX: "pence",
12
+ ILA: "agorot",
13
+ ZAc: "cents",
14
+ };
15
+
16
+ /**
17
+ * A currency code as a reader should see it; a sub-unit says which one,
18
+ * "GBp (pence)", and with `ofMajor` what it divides: "ILA (agorot, 1/100 ILS)".
19
+ */
20
+ export function currencyUnitLabel(code?: string | null, { ofMajor = false }: { ofMajor?: boolean } = {}): string {
21
+ const raw = (code ?? "").trim();
22
+ const unit = SUB_UNIT_NAMES[raw];
23
+ const major = SUB_UNIT_CURRENCIES[raw];
24
+ if (!unit) return raw;
25
+ return ofMajor && major ? `${raw} (${unit}, 1/${major.divisor} ${major.currency})` : `${raw} (${unit})`;
26
+ }
27
+
9
28
  const LIKELY_UNIT_MISMATCH_RATIOS: Record<string, number[]> = {
10
29
  BHD: [1000],
11
30
  GBP: [100],
@@ -0,0 +1,70 @@
1
+ import type { Fundamentals, Quote, ShareBasis } from "../types/financials";
2
+
3
+ // A word of its own, so a company called "ADS-TEC" is not one.
4
+ const DEPOSITARY_NAME = /(?:^|\s)(?:ADRs?|ADSs?|American depositary (?:receipts?|shares?))(?=$|[\s,)])/i;
5
+ const DEPOSITARY_TYPES = new Set(["ADR", "ADS", "DEPOSITARYRECEIPT"]);
6
+ /** A profile that opens by naming the security: "Toyota Motor Corporation Sponsored ADR is ...". */
7
+ const DEPOSITARY_SUBJECT = /^.{0,160}?\s(?:ADRs?|ADSs?|American depositary (?:receipts?|shares?)) is\s/i;
8
+
9
+ interface ListingEvidence {
10
+ /** Gloom Cloud's verdict; absent when it has no evidence either way. */
11
+ isDepositaryReceipt?: boolean | null;
12
+ instrumentType?: string | null;
13
+ name?: string | null;
14
+ currency?: string | null;
15
+ description?: string | null;
16
+ }
17
+
18
+ /**
19
+ * Whether a listing is a depositary receipt. Gloom Cloud's flag decides when
20
+ * it is set. Without it (an older service, or a listing it has no evidence
21
+ * for) this reads the instrument type, the name, and the security name a
22
+ * profile description opens with. A listing in another currency is the
23
+ * ordinary line even when its profile mentions the receipts.
24
+ */
25
+ export function isDepositaryReceipt(input: ListingEvidence): boolean {
26
+ if (typeof input.isDepositaryReceipt === "boolean") return input.isDepositaryReceipt;
27
+ const currency = input.currency?.trim().toUpperCase();
28
+ if (currency && currency !== "USD") return false;
29
+ if (DEPOSITARY_TYPES.has((input.instrumentType ?? "").replace(/[\s_-]/g, "").toUpperCase())) return true;
30
+ if (input.name && DEPOSITARY_NAME.test(input.name)) return true;
31
+ return DEPOSITARY_SUBJECT.test(input.description?.trim() ?? "");
32
+ }
33
+
34
+ /**
35
+ * Whether a record's share counts are in receipts. Gloom Cloud says so with
36
+ * `shareBasis`; without it, a receipt's counts are read as receipts, as its
37
+ * market cap is.
38
+ */
39
+ function sharesInReceipts(input: ListingEvidence & { shareBasis?: ShareBasis | null }): boolean {
40
+ if (input.shareBasis === "depositary_receipt") return true;
41
+ if (input.shareBasis === "ordinary") return false;
42
+ return isDepositaryReceipt(input);
43
+ }
44
+
45
+ /**
46
+ * Whether a listing's shares outstanding are counted in receipts: the
47
+ * fundamentals' basis, else the listing's flag (the fundamentals' or the
48
+ * quote's), else what the quote and profile say.
49
+ */
50
+ export function sharesOutstandingInReceipts(
51
+ quote: Pick<Quote, "isDepositaryReceipt" | "instrumentType" | "name" | "currency"> | null | undefined,
52
+ fundamentals: Pick<Fundamentals, "isDepositaryReceipt" | "shareBasis"> | null | undefined,
53
+ description?: string | null,
54
+ ): boolean {
55
+ return sharesInReceipts({
56
+ instrumentType: quote?.instrumentType,
57
+ name: quote?.name,
58
+ currency: quote?.currency,
59
+ description,
60
+ isDepositaryReceipt: fundamentals?.isDepositaryReceipt ?? quote?.isDepositaryReceipt,
61
+ shareBasis: fundamentals?.shareBasis,
62
+ });
63
+ }
64
+
65
+ /** "1 ADR = 2 ordinary shares", or null without a usable ratio. */
66
+ export function adrRatioText(ratio: number | null | undefined): string | null {
67
+ if (typeof ratio !== "number" || !Number.isFinite(ratio) || ratio <= 0) return null;
68
+ const count = Number.isInteger(ratio) ? String(ratio) : String(Number(ratio.toPrecision(6)));
69
+ return `1 ADR = ${count} ordinary share${ratio === 1 ? "" : "s"}`;
70
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Reading back a number a table or report drew ("+1.25%", "1.20B", "$1,234.50"),
3
+ * so a CSV export can write the number a spreadsheet uses and name the unit
4
+ * in its header instead of in every cell.
5
+ */
6
+
7
+ /** What a cell draws for a missing value: a dash, a run of dashes, or the loading ellipsis. */
8
+ export const DISPLAY_PLACEHOLDER = /^(?:[-\u2013\u2014]{1,3}|\u2026|\.\.\.)$/;
9
+
10
+ /**
11
+ * A number as a table draws it: sign, currency symbol, thousands commas,
12
+ * decimals, a compact scale (12.3k, 1.20B) and a unit (%, x, bp, USD, or c
13
+ * for the cents grain futures quote in).
14
+ */
15
+ const DISPLAY_NUMBER = /^([+-]?)([A-Z]{0,3}[$\u20ac\u00a3\u00a5\u20b9\u20a9\u20bd\u20ba\u20aa\u20ab\u0e3f])?(?=\.?\d)(\d{1,3}(?:,\d{3})+|\d*)(?:\.(\d+))?([kKMBT])?(%|x|c|\u00a2| ?bps?| [A-Z]{3})?$/;
16
+
17
+ const SCALE_DIGITS: Record<string, number> = { k: 3, K: 3, M: 6, B: 9, T: 12 };
18
+
19
+ export interface DisplayNumber {
20
+ /** Plain decimal text: no sign for positives, no commas, no scale letter. */
21
+ number: string;
22
+ /** What the column header has to name once the cells are bare numbers. */
23
+ unit: string;
24
+ /** The place value of the last digit drawn: 0.01 for "1.25%", 10,000,000 for "1.20B". */
25
+ step: number;
26
+ }
27
+
28
+ export const BLANK_DISPLAY = "blank";
29
+
30
+ /** Moves the decimal point right without going through a float, so 1.23B is exactly 1230000000. */
31
+ function scaleDecimal(integer: string, fraction: string, digits: number): string {
32
+ const whole = `${integer}${fraction.padEnd(digits, "0").slice(0, digits)}`.replace(/^0+(?=\d)/, "") || "0";
33
+ const rest = fraction.slice(digits);
34
+ return rest ? `${whole}.${rest}` : whole;
35
+ }
36
+
37
+ export function parseDisplayNumber(text: string): DisplayNumber | typeof BLANK_DISPLAY | null {
38
+ // A direction arrow beside a signed move repeats the sign.
39
+ const trimmed = text.trim().replace(/\u2212/g, "-").replace(/\s*[\u2191\u2193]$/, "");
40
+ if (!trimmed || DISPLAY_PLACEHOLDER.test(trimmed)) return BLANK_DISPLAY;
41
+ const match = DISPLAY_NUMBER.exec(trimmed);
42
+ if (!match) return null;
43
+ const [, sign, currency = "", grouped, fraction = "", scale, unitText = ""] = match;
44
+ const integer = grouped!.replace(/,/g, "") || "0";
45
+ const digits = scale ? SCALE_DIGITS[scale]! : 0;
46
+ const magnitude = digits ? scaleDecimal(integer, fraction, digits) : fraction ? `${integer}.${fraction}` : integer;
47
+ const unit = unitText.trim().replace(/^bps$/, "bp").replace(/^\u00a2$/, "c");
48
+ return {
49
+ number: `${sign === "-" ? "-" : ""}${magnitude}`,
50
+ unit: [currency, unit].filter(Boolean).join(" "),
51
+ step: 10 ** (digits - fraction.length),
52
+ };
53
+ }
54
+
55
+ /** Adds the unit the cells dropped, unless the label already names it. */
56
+ export function labelWithUnit(label: string, unit: string): string {
57
+ if (!unit) return label;
58
+ // A word unit has to stand alone: "Max" does not name x.
59
+ const named = unit === "bp" ? /\bbps?\b/i.test(label)
60
+ : /^[A-Za-z]+$/.test(unit) ? new RegExp(`\\b${unit}\\b`, "i").test(label)
61
+ : label.includes(unit);
62
+ return named ? label : `${label} (${unit})`;
63
+ }