gloomberb 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +44 -11
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +5 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/members.ts +26 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +41 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +9 -1
- package/src/app/global-shortcuts.ts +14 -6
- package/src/app/keybindings/actions.ts +1 -1
- package/src/app/runtime/update.ts +38 -2
- package/src/app.tsx +10 -6
- package/src/brokers/account-cache.ts +24 -0
- package/src/cli/commands/command-utils.ts +8 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +414 -106
- package/src/cli/commands/overview.ts +77 -32
- package/src/cli/commands/ticker.ts +101 -43
- package/src/cli/desktop-pane-shot.ts +34 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +1 -0
- package/src/cli/helpers.ts +4 -8
- package/src/cli/index.ts +12 -2
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +20 -2
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +36 -22
- package/src/cli/pane-functions/headless.ts +39 -11
- package/src/cli/pane-functions/index.ts +15 -4
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +35 -7
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +7 -3
- package/src/cli/result.ts +41 -27
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/commands/collection.ts +5 -1
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/root/command-items.ts +9 -2
- package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
- package/src/components/command-bar/routes/root/provider-search.ts +19 -5
- package/src/components/command-bar/routes/root/runtime.ts +14 -5
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
- package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
- package/src/components/command-bar/routing/actions.ts +2 -0
- package/src/components/command-bar/selection-runtime.ts +38 -0
- package/src/components/command-bar/surface/index.tsx +7 -2
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/view.tsx +29 -10
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/index.ts +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/floating-pane.tsx +6 -0
- package/src/components/layout/header.tsx +24 -7
- package/src/components/layout/missing-pane.tsx +2 -2
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +61 -28
- package/src/components/layout/pane/index.tsx +6 -0
- package/src/components/layout/pane/title.ts +31 -7
- package/src/components/layout/shell/drag/index.ts +6 -5
- package/src/components/layout/shell/drag/runtime.ts +3 -0
- package/src/components/layout/shell/index.tsx +6 -0
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +29 -10
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
- package/src/components/layout/shell/ticker-link-menu.ts +23 -9
- package/src/components/metric-treemap/heat-surface.tsx +745 -0
- package/src/components/metric-treemap/heat-tiles.ts +228 -0
- package/src/components/metric-treemap/index.tsx +2 -0
- package/src/components/metric-treemap/layout.ts +8 -0
- package/src/components/metric-treemap/scene.ts +432 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/toggle-list.tsx +38 -12
- package/src/components/ui/country-flag-art.tsx +449 -0
- package/src/components/ui/country-flag.tsx +41 -0
- package/src/components/ui/data-table/types.ts +13 -0
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/icon.tsx +2 -0
- package/src/components/ui/index.ts +4 -0
- package/src/components/ui/multi-select/dialog.tsx +108 -22
- package/src/components/ui/range-track.tsx +53 -0
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +11 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/core/state/app/types.ts +10 -1
- package/src/data/config/store/normalize.ts +17 -1
- package/src/i18n/es.ts +24 -4
- package/src/i18n/ja.ts +24 -4
- package/src/i18n/ko.ts +24 -4
- package/src/i18n/zh-cn.ts +24 -4
- package/src/i18n/zh-tw.ts +24 -4
- package/src/layout/ticker-navigation.ts +28 -2
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +78 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +8 -0
- package/src/market-data/quotes/freshness.ts +36 -0
- package/src/market-data/quotes/resolution.ts +24 -8
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/market-data/quotes/time.ts +16 -0
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/risk-client.ts +330 -79
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
- package/src/plugins/builtin/analytics/risk-math.ts +33 -13
- package/src/plugins/builtin/analytics/risk-model.ts +282 -64
- package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
- package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +1 -1
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/cells.tsx +15 -12
- package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
- package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
- package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
- package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
- package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/catalysts/index.tsx +2 -2
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/cds/index.tsx +1 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +1 -1
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
- package/src/plugins/builtin/dividend-yield/client.ts +4 -2
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/client.ts +2 -2
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
- package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
- package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
- package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/headless.ts +139 -5
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +20 -3
- package/src/plugins/builtin/holders/report-header.ts +95 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +30 -2
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
- package/src/plugins/builtin/market-heatmap/live.ts +88 -0
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
- package/src/plugins/builtin/market-movers/client.ts +3 -2
- package/src/plugins/builtin/market-movers/headless.ts +10 -1
- package/src/plugins/builtin/market-movers/screener.ts +18 -5
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +53 -0
- package/src/plugins/builtin/members/headless.ts +35 -0
- package/src/plugins/builtin/members/index.tsx +20 -0
- package/src/plugins/builtin/members/model.ts +68 -0
- package/src/plugins/builtin/members/pane.tsx +175 -0
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/mna/index.tsx +2 -1
- package/src/plugins/builtin/mna/pane.tsx +5 -2
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +2 -1
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +74 -2
- package/src/plugins/builtin/pe-band/headless.ts +26 -8
- package/src/plugins/builtin/pe-band/model.ts +102 -22
- package/src/plugins/builtin/pe-band/pane.tsx +34 -16
- package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
- package/src/plugins/builtin/perps/client.ts +66 -5
- package/src/plugins/builtin/perps/equity-identity.ts +16 -0
- package/src/plugins/builtin/perps/equity-row.tsx +6 -4
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +248 -47
- package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
- package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
- package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
- package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/index.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/index.tsx +2 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
- package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +67 -4
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
- package/src/plugins/builtin/world-venue-map/model.ts +7 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/catalog-browser.ts +2 -0
- package/src/plugins/catalog-manifest.ts +1 -0
- package/src/plugins/catalog-ui.ts +3 -1
- package/src/plugins/catalog.ts +1 -1
- package/src/plugins/host-link.ts +33 -1
- package/src/plugins/installer.ts +48 -12
- package/src/plugins/loader.ts +30 -3
- package/src/plugins/manager-node.ts +15 -5
- package/src/plugins/registry/index.ts +1 -1
- package/src/plugins/registry/pane-settings.ts +26 -7
- package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/row.tsx +52 -16
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/icons.tsx +1 -0
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +69 -26
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/tabs.tsx +37 -1
- package/src/renderers/dom/styles.css +41 -7
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
- package/src/renderers/electrobun/bun/index.ts +73 -6
- package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
- package/src/renderers/electrobun/shared/protocol.ts +3 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
- package/src/renderers/electrobun/view/main.tsx +7 -1
- package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/update-host.ts +45 -21
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financials.ts +11 -8
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/benign-window-error.ts +7 -0
- package/src/telemetry/crash-reports-dom.ts +2 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/daily-nav.ts +25 -0
- package/src/theme/heat-colors.ts +357 -2
- package/src/tickers/instrument-kind.ts +34 -7
- package/src/tickers/search/asset-classes.ts +24 -9
- package/src/tickers/search/index.ts +44 -11
- package/src/tickers/search/ranking.ts +23 -3
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +5 -0
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +38 -6
- package/src/types/ticker.ts +15 -0
- package/src/ui/context-menu.tsx +1 -0
- package/src/ui/host.tsx +16 -0
- package/src/updater/index.ts +38 -13
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +14 -0
- package/src/utils/depositary-receipt.ts +26 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Box, useUiCapabilities } from "../../../ui";
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
buildHeatTreemapScene,
|
|
5
5
|
findMetricTreemapNeighbor,
|
|
6
|
+
formatHeatTileMove,
|
|
7
|
+
heatTreemapCanvas,
|
|
8
|
+
HeatTreemapSurface,
|
|
9
|
+
settleTreemapLayoutItems,
|
|
10
|
+
} from "../../../components/metric-treemap";
|
|
11
|
+
import {
|
|
6
12
|
loadingText,
|
|
7
|
-
MetricTreemapSurface,
|
|
8
13
|
PaneStatusBody,
|
|
9
14
|
Tabs,
|
|
10
15
|
unavailableText,
|
|
@@ -20,11 +25,11 @@ import { useShortcut } from "../../../react/input";
|
|
|
20
25
|
import { TICKER_RESEARCH_PANE_ID } from "../../../types/config";
|
|
21
26
|
import type { GloomPlugin, PaneProps, PaneSettingField } from "../../../types/plugin";
|
|
22
27
|
import type { TickerRecord } from "../../../types/ticker";
|
|
23
|
-
import { tf } from "../../../i18n";
|
|
28
|
+
import { t, tf } from "../../../i18n";
|
|
24
29
|
import { priceColor } from "../../../theme/colors";
|
|
25
|
-
import { formatCompact, formatCurrency, formatPercentRaw } from "../../../utils/format";
|
|
30
|
+
import { clipToDisplayWidth, formatCompact, formatCurrency, formatPercentRaw } from "../../../utils/format";
|
|
26
31
|
import { isPlainKey } from "../../../utils/keyboard";
|
|
27
|
-
import { useAppSelector, usePaneAppConfig, usePaneSettingValue } from "../../../state/app/context";
|
|
32
|
+
import { useAppSelector, usePaneAppConfig, usePaneSettingValue, usePaneStateValue } from "../../../state/app/context";
|
|
28
33
|
import { usePluginTickerActions } from "../../runtime";
|
|
29
34
|
import { useLiveQuoteEntries } from "../../../state/hooks/quote-streaming";
|
|
30
35
|
import { useFxRatesMap, useTickerFinancialsMap } from "../../../market-data/hooks";
|
|
@@ -39,21 +44,27 @@ import { resolvePortfolioTotalsCurrency } from "../portfolio-list/metrics";
|
|
|
39
44
|
import { useThrottledMemo } from "../portfolio-list/use-throttled-memo";
|
|
40
45
|
import { PORTFOLIO_REORDER_THROTTLE_MS } from "../portfolio-list/use-throttled-ticker-order";
|
|
41
46
|
import {
|
|
47
|
+
MARKET_HEATMAP_REQUEST_COUNT,
|
|
42
48
|
MARKET_HEATMAP_UNIVERSES,
|
|
43
49
|
fetchMarketHeatmap,
|
|
44
50
|
resetMarketHeatmapCache,
|
|
45
51
|
type MarketHeatmapUniverseId,
|
|
46
52
|
} from "./data";
|
|
47
53
|
import {
|
|
54
|
+
HEATMAP_COLLECTION_KIND_STATE_KEY,
|
|
48
55
|
PORTFOLIO_HEATMAP_TAB,
|
|
49
56
|
buildPortfolioHeatmapAssets,
|
|
50
57
|
fallbackHeatmapCollectionId,
|
|
51
58
|
heatmapCollectionLabel,
|
|
52
59
|
heatmapFollowsCollection,
|
|
60
|
+
heatmapSizeBy,
|
|
61
|
+
heatmapSizeByApplies,
|
|
62
|
+
heatmapSizeWeight,
|
|
53
63
|
heatmapTabId,
|
|
54
64
|
isRemoteHeatmapUniverse,
|
|
55
65
|
useLinkedHeatmapCollection,
|
|
56
66
|
type HeatmapBoardAsset,
|
|
67
|
+
type HeatmapSizeBy,
|
|
57
68
|
} from "./portfolio";
|
|
58
69
|
import { useAutoRefresh, useUpdatedAgo } from "../../../react/auto-refresh";
|
|
59
70
|
import {
|
|
@@ -61,13 +72,31 @@ import {
|
|
|
61
72
|
useLiveStreamingSetting,
|
|
62
73
|
withLiveStreamingSetting,
|
|
63
74
|
} from "../../../state/hooks/live-streaming";
|
|
75
|
+
import type { QuoteSubscriptionTarget } from "../../../types/data-provider";
|
|
76
|
+
import {
|
|
77
|
+
buildHeatmapQuoteTargets,
|
|
78
|
+
liveHeatmapWeight,
|
|
79
|
+
rankHeatmapQuoteWeights,
|
|
80
|
+
useSettledValue,
|
|
81
|
+
} from "./live";
|
|
82
|
+
import { marketHeatmapHeadless } from "./headless";
|
|
83
|
+
import { heatmapMove, resolveHeatmapGrouping, sizeWeightedMove, type HeatmapGrouping } from "./model";
|
|
64
84
|
import {
|
|
65
|
-
buildScreenerQuoteTargets,
|
|
66
85
|
overlayScreenerQuoteEntries,
|
|
67
86
|
resolveScreenerQuoteFeedStatus,
|
|
68
87
|
} from "../../../market-data/quotes/screener-live-quotes";
|
|
69
88
|
|
|
70
89
|
const NO_ASSETS: HeatmapBoardAsset[] = [];
|
|
90
|
+
const NO_TARGETS: QuoteSubscriptionTarget[] = [];
|
|
91
|
+
const SNAPSHOT_REFRESH_MS = 60_000;
|
|
92
|
+
const LAYOUT_THROTTLE_MS = 5_000;
|
|
93
|
+
/** A size change below this share of a tile's area is not worth moving it. */
|
|
94
|
+
const LAYOUT_TOLERANCE = 0.005;
|
|
95
|
+
const TERMINAL_PAINT_THROTTLE_MS = 250;
|
|
96
|
+
const SELECTION_STREAM_SETTLE_MS = 1_500;
|
|
97
|
+
const TOOLTIP_NAME_WIDTH = 28;
|
|
98
|
+
const SIZE_BY_SETTING_KEY = "sizeBy";
|
|
99
|
+
const SQRT_SIZE_VALUE: HeatmapSizeBy = "sqrt-market-cap";
|
|
71
100
|
const NO_BOARD = { assets: NO_ASSETS, omitted: 0 };
|
|
72
101
|
const EMPTY_TICKERS: TickerRecord[] = [];
|
|
73
102
|
const NO_CURRENCIES: string[] = [];
|
|
@@ -102,46 +131,97 @@ function sizeLabel(asset: HeatmapBoardAsset): string | null {
|
|
|
102
131
|
return `${label} ${formatMoneyCompact(asset.size, asset.sizeCurrency ?? asset.currency)}`;
|
|
103
132
|
}
|
|
104
133
|
|
|
105
|
-
|
|
106
|
-
|
|
134
|
+
/** Marks a pre-market or after-hours move, which is measured from the regular close. */
|
|
135
|
+
function sessionMark(asset: HeatmapBoardAsset): string | null {
|
|
136
|
+
if (asset.extendedSession === "PRE") return "PM";
|
|
137
|
+
if (asset.extendedSession === "POST") return "AH";
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function formatMove(asset: HeatmapBoardAsset, change: number | null): string {
|
|
142
|
+
const mark = sessionMark(asset);
|
|
143
|
+
return change == null ? "—" : mark ? `${formatPercentRaw(change)} ${mark}` : formatPercentRaw(change);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The size transform applies to each name before groups sum them, so a
|
|
148
|
+
* sector's block is the sum of its transformed names. A board that already
|
|
149
|
+
* carries a weight (a portfolio or watchlist) applied it when it was built.
|
|
150
|
+
*/
|
|
151
|
+
function buildLayoutItems(
|
|
152
|
+
snapshot: readonly HeatmapBoardAsset[],
|
|
153
|
+
live: readonly HeatmapBoardAsset[],
|
|
154
|
+
grouping: HeatmapGrouping,
|
|
155
|
+
sizeBy: HeatmapSizeBy,
|
|
156
|
+
): Array<MetricTreemapItem<HeatmapBoardAsset>> {
|
|
157
|
+
return snapshot.map((asset, index) => ({
|
|
107
158
|
id: asset.symbol,
|
|
108
159
|
label: asset.symbol,
|
|
109
|
-
weight: asset.weight
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
tertiaryText: asset.volume != null ? `Vol ${formatCompact(asset.volume)}` : asset.exchange || null,
|
|
160
|
+
weight: asset.weight != null
|
|
161
|
+
? liveHeatmapWeight(asset, live[index] ?? asset)
|
|
162
|
+
: heatmapSizeWeight(liveHeatmapWeight(asset, live[index] ?? asset), sizeBy),
|
|
163
|
+
group: grouping === "flat" ? undefined : asset.sector ?? null,
|
|
164
|
+
subgroup: grouping === "sector-industry" ? asset.industry ?? null : undefined,
|
|
115
165
|
data: asset,
|
|
116
166
|
}));
|
|
117
167
|
}
|
|
118
168
|
|
|
119
169
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* geometry.
|
|
170
|
+
* The overlay hands back the same asset object while its quote is unchanged,
|
|
171
|
+
* so a tile's text is formatted once per tick of that name, not once per
|
|
172
|
+
* frame for all 500.
|
|
124
173
|
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
174
|
+
const paintItemCache = new WeakMap<HeatmapBoardAsset, MetricTreemapItem<HeatmapBoardAsset>>();
|
|
175
|
+
|
|
176
|
+
function paintItem(asset: HeatmapBoardAsset): MetricTreemapItem<HeatmapBoardAsset> {
|
|
177
|
+
const cached = paintItemCache.get(asset);
|
|
178
|
+
if (cached) return cached;
|
|
179
|
+
const change = heatmapMove(asset);
|
|
180
|
+
const details = [
|
|
181
|
+
asset.price > 0 ? formatCurrency(asset.price, asset.currency) : null,
|
|
182
|
+
sizeLabel(asset),
|
|
183
|
+
asset.volume != null ? `Vol ${formatCompact(asset.volume)}` : null,
|
|
184
|
+
].filter((part): part is string => !!part);
|
|
185
|
+
// The move closes the line, so a long name gives way instead of hiding it.
|
|
186
|
+
const name = asset.name && asset.name !== asset.symbol ? clipToDisplayWidth(asset.name, TOOLTIP_NAME_WIDTH) : null;
|
|
187
|
+
const item: MetricTreemapItem<HeatmapBoardAsset> = {
|
|
188
|
+
id: asset.symbol,
|
|
189
|
+
label: asset.symbol,
|
|
190
|
+
weight: asset.weight ?? asset.size ?? 0,
|
|
191
|
+
colorValue: change,
|
|
192
|
+
primaryText: formatHeatTileMove(change),
|
|
193
|
+
primaryTextSuffix: sessionMark(asset),
|
|
194
|
+
tooltip: [
|
|
195
|
+
[asset.symbol, name, formatMove(asset, change)].filter(Boolean).join(" · "),
|
|
196
|
+
...(details.length > 0 ? [details.join(" · ")] : []),
|
|
197
|
+
],
|
|
198
|
+
data: asset,
|
|
199
|
+
};
|
|
200
|
+
paintItemCache.set(asset, item);
|
|
201
|
+
return item;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function buildPaintItems(assets: readonly HeatmapBoardAsset[]): Array<MetricTreemapItem<HeatmapBoardAsset>> {
|
|
205
|
+
return assets.map(paintItem);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function otherSummary(items: readonly MetricTreemapItem<HeatmapBoardAsset>[]): string {
|
|
209
|
+
return tf("{count} names", { count: items.length });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function otherTooltip(items: readonly MetricTreemapItem<HeatmapBoardAsset>[]): string[] {
|
|
213
|
+
const move = sizeWeightedMove(items.map((item) => item.data));
|
|
214
|
+
return [
|
|
215
|
+
tf("Other · {count} smaller names", { count: items.length }),
|
|
216
|
+
...(move != null ? [`${formatPercentRaw(move)} ${t("cap-weighted")}`] : []),
|
|
217
|
+
];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function useSettledLayoutItems<T>(items: readonly MetricTreemapItem<T>[]): readonly MetricTreemapItem<T>[] {
|
|
221
|
+
const settledRef = useRef<readonly MetricTreemapItem<T>[] | null>(null);
|
|
222
|
+
const settled = settleTreemapLayoutItems(settledRef.current, items, LAYOUT_TOLERANCE);
|
|
223
|
+
settledRef.current = settled;
|
|
224
|
+
return settled;
|
|
145
225
|
}
|
|
146
226
|
|
|
147
227
|
function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
@@ -151,6 +231,8 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
151
231
|
// A pane setting, not private pane state, so the settings dialog can show it.
|
|
152
232
|
const [universeSetting, setActiveUniverse] = usePaneSettingValue<string>("universe", "us-equity");
|
|
153
233
|
const [linkPortfolio] = usePaneSettingValue<boolean>("linkPortfolio", false);
|
|
234
|
+
const [sizeBySetting] = usePaneSettingValue<string>(SIZE_BY_SETTING_KEY, SQRT_SIZE_VALUE);
|
|
235
|
+
const sizeBy = heatmapSizeBy(sizeBySetting);
|
|
154
236
|
const activeUniverse = heatmapTabId(universeSetting);
|
|
155
237
|
const portfolioTab = activeUniverse === PORTFOLIO_HEATMAP_TAB;
|
|
156
238
|
const config = usePaneAppConfig();
|
|
@@ -158,6 +240,7 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
158
240
|
const linkedPortfolio = useLinkedHeatmapCollection();
|
|
159
241
|
const collectionId = linkedPortfolio.collectionId ?? fallbackHeatmapCollectionId(config);
|
|
160
242
|
const collectionKind = getCollectionTypeFromConfig(config, collectionId);
|
|
243
|
+
const [, publishCollectionKind] = usePaneStateValue<string>(HEATMAP_COLLECTION_KIND_STATE_KEY, "");
|
|
161
244
|
const portfolioLabel = heatmapCollectionLabel(config, collectionId);
|
|
162
245
|
const universeTabs = useMemo(() => [
|
|
163
246
|
...MARKET_HEATMAP_UNIVERSES.map((universe) => ({ label: universe.label, value: universe.id })),
|
|
@@ -197,10 +280,11 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
197
280
|
kind: collectionKind,
|
|
198
281
|
currency: boardCurrency,
|
|
199
282
|
exchangeRates,
|
|
283
|
+
sizeBy,
|
|
200
284
|
})
|
|
201
285
|
: NO_BOARD),
|
|
202
286
|
[financials],
|
|
203
|
-
[boardCurrency, collectionId, collectionKind, collectionTickers, exchangeRates, financials.size],
|
|
287
|
+
[boardCurrency, collectionId, collectionKind, collectionTickers, exchangeRates, financials.size, sizeBy],
|
|
204
288
|
PORTFOLIO_REORDER_THROTTLE_MS,
|
|
205
289
|
);
|
|
206
290
|
const portfolioAssets = portfolioBoard.assets;
|
|
@@ -234,11 +318,24 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
234
318
|
});
|
|
235
319
|
|
|
236
320
|
const chartHeight = Math.max(1, height - (tabsInHeader ? 0 : 1));
|
|
237
|
-
const
|
|
238
|
-
|
|
321
|
+
const canvas = useMemo(
|
|
322
|
+
() => heatTreemapCanvas(width, chartHeight, { nativePaneChrome, cellWidthPx, cellHeightPx }),
|
|
323
|
+
[cellHeightPx, cellWidthPx, chartHeight, nativePaneChrome, width],
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// Stream weights by market-cap rank, fixed for this load of the board.
|
|
327
|
+
const quoteWeightsRef = useRef<{ tab: string; weights: Map<string, number> } | null>(null);
|
|
328
|
+
const quoteWeights = useMemo(() => {
|
|
329
|
+
const previous = quoteWeightsRef.current?.tab === activeUniverse ? quoteWeightsRef.current.weights : null;
|
|
330
|
+
const weights = rankHeatmapQuoteWeights(boardAssets, previous);
|
|
331
|
+
quoteWeightsRef.current = { tab: activeUniverse, weights };
|
|
332
|
+
return weights;
|
|
333
|
+
}, [activeUniverse, boardAssets]);
|
|
334
|
+
const streamSelection = useSettledValue(selectedSymbol, SELECTION_STREAM_SETTLE_MS);
|
|
335
|
+
// With streaming off the board refreshes from snapshots only: no 500-name poll on top of them.
|
|
239
336
|
const quoteTargets = useMemo(
|
|
240
|
-
() =>
|
|
241
|
-
[boardAssets,
|
|
337
|
+
() => (liveStreaming ? buildHeatmapQuoteTargets(boardAssets, quoteWeights, streamSelection) : NO_TARGETS),
|
|
338
|
+
[boardAssets, liveStreaming, quoteWeights, streamSelection],
|
|
242
339
|
);
|
|
243
340
|
const {
|
|
244
341
|
entries: liveQuoteEntries,
|
|
@@ -249,7 +346,7 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
249
346
|
liveStreaming,
|
|
250
347
|
});
|
|
251
348
|
const resolvedAssets = useMemo(
|
|
252
|
-
() => overlayScreenerQuoteEntries(boardAssets, liveQuoteEntries),
|
|
349
|
+
() => overlayScreenerQuoteEntries(boardAssets, liveQuoteEntries, { extendedSessions: true }),
|
|
253
350
|
[boardAssets, liveQuoteEntries],
|
|
254
351
|
);
|
|
255
352
|
const feedStatus = useMemo(
|
|
@@ -259,21 +356,45 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
259
356
|
}),
|
|
260
357
|
[freshnessNow, liveQuoteEntries, quoteTargets, subscriptionStartedAt],
|
|
261
358
|
);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
359
|
+
|
|
360
|
+
// Sizes follow live prices at most every LAYOUT_THROTTLE_MS and only past
|
|
361
|
+
// LAYOUT_TOLERANCE; a new snapshot relays out at once. Ticks only recolour.
|
|
362
|
+
const grouping = useMemo(
|
|
363
|
+
() => resolveHeatmapGrouping(boardAssets, activeUniverse === "us-equity"),
|
|
364
|
+
[activeUniverse, boardAssets],
|
|
266
365
|
);
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
[
|
|
366
|
+
const layoutAssets = useThrottledMemo(
|
|
367
|
+
() => resolvedAssets,
|
|
368
|
+
[resolvedAssets],
|
|
369
|
+
[boardAssets],
|
|
370
|
+
LAYOUT_THROTTLE_MS,
|
|
271
371
|
);
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const
|
|
372
|
+
const layoutItems = useSettledLayoutItems(
|
|
373
|
+
useMemo(() => buildLayoutItems(boardAssets, layoutAssets, grouping, sizeBy), [boardAssets, grouping, layoutAssets, sizeBy]),
|
|
374
|
+
);
|
|
375
|
+
// The board on screen seeds the next layout's order, so a refresh nudges tiles instead of reshuffling them.
|
|
376
|
+
const sceneRef = useRef<{ tab: string; scene: ReturnType<typeof buildHeatTreemapScene<HeatmapBoardAsset>> } | null>(null);
|
|
377
|
+
const scene = useMemo(() => {
|
|
378
|
+
const previous = sceneRef.current?.tab === activeUniverse ? sceneRef.current.scene : null;
|
|
379
|
+
const next = buildHeatTreemapScene(layoutItems, canvas, previous);
|
|
380
|
+
sceneRef.current = { tab: activeUniverse, scene: next };
|
|
381
|
+
return next;
|
|
382
|
+
}, [activeUniverse, canvas, layoutItems]);
|
|
383
|
+
// The terminal repaints whole cells: colours there move at most four times a second.
|
|
384
|
+
const paintAssets = useThrottledMemo(
|
|
385
|
+
() => resolvedAssets,
|
|
386
|
+
[resolvedAssets],
|
|
387
|
+
[boardAssets],
|
|
388
|
+
nativePaneChrome ? 0 : TERMINAL_PAINT_THROTTLE_MS,
|
|
389
|
+
);
|
|
390
|
+
const paintItems = useMemo(() => buildPaintItems(paintAssets), [paintAssets]);
|
|
391
|
+
const visibleTiles = scene.tiles;
|
|
392
|
+
const selectedTileIndex = selectedSymbol ? visibleTiles.findIndex((tile) => tile.item.id === selectedSymbol) : -1;
|
|
393
|
+
const activeIdx = selectedTileIndex >= 0 ? selectedTileIndex : (visibleTiles.length > 0 ? 0 : -1);
|
|
394
|
+
const activeSymbol = activeIdx >= 0 ? visibleTiles[activeIdx]!.item.id : null;
|
|
395
|
+
const selectedAsset = activeSymbol
|
|
396
|
+
? resolvedAssets.find((asset) => asset.symbol === activeSymbol) ?? null
|
|
397
|
+
: null;
|
|
277
398
|
|
|
278
399
|
const loadUniverse = useCallback(async (universe: MarketHeatmapUniverseId, options?: { forceRefresh?: boolean }) => {
|
|
279
400
|
fetchGenRef.current += 1;
|
|
@@ -283,7 +404,7 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
283
404
|
|
|
284
405
|
try {
|
|
285
406
|
const result = await fetchMarketHeatmap(universe, {
|
|
286
|
-
count:
|
|
407
|
+
count: MARKET_HEATMAP_REQUEST_COUNT[universe],
|
|
287
408
|
forceRefresh: options?.forceRefresh,
|
|
288
409
|
});
|
|
289
410
|
if (fetchGenRef.current !== gen) return;
|
|
@@ -314,6 +435,11 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
314
435
|
setSelectedSymbol(null);
|
|
315
436
|
}, [collectionId, linkPortfolio, setActiveUniverse]);
|
|
316
437
|
|
|
438
|
+
// The header shows the square-root control only where it changes the board.
|
|
439
|
+
useEffect(() => {
|
|
440
|
+
publishCollectionKind(collectionKind ?? "");
|
|
441
|
+
}, [collectionKind, publishCollectionKind]);
|
|
442
|
+
|
|
317
443
|
// The financials map only reads the cache; this fills it for the list on screen.
|
|
318
444
|
useEffect(() => {
|
|
319
445
|
if (!portfolioTab) return;
|
|
@@ -321,10 +447,12 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
321
447
|
// Keyed by the symbols: another ticker's record changing does not reload the list.
|
|
322
448
|
}, [collectionId, collectionKind, collectionSymbolsKey, portfolioTab]);
|
|
323
449
|
|
|
450
|
+
// Only drawn tiles are selectable; a name folded into Other hands the selection to the first tile.
|
|
324
451
|
useEffect(() => {
|
|
325
|
-
if (selectedSymbol &&
|
|
326
|
-
|
|
327
|
-
|
|
452
|
+
if (selectedSymbol && visibleTiles.some((tile) => tile.item.id === selectedSymbol)) return;
|
|
453
|
+
const first = visibleTiles[0]?.item.id ?? null;
|
|
454
|
+
if (first !== selectedSymbol) setSelectedSymbol(first);
|
|
455
|
+
}, [selectedSymbol, visibleTiles]);
|
|
328
456
|
|
|
329
457
|
const refresh = useCallback(() => {
|
|
330
458
|
if (portfolioTab) {
|
|
@@ -359,15 +487,16 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
359
487
|
pinTicker(symbol, { floating: true, paneType: TICKER_RESEARCH_PANE_ID });
|
|
360
488
|
}, [pinTicker]);
|
|
361
489
|
|
|
490
|
+
// j and k walk the tiles in reading order: sector by sector, largest first.
|
|
362
491
|
const selectIndex = useCallback((index: number) => {
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
}, [
|
|
492
|
+
const tile = visibleTiles[index];
|
|
493
|
+
if (tile) setSelectedSymbol(tile.item.id);
|
|
494
|
+
}, [visibleTiles]);
|
|
366
495
|
|
|
367
496
|
const selectNeighbor = useCallback((direction: MetricTreemapDirection) => {
|
|
368
|
-
const target = findMetricTreemapNeighbor(
|
|
369
|
-
if (target) setSelectedSymbol(target.item.
|
|
370
|
-
}, [
|
|
497
|
+
const target = findMetricTreemapNeighbor(visibleTiles, activeSymbol, direction);
|
|
498
|
+
if (target) setSelectedSymbol(target.item.id);
|
|
499
|
+
}, [activeSymbol, visibleTiles]);
|
|
371
500
|
|
|
372
501
|
useShortcut((event) => {
|
|
373
502
|
if (!focused) return;
|
|
@@ -405,7 +534,7 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
405
534
|
if (isPlainKey(event, "j")) {
|
|
406
535
|
event.preventDefault();
|
|
407
536
|
event.stopPropagation();
|
|
408
|
-
selectIndex(Math.min((activeIdx >= 0 ? activeIdx : 0) + 1,
|
|
537
|
+
selectIndex(Math.min((activeIdx >= 0 ? activeIdx : 0) + 1, visibleTiles.length - 1));
|
|
409
538
|
return;
|
|
410
539
|
}
|
|
411
540
|
if (isPlainKey(event, "k")) {
|
|
@@ -446,7 +575,8 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
446
575
|
});
|
|
447
576
|
|
|
448
577
|
const updated = useUpdatedAgo(!portfolioTab && loadedUniverse === activeUniverse ? lastUpdated : null);
|
|
449
|
-
|
|
578
|
+
// The snapshot carries sizes and every name the stream does not; the server caches it for a minute.
|
|
579
|
+
useAutoRefresh(lastUpdated, autoRefresh, { intervalMs: SNAPSHOT_REFRESH_MS });
|
|
450
580
|
|
|
451
581
|
usePaneStatusFooter({ registrationId: "market-heatmap-retained", stale: hasBoard && stale && !portfolioTab });
|
|
452
582
|
usePaneNoticeFooter({
|
|
@@ -463,13 +593,20 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
463
593
|
id: "selected",
|
|
464
594
|
parts: [
|
|
465
595
|
{ text: selectedAsset.symbol, tone: "label" as const },
|
|
466
|
-
{ text: formatCurrency(selectedAsset.price, selectedAsset.currency), tone: "value" as const },
|
|
467
596
|
{
|
|
468
|
-
text: selectedAsset
|
|
597
|
+
text: heatmapMove(selectedAsset) == null ? "—" : formatPercentRaw(heatmapMove(selectedAsset)!),
|
|
469
598
|
tone: "value" as const,
|
|
470
|
-
color: selectedAsset
|
|
599
|
+
color: heatmapMove(selectedAsset) == null ? undefined : priceColor(heatmapMove(selectedAsset)!),
|
|
471
600
|
bold: true,
|
|
472
601
|
},
|
|
602
|
+
...(sessionMark(selectedAsset) ? [{ text: sessionMark(selectedAsset)!, tone: "muted" as const }] : []),
|
|
603
|
+
...(selectedAsset.price > 0
|
|
604
|
+
? [{ text: formatCurrency(selectedAsset.price, selectedAsset.currency), tone: "value" as const }]
|
|
605
|
+
: []),
|
|
606
|
+
...(sizeLabel(selectedAsset) ? [{ text: sizeLabel(selectedAsset)!, tone: "muted" as const }] : []),
|
|
607
|
+
...(selectedAsset.volume != null
|
|
608
|
+
? [{ text: `Vol ${formatCompact(selectedAsset.volume)}`, tone: "muted" as const }]
|
|
609
|
+
: []),
|
|
473
610
|
],
|
|
474
611
|
}] : []),
|
|
475
612
|
...(updated ? [{
|
|
@@ -509,14 +646,17 @@ function MarketHeatmapPane({ focused, width, height }: PaneProps) {
|
|
|
509
646
|
empty={!hasBoard}
|
|
510
647
|
emptyTitle={portfolioTab ? EMPTY_PORTFOLIO_TITLE : EMPTY_TITLE}
|
|
511
648
|
>
|
|
512
|
-
<
|
|
513
|
-
|
|
649
|
+
<HeatTreemapSurface
|
|
650
|
+
scene={scene}
|
|
651
|
+
items={paintItems}
|
|
514
652
|
width={width}
|
|
515
653
|
height={chartHeight}
|
|
516
|
-
selectedId={
|
|
517
|
-
onSelect={(item) => setSelectedSymbol(item.
|
|
518
|
-
onActivate={(item) => openSymbol(item.
|
|
654
|
+
selectedId={activeSymbol}
|
|
655
|
+
onSelect={(item) => setSelectedSymbol(item.id)}
|
|
656
|
+
onActivate={(item) => openSymbol(item.id)}
|
|
519
657
|
emptyStateTitle={portfolioTab ? EMPTY_PORTFOLIO_TITLE : EMPTY_TITLE}
|
|
658
|
+
otherTooltip={otherTooltip}
|
|
659
|
+
otherSummary={otherSummary}
|
|
520
660
|
/>
|
|
521
661
|
</PaneStatusBody>
|
|
522
662
|
</Box>
|
|
@@ -527,7 +667,7 @@ export const marketHeatmapPlugin: GloomPlugin = {
|
|
|
527
667
|
id: "market-heatmap",
|
|
528
668
|
name: "Market Heatmap",
|
|
529
669
|
version: "1.0.0",
|
|
530
|
-
description: "Largest US stocks and ETFs, or the portfolio pane's list, sized by market cap or position and colored by daily move",
|
|
670
|
+
description: "Largest US stocks and ETFs, or the portfolio pane's list, sized by the square root of market cap or by position value and colored by daily move",
|
|
531
671
|
toggleable: true,
|
|
532
672
|
targets: ["cli", "tui", "desktop", "web"],
|
|
533
673
|
|
|
@@ -541,13 +681,27 @@ export const marketHeatmapPlugin: GloomPlugin = {
|
|
|
541
681
|
name: "Market Heatmap",
|
|
542
682
|
icon: "H",
|
|
543
683
|
component: MarketHeatmapPane,
|
|
684
|
+
headless: marketHeatmapHeadless,
|
|
544
685
|
defaultPosition: "right",
|
|
545
686
|
defaultMode: "floating",
|
|
546
687
|
defaultFloatingSize: { width: 110, height: 36 },
|
|
547
|
-
quickSettings: [
|
|
688
|
+
quickSettings: [
|
|
689
|
+
LIVE_STREAMING_QUICK_SETTING,
|
|
690
|
+
{
|
|
691
|
+
type: "toggle",
|
|
692
|
+
key: SIZE_BY_SETTING_KEY,
|
|
693
|
+
icon: "sqrt",
|
|
694
|
+
onValue: SQRT_SIZE_VALUE,
|
|
695
|
+
label: "Size by square root of market cap",
|
|
696
|
+
visible: (context) => heatmapSizeByApplies(context.settings.universe, context.paneState[HEATMAP_COLLECTION_KIND_STATE_KEY]),
|
|
697
|
+
},
|
|
698
|
+
],
|
|
548
699
|
settings: (context) => withLiveStreamingSetting({
|
|
549
700
|
title: "Market Heatmap Settings",
|
|
550
|
-
values: {
|
|
701
|
+
values: {
|
|
702
|
+
linkPortfolio: context.settings.linkPortfolio === true,
|
|
703
|
+
[SIZE_BY_SETTING_KEY]: heatmapSizeBy(context.settings[SIZE_BY_SETTING_KEY]),
|
|
704
|
+
},
|
|
551
705
|
fields: [
|
|
552
706
|
{
|
|
553
707
|
key: "universe",
|
|
@@ -561,6 +715,16 @@ export const marketHeatmapPlugin: GloomPlugin = {
|
|
|
561
715
|
{ value: PORTFOLIO_HEATMAP_TAB, label: "Portfolio pane list" },
|
|
562
716
|
],
|
|
563
717
|
},
|
|
718
|
+
{
|
|
719
|
+
key: SIZE_BY_SETTING_KEY,
|
|
720
|
+
label: "Size by",
|
|
721
|
+
type: "select",
|
|
722
|
+
options: [
|
|
723
|
+
{ value: "market-cap", label: "Market cap" },
|
|
724
|
+
{ value: SQRT_SIZE_VALUE, label: "Square root of market cap" },
|
|
725
|
+
],
|
|
726
|
+
description: "Square root gives mid-size names room next to the largest. A portfolio is always sized by position value.",
|
|
727
|
+
},
|
|
564
728
|
{
|
|
565
729
|
key: "linkPortfolio",
|
|
566
730
|
label: "Link to portfolio",
|
|
@@ -577,7 +741,7 @@ export const marketHeatmapPlugin: GloomPlugin = {
|
|
|
577
741
|
id: "market-heatmap-pane",
|
|
578
742
|
paneId: "market-heatmap",
|
|
579
743
|
label: "Market Heatmap",
|
|
580
|
-
description: "Largest US stocks and ETFs, or the portfolio pane's list, sized by market cap or position and colored by daily move.",
|
|
744
|
+
description: "Largest US stocks and ETFs, or the portfolio pane's list, sized by the square root of market cap or by position value and colored by daily move.",
|
|
581
745
|
keywords: ["heatmap", "market", "largest", "top", "stocks", "etf", "portfolio", "watchlist", "screener"],
|
|
582
746
|
shortcut: { prefix: "HM" },
|
|
583
747
|
},
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import type { QuoteSubscriptionTarget } from "../../../types/data-provider";
|
|
3
|
+
import type { HeatmapBoardAsset } from "./portfolio";
|
|
4
|
+
|
|
5
|
+
/** The board never asks to stream more than this; the server caps lower for most tiers. */
|
|
6
|
+
export const HEATMAP_MAX_QUOTE_TARGETS = 500;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Stream priority by market-cap rank. A connection over its tier's symbol cap
|
|
10
|
+
* keeps its highest-priority targets (the cloud realtime service ranks by
|
|
11
|
+
* weight plus selected and visible bonuses and breaks ties alphabetically), so
|
|
12
|
+
* every rank gets its own weight and the largest names stay live whatever the
|
|
13
|
+
* cap. The weights stay at or under the client's off-screen ceiling of 10
|
|
14
|
+
* (`OFFSCREEN_QUOTE_WEIGHT`), so covering the pane rewrites no weight and the
|
|
15
|
+
* server evicts and admits nothing.
|
|
16
|
+
*/
|
|
17
|
+
function heatmapQuoteWeight(rank: number): number {
|
|
18
|
+
return Math.max(0.02, Math.round((10 - rank * 0.02) * 100) / 100);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function sizeOf(asset: HeatmapBoardAsset): number {
|
|
22
|
+
return asset.weight ?? asset.size ?? 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Weights for this load of a board. A name keeps the weight it was first
|
|
27
|
+
* given, so a snapshot refresh that reorders two neighbours re-sends nothing;
|
|
28
|
+
* a new name takes the weight of its rank.
|
|
29
|
+
*/
|
|
30
|
+
export function rankHeatmapQuoteWeights(
|
|
31
|
+
assets: readonly HeatmapBoardAsset[],
|
|
32
|
+
previous: ReadonlyMap<string, number> | null,
|
|
33
|
+
): Map<string, number> {
|
|
34
|
+
const ranked = [...assets].sort((left, right) => sizeOf(right) - sizeOf(left) || left.symbol.localeCompare(right.symbol));
|
|
35
|
+
const weights = new Map<string, number>();
|
|
36
|
+
ranked.forEach((asset, rank) => {
|
|
37
|
+
weights.set(asset.symbol, previous?.get(asset.symbol) ?? heatmapQuoteWeight(rank));
|
|
38
|
+
});
|
|
39
|
+
return weights;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The board's stream targets: the largest names first, at most
|
|
44
|
+
* `HEATMAP_MAX_QUOTE_TARGETS`. No `visible` hint: a treemap shows every tile
|
|
45
|
+
* at once, the hint would only add a bonus that changes when the pane is
|
|
46
|
+
* covered, and a tile without it is paced at about once a second, which is
|
|
47
|
+
* all a colour needs. Only the settled selection is marked selected.
|
|
48
|
+
*/
|
|
49
|
+
export function buildHeatmapQuoteTargets(
|
|
50
|
+
assets: readonly HeatmapBoardAsset[],
|
|
51
|
+
weights: ReadonlyMap<string, number>,
|
|
52
|
+
selectedSymbol: string | null,
|
|
53
|
+
): QuoteSubscriptionTarget[] {
|
|
54
|
+
return [...assets]
|
|
55
|
+
.sort((left, right) => (weights.get(right.symbol) ?? 0) - (weights.get(left.symbol) ?? 0)
|
|
56
|
+
|| left.symbol.localeCompare(right.symbol))
|
|
57
|
+
.slice(0, HEATMAP_MAX_QUOTE_TARGETS)
|
|
58
|
+
.map((asset) => ({
|
|
59
|
+
symbol: asset.symbol,
|
|
60
|
+
exchange: asset.exchange,
|
|
61
|
+
surface: "screener",
|
|
62
|
+
weight: weights.get(asset.symbol) ?? 0,
|
|
63
|
+
...(asset.symbol === selectedSymbol ? { selected: true } : {}),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The tile area follows the live price: market cap scales with it until the
|
|
69
|
+
* next snapshot brings a fresh cap. Boards sized by something else (a
|
|
70
|
+
* position's value) already move with their own data.
|
|
71
|
+
*/
|
|
72
|
+
export function liveHeatmapWeight(snapshot: HeatmapBoardAsset, live: HeatmapBoardAsset): number {
|
|
73
|
+
const base = sizeOf(snapshot);
|
|
74
|
+
if (snapshot.weight != null || live === snapshot) return base;
|
|
75
|
+
if (!(snapshot.price > 0) || !(typeof live.price === "number" && live.price > 0)) return base;
|
|
76
|
+
return base * live.price / snapshot.price;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Selection as the stream sees it: only once it rests, so sweeping the pointer across tiles does not churn subscriptions. */
|
|
80
|
+
export function useSettledValue<T>(value: T, delayMs: number): T {
|
|
81
|
+
const [settled, setSettled] = useState(value);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (Object.is(settled, value)) return;
|
|
84
|
+
const timer = setTimeout(() => setSettled(value), delayMs);
|
|
85
|
+
return () => clearTimeout(timer);
|
|
86
|
+
}, [delayMs, settled, value]);
|
|
87
|
+
return settled;
|
|
88
|
+
}
|