gloomberb 0.15.7 → 0.16.0
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 +11 -2
- package/package.json +1 -1
- package/src/api-client/app-attention.ts +147 -0
- package/src/api-client/attention.ts +26 -0
- package/src/api-client/awards.ts +215 -0
- package/src/api-client/catalysts.ts +160 -0
- package/src/api-client/chat.ts +137 -14
- package/src/api-client/company-kpis.ts +153 -0
- package/src/api-client/cpi.ts +52 -0
- package/src/api-client/credit-documents.ts +107 -0
- package/src/api-client/data.ts +192 -3
- package/src/api-client/distress.ts +164 -0
- package/src/api-client/doe.ts +75 -0
- package/src/api-client/equity-screener.ts +11 -0
- package/src/api-client/exposure.ts +202 -0
- package/src/api-client/gpu.ts +93 -0
- package/src/api-client/hiring.ts +110 -0
- package/src/api-client/index.ts +78 -3
- package/src/api-client/normalizers.ts +31 -1
- package/src/api-client/paths.ts +3 -0
- package/src/api-client/perps.ts +127 -0
- package/src/api-client/power.ts +148 -0
- package/src/api-client/request.ts +58 -1
- package/src/api-client/research-activity.ts +172 -13
- package/src/api-client/socket.ts +75 -27
- package/src/api-client/supply-chain-graph.ts +40 -0
- package/src/api-client/supply-chain.ts +98 -0
- package/src/api-client/telemetry.ts +29 -0
- package/src/api-client/themes.ts +28 -0
- package/src/api-client/types.ts +33 -1
- package/src/api-client/wall-experiments.ts +100 -0
- package/src/api-client/wall-summary.ts +49 -0
- package/src/api-client/web-experiments.ts +136 -0
- package/src/app/pane-runtime/plugin-bindings.ts +5 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +8 -2
- package/src/app/runtime/update.ts +13 -1
- package/src/cli/commands/system.ts +2 -0
- package/src/cli/desktop-pane-shot.ts +3 -4
- package/src/cli/pane-functions/data.ts +78 -0
- package/src/cli/pane-functions/financial-ratio-shot.ts +160 -0
- package/src/cli/pane-functions/function-help.ts +220 -8
- package/src/cli/pane-functions/headless.ts +4 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +21 -0
- package/src/cli/pane-functions/screenshot.ts +49 -5
- package/src/components/chart/composite/composite-chart.tsx +15 -2
- package/src/components/chart/composite/format.ts +24 -11
- package/src/components/chart/composite/rasterizer.ts +67 -16
- package/src/components/chart/composite/scene.ts +53 -2
- package/src/components/chart/composite/session-shading.ts +3 -2
- package/src/components/chart/composite/text-renderer.ts +52 -1
- package/src/components/chart/composite/time-axis.ts +100 -30
- package/src/components/chart/composite/tools.ts +2 -1
- package/src/components/chart/composite/types.ts +4 -0
- package/src/components/chart-table/index.ts +1 -0
- package/src/components/chart-table/layout.ts +15 -0
- package/src/components/command-bar/action-runtime.ts +1 -0
- package/src/components/command-bar/commands/direct/index.ts +32 -0
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/pane-templates/items.ts +11 -0
- package/src/components/command-bar/pane-templates/workflow.ts +19 -4
- package/src/components/command-bar/routes/root/command-items.ts +6 -0
- package/src/components/command-bar/routes/root/provider-search.ts +2 -0
- package/src/components/command-bar/routes/root/results.ts +64 -0
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +89 -24
- package/src/components/command-bar/routes/ticker-search/route.ts +2 -0
- package/src/components/command-bar/surface/index.tsx +15 -0
- package/src/components/command-bar/view-model.ts +3 -0
- package/src/components/command-bar/workflow/collection-actions.ts +9 -7
- package/src/components/command-bar/workflow/ops.ts +19 -0
- package/src/components/command-bar/workflow/tickers.ts +5 -0
- package/src/components/company-logo.tsx +15 -2
- package/src/components/data-table/table-pane.ts +2 -1
- package/src/components/index.ts +1 -0
- package/src/components/layout/detached-pane-shell.tsx +12 -1
- package/src/components/layout/missing-pane.tsx +87 -23
- package/src/components/layout/pane/footer/index.tsx +64 -18
- package/src/components/layout/pane/footer/model.ts +85 -0
- package/src/components/layout/pane/sidebar.tsx +19 -1
- package/src/components/layout/shell/index.tsx +38 -28
- package/src/components/layout/shell/pane/management-shortcuts.ts +13 -1
- package/src/components/layout/status-bar.tsx +93 -28
- package/src/components/layout/status-widget-space.ts +72 -0
- package/src/components/onboarding/first-run-workspace.ts +8 -2
- package/src/components/onboarding/onboarding-wizard.tsx +35 -16
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -5
- package/src/components/onboarding/wizard-model.ts +13 -5
- package/src/components/onboarding/wizard-positions.ts +56 -7
- package/src/components/price-performance.tsx +31 -34
- package/src/components/ui/data-table/index.tsx +11 -8
- package/src/components/ui/display.tsx +15 -6
- package/src/components/ui/fields.tsx +5 -0
- package/src/components/ui/figure.tsx +94 -0
- package/src/components/ui/header-case.ts +25 -3
- package/src/components/ui/icon.tsx +3 -1
- package/src/components/ui/message-composer.tsx +8 -1
- package/src/components/ui/query-bar.tsx +8 -1
- package/src/components/ui/ratio-bar.tsx +84 -0
- package/src/components/ui/toggle.tsx +3 -1
- package/src/components/use-scrollbox-layout.ts +17 -0
- package/src/core/state/app/layout.ts +35 -1
- package/src/core/state/app/state.ts +15 -0
- package/src/core/state/app/types.ts +1 -0
- package/src/data/config/store/normalize.ts +24 -0
- package/src/i18n/es.ts +2 -0
- package/src/i18n/ja.ts +2 -0
- package/src/i18n/ko.ts +2 -0
- package/src/i18n/zh-cn.ts +2 -0
- package/src/i18n/zh-tw.ts +2 -0
- package/src/layout-marketplace/pane-imagery.ts +1 -0
- package/src/market-data/coordinator/entries.ts +13 -0
- package/src/market-data/coordinator/financials.ts +33 -8
- package/src/market-data/market/freshness.ts +16 -5
- package/src/market-data/market/trading-sessions.ts +65 -1
- package/src/market-data/published-cn-sessions.ts +25 -0
- package/src/market-data/published-nse-sessions.ts +20 -0
- package/src/news/aggregator.ts +4 -0
- package/src/plugins/builtin/account-management/model.ts +6 -1
- package/src/plugins/builtin/account-management/pane.tsx +36 -25
- package/src/plugins/builtin/alerts/catalysts.ts +77 -0
- package/src/plugins/builtin/alerts/events-pane.tsx +3 -0
- package/src/plugins/builtin/alerts/events.ts +10 -4
- package/src/plugins/builtin/alerts/history-pane.tsx +1 -1
- package/src/plugins/builtin/alerts/history.ts +1 -0
- package/src/plugins/builtin/alerts/index.tsx +6 -0
- package/src/plugins/builtin/alerts/research-builder.ts +10 -3
- package/src/plugins/builtin/alerts/research-rules.ts +15 -1
- package/src/plugins/builtin/analytics/risk-client.ts +15 -3
- package/src/plugins/builtin/analytics/risk-headless.ts +123 -18
- package/src/plugins/builtin/attention/client.ts +80 -0
- package/src/plugins/builtin/attention/evidence.ts +30 -0
- package/src/plugins/builtin/attention/headless.ts +33 -0
- package/src/plugins/builtin/attention/index.tsx +18 -0
- package/src/plugins/builtin/attention/model.ts +59 -0
- package/src/plugins/builtin/attention/pane.tsx +211 -0
- package/src/plugins/builtin/attention/trending.tsx +59 -0
- package/src/plugins/builtin/awards/alerts.ts +32 -0
- package/src/plugins/builtin/awards/client.ts +82 -0
- package/src/plugins/builtin/awards/detail.tsx +107 -0
- package/src/plugins/builtin/awards/evidence.ts +36 -0
- package/src/plugins/builtin/awards/headless.ts +55 -0
- package/src/plugins/builtin/awards/index.tsx +20 -0
- package/src/plugins/builtin/awards/model.ts +42 -0
- package/src/plugins/builtin/awards/pane.tsx +263 -0
- package/src/plugins/builtin/catalysts/client.ts +28 -0
- package/src/plugins/builtin/catalysts/detail.tsx +88 -0
- package/src/plugins/builtin/catalysts/evidence.ts +47 -0
- package/src/plugins/builtin/catalysts/headless.ts +42 -0
- package/src/plugins/builtin/catalysts/history.ts +26 -0
- package/src/plugins/builtin/catalysts/index.tsx +29 -0
- package/src/plugins/builtin/catalysts/model.ts +135 -0
- package/src/plugins/builtin/catalysts/pane.tsx +159 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +4 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +6 -0
- package/src/plugins/builtin/chart-composer/index.tsx +8 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +28 -1
- package/src/plugins/builtin/chat/attachments/desktop.tsx +610 -0
- package/src/plugins/builtin/chat/attachments/files.ts +45 -0
- package/src/plugins/builtin/chat/attachments/model.ts +164 -0
- package/src/plugins/builtin/chat/attachments/terminal.tsx +72 -0
- package/src/plugins/builtin/chat/attachments/transfer.ts +165 -0
- package/src/plugins/builtin/chat/content/channel-navigation.ts +13 -12
- package/src/plugins/builtin/chat/content/composer-runtime.ts +25 -4
- package/src/plugins/builtin/chat/content/composer.tsx +46 -4
- package/src/plugins/builtin/chat/content/footer.tsx +46 -8
- package/src/plugins/builtin/chat/content/index.tsx +263 -62
- package/src/plugins/builtin/chat/content/layout-metrics.ts +10 -2
- package/src/plugins/builtin/chat/content/open-targets.ts +17 -3
- package/src/plugins/builtin/chat/content/scroll.ts +7 -1
- package/src/plugins/builtin/chat/content/shortcuts.ts +36 -11
- package/src/plugins/builtin/chat/content/snapshot.ts +3 -0
- package/src/plugins/builtin/chat/content/transcript.tsx +17 -1
- package/src/plugins/builtin/chat/content/types.ts +7 -0
- package/src/plugins/builtin/chat/controller/attachments.ts +213 -0
- package/src/plugins/builtin/chat/controller/connections.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +114 -2
- package/src/plugins/builtin/chat/controller/lifecycle.ts +9 -0
- package/src/plugins/builtin/chat/controller/messages.ts +35 -2
- package/src/plugins/builtin/chat/controller/send.ts +128 -25
- package/src/plugins/builtin/chat/controller/state.ts +12 -1
- package/src/plugins/builtin/chat/controller/utils.ts +7 -5
- package/src/plugins/builtin/chat/controller/view.ts +2 -0
- package/src/plugins/builtin/chat/index.tsx +21 -0
- package/src/plugins/builtin/chat/layout.ts +9 -4
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -20
- package/src/plugins/builtin/chat/message/header.tsx +30 -5
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +9 -0
- package/src/plugins/builtin/chat/message/pending-send.ts +35 -0
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/render-state.ts +12 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +51 -4
- package/src/plugins/builtin/chat/message/types.ts +6 -1
- package/src/plugins/builtin/chat/pane-state.ts +59 -1
- package/src/plugins/builtin/chat/profile-popover.ts +50 -1
- package/src/plugins/builtin/chat/sidebar.tsx +8 -3
- package/src/plugins/builtin/chat/status-widget.tsx +29 -12
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +143 -0
- package/src/plugins/builtin/chat/unread-inbox.ts +91 -0
- package/src/plugins/builtin/clinical-trials/client.ts +237 -0
- package/src/plugins/builtin/clinical-trials/index.tsx +74 -0
- package/src/plugins/builtin/clinical-trials/pane.tsx +225 -0
- package/src/plugins/builtin/clinical-trials/types.ts +2 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +37 -6
- package/src/plugins/builtin/cloud/askg/executor.ts +59 -44
- package/src/plugins/builtin/cloud/askg/host.ts +8 -1
- package/src/plugins/builtin/cloud/askg/manifest.ts +29 -2
- package/src/plugins/builtin/cloud/askg/model.ts +47 -13
- package/src/plugins/builtin/cloud/askg/notes.ts +100 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +50 -14
- package/src/plugins/builtin/cloud/askg/protocol.ts +39 -1
- package/src/plugins/builtin/cloud/askg/result-budget.ts +156 -0
- package/src/plugins/builtin/cloud/askg/user-data.ts +89 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +55 -31
- package/src/plugins/builtin/cloud/plugin.tsx +4 -1
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +10 -1
- package/src/plugins/builtin/cloud/team/pane.tsx +3 -2
- package/src/plugins/builtin/cloud/thesis/board-pane.tsx +2 -2
- package/src/plugins/builtin/cloud/thesis/detail.tsx +1 -1
- package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -2
- package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +202 -0
- package/src/plugins/builtin/cloud/upgrade-command.ts +1 -1
- package/src/plugins/builtin/cloud/upgrade-dialog.tsx +29 -3
- package/src/plugins/builtin/cloud/upgrade-status-widget.tsx +1 -1
- package/src/plugins/builtin/cloud-tweets/table.tsx +1 -1
- package/src/plugins/builtin/comment-letters/client.ts +342 -0
- package/src/plugins/builtin/comment-letters/index.tsx +74 -0
- package/src/plugins/builtin/comment-letters/pane.tsx +295 -0
- package/src/plugins/builtin/comment-letters/types.ts +43 -0
- package/src/plugins/builtin/company-attention/app-rank.tsx +79 -0
- package/src/plugins/builtin/company-attention/client.ts +69 -0
- package/src/plugins/builtin/company-attention/evidence.ts +45 -0
- package/src/plugins/builtin/company-attention/headless.ts +47 -0
- package/src/plugins/builtin/company-attention/index.tsx +30 -0
- package/src/plugins/builtin/company-attention/model.ts +129 -0
- package/src/plugins/builtin/company-attention/pane.tsx +183 -0
- package/src/plugins/builtin/company-kpis/client.ts +92 -0
- package/src/plugins/builtin/company-kpis/headless.ts +32 -0
- package/src/plugins/builtin/company-kpis/index.tsx +26 -0
- package/src/plugins/builtin/company-kpis/model.ts +124 -0
- package/src/plugins/builtin/company-kpis/pane.tsx +226 -0
- package/src/plugins/builtin/company-kpis/related.ts +11 -0
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +44 -0
- package/src/plugins/builtin/composite-plugins.ts +34 -0
- package/src/plugins/builtin/correlation/history.ts +4 -1
- package/src/plugins/builtin/correlation/index.tsx +139 -80
- package/src/plugins/builtin/correlation/matrix/pair-chart.tsx +48 -0
- package/src/plugins/builtin/correlation/matrix/selection.ts +77 -0
- package/src/plugins/builtin/correlation/relationship/model.ts +2 -2
- package/src/plugins/builtin/cpi/client.ts +66 -0
- package/src/plugins/builtin/cpi/headless.ts +78 -0
- package/src/plugins/builtin/cpi/index.tsx +31 -0
- package/src/plugins/builtin/cpi/model.ts +198 -0
- package/src/plugins/builtin/cpi/pane.tsx +157 -0
- package/src/plugins/builtin/credit-documents/client.ts +99 -0
- package/src/plugins/builtin/credit-documents/detail.tsx +109 -0
- package/src/plugins/builtin/credit-documents/evidence.ts +64 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +55 -0
- package/src/plugins/builtin/credit-documents/headless.ts +40 -0
- package/src/plugins/builtin/credit-documents/index.tsx +19 -0
- package/src/plugins/builtin/credit-documents/model.ts +336 -0
- package/src/plugins/builtin/credit-documents/pane.tsx +185 -0
- package/src/plugins/builtin/custom-view/view-spec.ts +14 -2
- package/src/plugins/builtin/debt-maturities/pane.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/doe/client.ts +73 -0
- package/src/plugins/builtin/doe/headless.ts +93 -0
- package/src/plugins/builtin/doe/index.tsx +41 -0
- package/src/plugins/builtin/doe/model.ts +215 -0
- package/src/plugins/builtin/doe/pane.tsx +148 -0
- package/src/plugins/builtin/doe/range-bar.tsx +45 -0
- package/src/plugins/builtin/earnings/board.tsx +3 -0
- package/src/plugins/builtin/earnings/index.tsx +2 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +7 -1
- package/src/plugins/builtin/earnings-calls/transcript-view.tsx +7 -7
- package/src/plugins/builtin/earnings-ripple/client.ts +60 -0
- package/src/plugins/builtin/earnings-ripple/headless.ts +35 -0
- package/src/plugins/builtin/earnings-ripple/index.tsx +35 -0
- package/src/plugins/builtin/earnings-ripple/model.ts +98 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +103 -0
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/criterion-editor.tsx +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +74 -9
- package/src/plugins/builtin/equity-screener/pane.tsx +2 -0
- package/src/plugins/builtin/estimate-revisions/pane.tsx +3 -0
- package/src/plugins/builtin/executives/pane.tsx +7 -5
- package/src/plugins/builtin/exposure/charts.tsx +66 -0
- package/src/plugins/builtin/exposure/client.ts +53 -0
- package/src/plugins/builtin/exposure/drivers.ts +29 -0
- package/src/plugins/builtin/exposure/editor.tsx +61 -0
- package/src/plugins/builtin/exposure/evidence.ts +39 -0
- package/src/plugins/builtin/exposure/headless.ts +51 -0
- package/src/plugins/builtin/exposure/holdings.ts +56 -0
- package/src/plugins/builtin/exposure/index.tsx +13 -0
- package/src/plugins/builtin/exposure/model.ts +104 -0
- package/src/plugins/builtin/exposure/pane.tsx +247 -0
- package/src/plugins/builtin/fear-greed/charts.tsx +1 -1
- package/src/plugins/builtin/fear-greed/pane.tsx +2 -9
- package/src/plugins/builtin/filing-events/pane.tsx +2 -1
- package/src/plugins/builtin/gpu/board.tsx +163 -0
- package/src/plugins/builtin/gpu/changes.tsx +94 -0
- package/src/plugins/builtin/gpu/client.ts +130 -0
- package/src/plugins/builtin/gpu/equities.tsx +112 -0
- package/src/plugins/builtin/gpu/headless.ts +67 -0
- package/src/plugins/builtin/gpu/history.tsx +140 -0
- package/src/plugins/builtin/gpu/index.tsx +18 -0
- package/src/plugins/builtin/gpu/ladder.tsx +127 -0
- package/src/plugins/builtin/gpu/model.ts +317 -0
- package/src/plugins/builtin/gpu/pane.tsx +63 -0
- package/src/plugins/builtin/help/index.tsx +19 -2
- package/src/plugins/builtin/holders/pane.tsx +5 -9
- package/src/plugins/builtin/insider/detail.tsx +119 -0
- package/src/plugins/builtin/insider/display.ts +221 -0
- package/src/plugins/builtin/insider/headless.ts +24 -3
- package/src/plugins/builtin/insider/index.tsx +206 -108
- package/src/plugins/builtin/insider/insider-data.ts +31 -3
- package/src/plugins/builtin/insider/model.ts +53 -4
- package/src/plugins/builtin/insider/table-model.ts +226 -0
- package/src/plugins/builtin/insider/table.tsx +79 -0
- package/src/plugins/builtin/iv-history/screen-pane.tsx +1 -1
- package/src/plugins/builtin/jobs/pane.tsx +14 -7
- package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
- package/src/plugins/builtin/macro-day/client.ts +50 -0
- package/src/plugins/builtin/macro-day/headless.ts +51 -0
- package/src/plugins/builtin/macro-day/index.tsx +21 -0
- package/src/plugins/builtin/macro-day/model.ts +137 -0
- package/src/plugins/builtin/macro-day/pane.tsx +118 -0
- package/src/plugins/builtin/macro-day/releases.ts +58 -0
- package/src/plugins/builtin/market-halts/model.ts +30 -17
- package/src/plugins/builtin/market-halts/pane.tsx +15 -21
- package/src/plugins/builtin/market-heatmap/data.ts +1 -1
- package/src/plugins/builtin/market-heatmap/index.tsx +198 -50
- package/src/plugins/builtin/market-heatmap/portfolio.ts +220 -0
- package/src/plugins/builtin/market-movers/index.tsx +1 -0
- package/src/plugins/builtin/market-movers/session-body.tsx +5 -2
- package/src/plugins/builtin/mna/distress/client.ts +326 -0
- package/src/plugins/builtin/mna/distress/detail.tsx +247 -0
- package/src/plugins/builtin/mna/distress/headless.ts +257 -0
- package/src/plugins/builtin/mna/distress/model.ts +427 -0
- package/src/plugins/builtin/mna/distress/pane.tsx +606 -0
- package/src/plugins/builtin/mna/index.tsx +15 -0
- package/src/plugins/builtin/mna/pane.tsx +42 -1
- package/src/plugins/builtin/news/index.tsx +62 -16
- package/src/plugins/builtin/news/wire/filter-articles.ts +54 -0
- package/src/plugins/builtin/news/wire/index.tsx +37 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +29 -13
- package/src/plugins/builtin/news/wire/mutes.ts +253 -0
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +117 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +4 -0
- package/src/plugins/builtin/news/wire/news/list-search.ts +34 -0
- package/src/plugins/builtin/news/wire/news/pop-out.tsx +158 -0
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +64 -19
- package/src/plugins/builtin/openfda/client.ts +300 -0
- package/src/plugins/builtin/openfda/index.tsx +71 -0
- package/src/plugins/builtin/openfda/pane.tsx +382 -0
- package/src/plugins/builtin/openfda/types.ts +76 -0
- package/src/plugins/builtin/options/footer.ts +1 -0
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/pane.tsx +0 -1
- package/src/plugins/builtin/options-positioning/index.tsx +4 -2
- package/src/plugins/builtin/options-positioning/pane.tsx +1 -1
- package/src/plugins/builtin/pe-band/client.ts +61 -0
- package/src/plugins/builtin/pe-band/headless.ts +51 -0
- package/src/plugins/builtin/pe-band/index.tsx +20 -0
- package/src/plugins/builtin/pe-band/model.ts +267 -0
- package/src/plugins/builtin/pe-band/pane.tsx +159 -0
- package/src/plugins/builtin/perps/client.ts +66 -0
- package/src/plugins/builtin/perps/equity-row.tsx +28 -0
- package/src/plugins/builtin/perps/headless.ts +34 -0
- package/src/plugins/builtin/perps/index.tsx +14 -0
- package/src/plugins/builtin/perps/model.ts +58 -0
- package/src/plugins/builtin/perps/pane.tsx +185 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +0 -1
- package/src/plugins/builtin/portfolio-list/cli/render.ts +177 -87
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +6 -20
- package/src/plugins/builtin/portfolio-list/command-bar.ts +6 -2
- package/src/plugins/builtin/portfolio-list/headless.ts +237 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +2 -0
- package/src/plugins/builtin/portfolio-list/mutations.ts +70 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +17 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +88 -5
- package/src/plugins/builtin/portfolio-list/pane/remove-ticker.ts +85 -0
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +18 -12
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +6 -0
- package/src/plugins/builtin/power/client.ts +100 -0
- package/src/plugins/builtin/power/detail.tsx +82 -0
- package/src/plugins/builtin/power/evidence.ts +56 -0
- package/src/plugins/builtin/power/generation.tsx +37 -0
- package/src/plugins/builtin/power/headless.ts +43 -0
- package/src/plugins/builtin/power/index.tsx +16 -0
- package/src/plugins/builtin/power/model.ts +89 -0
- package/src/plugins/builtin/power/pane.tsx +209 -0
- package/src/plugins/builtin/power/query.ts +25 -0
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -3
- package/src/plugins/builtin/research/analyst-pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +13 -4
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +11 -9
- package/src/plugins/builtin/research-search/pane.tsx +21 -7
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +1 -1
- package/src/plugins/builtin/reverse-dcf/client.ts +35 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +44 -0
- package/src/plugins/builtin/reverse-dcf/index.tsx +20 -0
- package/src/plugins/builtin/reverse-dcf/model.ts +87 -0
- package/src/plugins/builtin/reverse-dcf/pane.tsx +107 -0
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/scanner/denied.tsx +4 -2
- package/src/plugins/builtin/scanner/feed.ts +1 -0
- package/src/plugins/builtin/scanner/flow-pane.tsx +3 -2
- package/src/plugins/builtin/scanner/hilo-pane.tsx +1 -1
- package/src/plugins/builtin/seasonality/client.ts +4 -1
- package/src/plugins/builtin/sec/command-bar-search.ts +217 -0
- package/src/plugins/builtin/sec/forms.ts +54 -0
- package/src/plugins/builtin/sec/headless.ts +31 -5
- package/src/plugins/builtin/sec/index.tsx +67 -11
- package/src/plugins/builtin/sec/model.ts +35 -5
- package/src/plugins/builtin/sectors/headless.ts +1 -0
- package/src/plugins/builtin/sectors/index.tsx +72 -26
- package/src/plugins/builtin/shared/cloud-upgrade.ts +143 -39
- package/src/plugins/builtin/shared/pro-feature-wall.tsx +8 -4
- package/src/plugins/builtin/shared/research-cells.tsx +107 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +5 -1
- package/src/plugins/builtin/shared/ticker-request.ts +1 -1
- package/src/plugins/builtin/shared/wall-teaser-catalog.ts +80 -0
- package/src/plugins/builtin/shared/wall-teaser.tsx +192 -0
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +43 -0
- package/src/plugins/builtin/short-interest/index.tsx +31 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +70 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +49 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +185 -0
- package/src/plugins/builtin/short-interest/watch-pane.tsx +169 -0
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/client.ts +104 -0
- package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +17 -0
- package/src/plugins/builtin/supply-chain/evidence.ts +88 -0
- package/src/plugins/builtin/supply-chain/flow-layout.ts +133 -0
- package/src/plugins/builtin/supply-chain/flow.tsx +323 -0
- package/src/plugins/builtin/supply-chain/graph-client.ts +83 -0
- package/src/plugins/builtin/supply-chain/graph-evidence.ts +25 -0
- package/src/plugins/builtin/supply-chain/graph-model.ts +45 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +218 -0
- package/src/plugins/builtin/supply-chain/graph.tsx +163 -0
- package/src/plugins/builtin/supply-chain/headless.ts +105 -0
- package/src/plugins/builtin/supply-chain/index.tsx +17 -0
- package/src/plugins/builtin/supply-chain/model.ts +145 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +276 -0
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +96 -0
- package/src/plugins/builtin/supply-chain/trust.ts +34 -0
- package/src/plugins/builtin/themes/client.ts +39 -0
- package/src/plugins/builtin/themes/headless.ts +38 -0
- package/src/plugins/builtin/themes/model.ts +92 -0
- package/src/plugins/builtin/themes/pane.tsx +125 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +6 -15
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +5 -6
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +201 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +327 -0
- package/src/plugins/builtin/ticker-detail/financials/period-end-history.ts +5 -2
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +60 -12
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -2
- package/src/plugins/builtin/ticker-detail/index.tsx +22 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +53 -30
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +112 -47
- package/src/plugins/builtin/ticker-detail/pane.tsx +50 -6
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +21 -42
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +3 -0
- package/src/plugins/builtin/time-sales/pane.tsx +1 -1
- package/src/plugins/builtin/world-indices/indices.ts +1 -0
- package/src/plugins/catalog-browser.ts +40 -0
- package/src/plugins/catalog-manifest.ts +3 -0
- package/src/plugins/catalog-ui.ts +6 -0
- package/src/plugins/current-target.ts +0 -9
- package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
- package/src/renderers/browser/cloud-transport.ts +66 -1
- package/src/renderers/browser/main.tsx +2 -0
- package/src/renderers/dom/data-table/row.tsx +2 -0
- package/src/renderers/dom/desktop/controls.tsx +38 -25
- package/src/renderers/dom/desktop/icons.tsx +8 -0
- package/src/renderers/dom/host/chart-surface.tsx +36 -2
- package/src/renderers/dom/host/focus-scope.ts +11 -1
- package/src/renderers/dom/styles.css +28 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +3 -2
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/http-fetch.ts +2 -0
- package/src/renderers/electrobun/view/main.tsx +3 -1
- package/src/renderers/electrobun/view/rpc-timeout.ts +59 -0
- package/src/renderers/opentui/start.tsx +3 -0
- package/src/shares/api.ts +3 -1
- package/src/sources/gloomberb-cloud/index.ts +47 -13
- package/src/sources/history-result.ts +1 -0
- package/src/sources/history-retention.ts +16 -0
- package/src/sources/provider-router/history.ts +4 -2
- package/src/sources/sec-edgar/identity.ts +36 -0
- package/src/sources/sec-edgar.ts +1 -34
- package/src/state/app/context/index.tsx +8 -0
- package/src/sync/core-contributors.ts +20 -2
- package/src/telemetry/attention-counts.ts +164 -0
- package/src/telemetry/live-config.ts +7 -0
- package/src/test-support/rpc-loopback.ts +7 -3
- package/src/test-support/shell-pane-keys.tsx +34 -0
- package/src/tickers/instrument-kind.ts +12 -6
- package/src/tickers/open-target.ts +1 -1
- package/src/tickers/search/asset-classes.ts +91 -0
- package/src/tickers/search/index.ts +62 -15
- package/src/tickers/search/ranking.ts +22 -3
- package/src/tickers/search/upsert.ts +4 -1
- package/src/time-series/live-bars.ts +8 -3
- package/src/time-series/resolve.ts +224 -17
- package/src/time-series/spec.ts +1 -0
- package/src/time-series/types.ts +9 -1
- package/src/types/config.ts +23 -1
- package/src/types/data-provider.ts +2 -0
- package/src/types/headless.ts +17 -0
- package/src/types/price-history.ts +2 -0
- package/src/ui/host.tsx +6 -0
- package/src/utils/double-escape-close.ts +20 -0
- package/src/utils/exchanges.ts +1 -0
- package/src/utils/html-entities.ts +15 -0
- package/src/utils/http-proxy-response.ts +44 -7
- package/src/utils/plugin-proxy-hosts.json +3 -0
- package/src/utils/price-history.ts +35 -1
- package/src/utils/sec.ts +21 -2
- package/src/utils/text-wrap.ts +13 -8
- package/src/utils/zoned-date-time.ts +67 -0
|
@@ -14,6 +14,8 @@ const STAT_LABEL_WIDTH = 12;
|
|
|
14
14
|
const FUNDAMENTALS_MAX_COLUMN_WIDTH = 40;
|
|
15
15
|
const BOOK_LABEL_WIDTH = 4;
|
|
16
16
|
const RANGE_ENDPOINT_WIDTH = 11;
|
|
17
|
+
/** Shortest track worth drawing; below it the label shortens. */
|
|
18
|
+
const RANGE_MIN_TRACK_WIDTH = 6;
|
|
17
19
|
const POSITION_COLUMN_GAP = 1;
|
|
18
20
|
|
|
19
21
|
interface PositionColumn {
|
|
@@ -77,62 +79,82 @@ function RangeTrack({
|
|
|
77
79
|
);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
/** Cells a range row needs around its track: label, endpoints and the gaps between them. */
|
|
83
|
+
export function rangeRowChrome(labelWidth: number, endpointWidth: number): number {
|
|
84
|
+
return labelWidth + 1 + endpointWidth * 2 + 2;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** The longest endpoint among ranges drawn together, so stacked tracks start and end in one column. */
|
|
88
|
+
export function rangeEndpointWidth(
|
|
89
|
+
values: readonly number[],
|
|
90
|
+
currency: string,
|
|
91
|
+
priceOptions: MarketFormatOptions,
|
|
92
|
+
): number {
|
|
93
|
+
const widths = values.map((value) => displayWidth(formatMarketPriceWithCurrency(value, currency, priceOptions)));
|
|
94
|
+
return Math.min(RANGE_ENDPOINT_WIDTH, Math.max(1, ...widths));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Where the price sits in a range, on one row: the label, the low, a track
|
|
99
|
+
* with a neutral marker and the high. The marker is the position, so no
|
|
100
|
+
* percentage repeats it.
|
|
101
|
+
*/
|
|
80
102
|
export function CompactRangeBar({
|
|
81
103
|
current,
|
|
82
104
|
low,
|
|
83
105
|
high,
|
|
84
106
|
label,
|
|
107
|
+
shortLabel,
|
|
108
|
+
labelWidth,
|
|
109
|
+
endpointWidth,
|
|
85
110
|
width,
|
|
86
111
|
currency,
|
|
87
112
|
priceOptions,
|
|
88
|
-
markerColor,
|
|
89
113
|
}: {
|
|
90
114
|
current: number;
|
|
91
115
|
low: number;
|
|
92
116
|
high: number;
|
|
117
|
+
/** Translated, like `shortLabel`; `labelWidth` is measured from them. */
|
|
93
118
|
label: string;
|
|
119
|
+
/** Used when the full label would leave the track too short. */
|
|
120
|
+
shortLabel?: string;
|
|
121
|
+
/** Shared by ranges drawn together, so their values line up. */
|
|
122
|
+
labelWidth: number;
|
|
123
|
+
endpointWidth: number;
|
|
94
124
|
width: number;
|
|
95
125
|
currency: string;
|
|
96
126
|
/** The quote's live price options, so the endpoints keep the price's decimals. */
|
|
97
127
|
priceOptions: MarketFormatOptions;
|
|
98
|
-
markerColor: string;
|
|
99
128
|
}) {
|
|
100
129
|
const range = high - low;
|
|
101
130
|
if (range <= 0) return null;
|
|
102
131
|
const position = Math.max(0, Math.min(1, (current - low) / range));
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
Math.max(7, Math.floor((width - 8) / 3)),
|
|
107
|
-
);
|
|
132
|
+
const useShortLabel = shortLabel != null && width - rangeRowChrome(labelWidth, endpointWidth) < RANGE_MIN_TRACK_WIDTH;
|
|
133
|
+
const shownLabel = useShortLabel ? shortLabel : label;
|
|
134
|
+
const shownLabelWidth = useShortLabel ? displayWidth(shortLabel) : labelWidth;
|
|
108
135
|
const endpointOptions = { ...priceOptions, maxWidth: endpointWidth };
|
|
109
136
|
const lowText = formatMarketPriceWithCurrency(low, currency, endpointOptions);
|
|
110
137
|
const highText = formatMarketPriceWithCurrency(high, currency, endpointOptions);
|
|
111
|
-
const barWidth = Math.max(
|
|
138
|
+
const barWidth = Math.max(1, width - rangeRowChrome(shownLabelWidth, endpointWidth));
|
|
112
139
|
const markerIndex = Math.max(0, Math.min(barWidth - 1, Math.round(position * (barWidth - 1))));
|
|
113
|
-
const labelWidth = Math.max(0, width - displayWidth(pctLabel));
|
|
114
140
|
|
|
115
141
|
return (
|
|
116
|
-
<Box flexDirection="
|
|
117
|
-
<Box
|
|
118
|
-
<
|
|
119
|
-
<Text fg={colors.textDim}>{label}</Text>
|
|
120
|
-
</Box>
|
|
121
|
-
<Text fg={markerColor}>{pctLabel}</Text>
|
|
142
|
+
<Box flexDirection="row" height={1} width={width} flexShrink={0} overflow="hidden">
|
|
143
|
+
<Box width={shownLabelWidth + 1} flexShrink={0} overflow="hidden">
|
|
144
|
+
<Text fg={colors.textDim}>{shownLabel}</Text>
|
|
122
145
|
</Box>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
</Box>
|
|
146
|
+
{/* The low sits against the track and the high starts after it, so stacked tracks align. */}
|
|
147
|
+
<Box flexDirection="row" width={endpointWidth} flexShrink={0} justifyContent="flex-end" overflow="hidden">
|
|
148
|
+
<Text fg={colors.text}>{lowText}</Text>
|
|
149
|
+
</Box>
|
|
150
|
+
<RangeTrack
|
|
151
|
+
barWidth={barWidth}
|
|
152
|
+
markerIndex={markerIndex}
|
|
153
|
+
position={position}
|
|
154
|
+
markerColor={colors.textBright}
|
|
155
|
+
/>
|
|
156
|
+
<Box width={endpointWidth} flexShrink={0} overflow="hidden">
|
|
157
|
+
<Text fg={colors.text}>{highText}</Text>
|
|
136
158
|
</Box>
|
|
137
159
|
</Box>
|
|
138
160
|
);
|
|
@@ -175,8 +197,9 @@ export function QuoteBook({ quote, assetCategory, width }: { quote: Quote; asset
|
|
|
175
197
|
|
|
176
198
|
return (
|
|
177
199
|
<Box flexDirection="column" width={width} flexShrink={0}>
|
|
178
|
-
|
|
179
|
-
<BookRow label={t("
|
|
200
|
+
{/* Neutral: a red ask would read as a loss. */}
|
|
201
|
+
<BookRow label={t("Bid")} value={bidText} width={width} valueColor={colors.textBright} />
|
|
202
|
+
<BookRow label={t("Ask")} value={askText} width={width} valueColor={colors.textBright} />
|
|
180
203
|
<BookRow label={t("Spr")} value={spreadText} width={width} valueColor={colors.textDim} />
|
|
181
204
|
</Box>
|
|
182
205
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PerpEquityRow } from "../../perps/equity-row";
|
|
1
2
|
import { useCallback } from "react";
|
|
2
3
|
import type { TickerResearchTabProps } from "../../../../types/plugin";
|
|
3
4
|
import {
|
|
@@ -41,6 +42,7 @@ export function OverviewResearchTab({ width, focused }: TickerResearchTabProps)
|
|
|
41
42
|
financials={financials}
|
|
42
43
|
onOpenChart={paneId && !lockedToOneTab ? openChart : undefined}
|
|
43
44
|
onOpenFunction={openFunction}
|
|
45
|
+
perpetuals={ticker ? <PerpEquityRow symbol={ticker.metadata.ticker} instrumentType={financials?.quote?.instrumentType ?? ticker.metadata.assetCategory} /> : undefined}
|
|
44
46
|
/>
|
|
45
47
|
);
|
|
46
48
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { TrendingSummary } from "../attention/trending";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
1
3
|
import { EmptyState, PaneLinkMenu, SectionHeading, usePaneNoticeFooter } from "../../../components";
|
|
2
4
|
import { CompositeChart, pricePointsToResolvedSeries } from "../../../components/chart/composite";
|
|
3
|
-
import { CompanyLogo } from "../../../components/company-logo";
|
|
5
|
+
import { CompanyLogo, resolveCompanyLogoSrc } from "../../../components/company-logo";
|
|
6
|
+
import { bodyLineInk, FigureText, figureLineInk, useFigureCells } from "../../../components/ui/figure";
|
|
4
7
|
import { PriceReturnStrip } from "../../../components/price-performance";
|
|
5
8
|
import { t } from "../../../i18n";
|
|
6
9
|
import { useFxRatesMap } from "../../../market-data/hooks";
|
|
@@ -13,17 +16,33 @@ import { colors, priceColor } from "../../../theme/colors";
|
|
|
13
16
|
import { appendLiveQuotePoint, hasUnknownBondHistoryBasis } from "../../../time-series/chart-data";
|
|
14
17
|
import type { TickerFinancials } from "../../../types/financials";
|
|
15
18
|
import type { TickerRecord } from "../../../types/ticker";
|
|
16
|
-
import { Box, ScrollBox, Text,
|
|
17
|
-
import { resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
19
|
+
import { Box, ScrollBox, Text, useUiCapabilities } from "../../../ui";
|
|
20
|
+
import { publicTickerKey, resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
18
21
|
import { convertCurrency, displayWidth, formatPercentRaw, truncateToDisplayWidth } from "../../../utils/format";
|
|
19
22
|
import { zonedDateKey } from "../../../utils/zoned-date-time";
|
|
20
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
CompactRangeBar,
|
|
25
|
+
FundamentalsGrid,
|
|
26
|
+
PositionTable,
|
|
27
|
+
QuoteBook,
|
|
28
|
+
rangeEndpointWidth,
|
|
29
|
+
rangeRowChrome,
|
|
30
|
+
textGridColumns,
|
|
31
|
+
} from "./overview/components";
|
|
21
32
|
import { buildOverviewStats, buildPositionRows, buildProfileFields } from "./overview/model";
|
|
22
33
|
import type { OverviewFunctionLink } from "./overview/types";
|
|
23
34
|
import { describeFundamentalMarketCap } from "../../../utils/market-capitalization";
|
|
24
35
|
import { liveFiftyTwoWeekRange, liveMarketCapitalization } from "../portfolio-list/live-valuation";
|
|
25
36
|
|
|
37
|
+
/** Cells between the Day and 52W ranges when they share a row. */
|
|
38
|
+
const RANGE_PAIR_GAP = 4;
|
|
39
|
+
/** Shortest track that still reads as a range; below it the two ranges stack. */
|
|
40
|
+
const RANGE_INLINE_MIN_TRACK = 10;
|
|
41
|
+
/** Desktop px between the logo and the name and price beside it. */
|
|
42
|
+
const LOGO_GAP_PX = 6;
|
|
43
|
+
|
|
26
44
|
interface OverviewTabProps {
|
|
45
|
+
perpetuals?: ReactNode;
|
|
27
46
|
width?: number;
|
|
28
47
|
focused?: boolean;
|
|
29
48
|
ticker: TickerRecord | null;
|
|
@@ -39,10 +58,11 @@ export function OverviewTab(props: OverviewTabProps) {
|
|
|
39
58
|
return <ResolvedOverviewTab {...props} ticker={props.ticker} />;
|
|
40
59
|
}
|
|
41
60
|
|
|
42
|
-
function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpenChart, onOpenFunction }: OverviewTabProps & { ticker: TickerRecord }) {
|
|
61
|
+
function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpenChart, onOpenFunction, perpetuals }: OverviewTabProps & { ticker: TickerRecord }) {
|
|
43
62
|
const baseCurrency = useAppSelector((state) => state.config.baseCurrency);
|
|
44
63
|
const { width: termWidth } = useViewport();
|
|
45
|
-
const { fractionalViewport = false, nativePaneChrome } = useUiCapabilities();
|
|
64
|
+
const { fractionalViewport = false, nativePaneChrome, cellWidthPx = 8, cellHeightPx = 18, pixelRatio = 1 } = useUiCapabilities();
|
|
65
|
+
const figureCells = useFigureCells();
|
|
46
66
|
|
|
47
67
|
const quote = financials?.quote;
|
|
48
68
|
const fundamentals = financials?.fundamentals;
|
|
@@ -58,7 +78,7 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
58
78
|
capitalization?.currency,
|
|
59
79
|
...ticker.metadata.positions.map((position) => position.currency),
|
|
60
80
|
]);
|
|
61
|
-
const quoteCurrency = quote?.currency
|
|
81
|
+
const quoteCurrency = quote?.currency || ticker.metadata.currency || baseCurrency;
|
|
62
82
|
const toBase = (value: number, fromCurrency: string) =>
|
|
63
83
|
convertCurrency(value, fromCurrency, baseCurrency, exchangeRates);
|
|
64
84
|
const sector = ticker.metadata.sector ?? profile?.sector;
|
|
@@ -114,23 +134,48 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
114
134
|
const quotePriceText = quote ? formatMarketPriceWithCurrency(quote.price, quote.currency, moneyOptions) : "";
|
|
115
135
|
const quoteChangeText = quote ? formatSignedMarketPrice(quote.change, moneyOptions) : "";
|
|
116
136
|
const quotePercentText = quote ? `(${formatPercentRaw(quote.changePercent)})` : "";
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
// The pane title already names the ticker, so the line leads with the company.
|
|
121
|
-
const companyName = ticker.metadata.name || quote?.name || ticker.metadata.ticker;
|
|
137
|
+
// The pane title already names the ticker, so the line leads with the company and drops a name that only repeats it.
|
|
138
|
+
const companyName = [ticker.metadata.name, quote?.name].find((name) => name && name !== ticker.metadata.ticker) ?? "";
|
|
139
|
+
const venueText = listingVenue ? (companyName ? ` (${listingVenue})` : listingVenue) : "";
|
|
122
140
|
const marketStateText = quote?.marketState ? t(marketStateLabel(quote.marketState)) : "";
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
141
|
+
const hasIdentityLine = Boolean(companyName || venueText || marketStateText);
|
|
142
|
+
// The desktop logo is a square from the top of the company name's capitals down to the
|
|
143
|
+
// price's baseline, so its edges meet the text's and the three read as one block. The
|
|
144
|
+
// extended-hours line hangs below, as it comes and goes with the session. Without a
|
|
145
|
+
// price the logo keeps two rows.
|
|
146
|
+
const hasLogo = nativePaneChrome === true
|
|
147
|
+
&& resolveCompanyLogoSrc({ symbol: ticker.metadata.ticker, assetCategory: ticker.metadata.assetCategory }) != null;
|
|
148
|
+
const priceInk = figureLineInk();
|
|
149
|
+
// The top snaps up to a whole px so it never starts below the capitals; the bottom lands
|
|
150
|
+
// on the device pixel nearest the baseline.
|
|
151
|
+
const logoTopPx = quote ? Math.floor(hasIdentityLine ? bodyLineInk(cellHeightPx).capTop : priceInk.capTop) : 0;
|
|
152
|
+
const logoBottomPx = Math.round(((hasIdentityLine ? cellHeightPx : 0) + priceInk.baseline) * pixelRatio) / pixelRatio;
|
|
153
|
+
const logoPx = quote ? logoBottomPx - logoTopPx : cellHeightPx * 2;
|
|
154
|
+
const logoCells = hasLogo ? Math.ceil((logoPx + LOGO_GAP_PX) / cellWidthPx) : 0;
|
|
155
|
+
const quoteTextWidth = Math.max(1, quoteSummaryWidth - logoCells);
|
|
156
|
+
const quoteChangeCells = figureCells(quoteChangeText, "sub") + 1 + figureCells(quotePercentText, "sub");
|
|
157
|
+
const stackQuoteChange = quoteChangeCells > quoteTextWidth;
|
|
158
|
+
const stackQuoteSummary = figureCells(quotePriceText) + 2 + quoteChangeCells > quoteTextWidth;
|
|
159
|
+
const companyNameWidth = Math.max(8, quoteTextWidth
|
|
160
|
+
- displayWidth(venueText)
|
|
161
|
+
- (marketStateText ? displayWidth(marketStateText) + 1 : 0));
|
|
126
162
|
const hasDayRange = quote?.low != null && quote?.high != null && quote.high > quote.low;
|
|
127
163
|
const yearRange = liveFiftyTwoWeekRange(quote);
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
?
|
|
132
|
-
:
|
|
133
|
-
|
|
164
|
+
const dayRangeLabel = t("Day Range");
|
|
165
|
+
const yearRangeLabel = t("52W Range");
|
|
166
|
+
const rangeLabelWidth = Math.max(
|
|
167
|
+
hasDayRange ? displayWidth(dayRangeLabel) : 0,
|
|
168
|
+
yearRange ? displayWidth(yearRangeLabel) : 0,
|
|
169
|
+
);
|
|
170
|
+
// Both ranges share one endpoint width, so stacked tracks start and end in the same column.
|
|
171
|
+
const rangeEndpointCells = rangeEndpointWidth([
|
|
172
|
+
...(hasDayRange ? [quote.low!, quote.high!] : []),
|
|
173
|
+
...(yearRange ? [yearRange.low, yearRange.high] : []),
|
|
174
|
+
], quoteCurrency, moneyOptions);
|
|
175
|
+
const rangeHalfWidth = Math.floor((contentWidth - RANGE_PAIR_GAP) / 2);
|
|
176
|
+
const rangeInline = hasDayRange && yearRange != null
|
|
177
|
+
&& rangeHalfWidth - rangeRowChrome(rangeLabelWidth, rangeEndpointCells) >= RANGE_INLINE_MIN_TRACK;
|
|
178
|
+
const rangeWidth = rangeInline ? rangeHalfWidth : contentWidth;
|
|
134
179
|
const stats = buildOverviewStats({
|
|
135
180
|
quote,
|
|
136
181
|
fundamentals,
|
|
@@ -163,37 +208,49 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
163
208
|
|
|
164
209
|
return (
|
|
165
210
|
<ScrollBox flexGrow={1} flexBasis={0} scrollY focusable={false}>
|
|
166
|
-
<Box
|
|
211
|
+
<Box
|
|
212
|
+
flexDirection="column"
|
|
213
|
+
paddingX={1}
|
|
214
|
+
paddingBottom={1}
|
|
215
|
+
gap={1}
|
|
216
|
+
// On the desktop the header keeps half a row clear of the tab bar's edge.
|
|
217
|
+
style={nativePaneChrome ? { paddingTop: Math.round(cellHeightPx / 2) } : undefined}
|
|
218
|
+
>
|
|
167
219
|
<Box flexDirection={quoteBookInline ? "row" : "column"} gap={quoteBookInline ? 2 : 0} width={contentWidth}>
|
|
168
220
|
<Box flexDirection="row" width={quoteSummaryWidth} flexShrink={0} minWidth={0} overflow="hidden">
|
|
169
221
|
<CompanyLogo
|
|
170
222
|
symbol={ticker.metadata.ticker}
|
|
171
223
|
assetCategory={ticker.metadata.assetCategory}
|
|
172
224
|
name={ticker.metadata.name || quote?.name}
|
|
225
|
+
width={logoPx / cellWidthPx}
|
|
226
|
+
height={logoPx / cellHeightPx}
|
|
227
|
+
style={{ marginTop: logoTopPx, marginRight: LOGO_GAP_PX }}
|
|
173
228
|
/>
|
|
174
229
|
<Box flexDirection="column" flexGrow={1} flexShrink={1} minWidth={0}>
|
|
175
|
-
|
|
176
|
-
<
|
|
177
|
-
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<Text flexShrink={0} fg={colors.textDim}>{
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
230
|
+
{hasIdentityLine && (
|
|
231
|
+
<Box flexDirection="row" minWidth={0} overflow="hidden">
|
|
232
|
+
{companyName && (
|
|
233
|
+
<Text fg={colors.textDim}>{truncateToDisplayWidth(companyName, companyNameWidth)}</Text>
|
|
234
|
+
)}
|
|
235
|
+
{venueText && <Text flexShrink={0} fg={colors.textDim}>{venueText}</Text>}
|
|
236
|
+
{quote?.marketState && (
|
|
237
|
+
<Text flexShrink={0} fg={marketStateColor(quote.marketState)}>
|
|
238
|
+
{companyName || venueText ? " " : ""}{marketStateText}
|
|
239
|
+
</Text>
|
|
240
|
+
)}
|
|
241
|
+
</Box>
|
|
242
|
+
)}
|
|
188
243
|
|
|
189
244
|
{quote && (
|
|
190
|
-
<Box
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
245
|
+
<Box
|
|
246
|
+
flexDirection={stackQuoteSummary ? "column" : "row"}
|
|
247
|
+
gap={stackQuoteSummary ? 0 : 2}
|
|
248
|
+
alignItems={stackQuoteSummary ? undefined : "baseline"}
|
|
249
|
+
>
|
|
250
|
+
<FigureText>{quotePriceText}</FigureText>
|
|
194
251
|
<Box flexDirection={stackQuoteChange ? "column" : "row"} gap={stackQuoteChange ? 0 : 1}>
|
|
195
|
-
<
|
|
196
|
-
<
|
|
252
|
+
<FigureText part="sub" change={quote.change}>{quoteChangeText}</FigureText>
|
|
253
|
+
<FigureText part="sub" change={quote.change}>{quotePercentText}</FigureText>
|
|
197
254
|
</Box>
|
|
198
255
|
</Box>
|
|
199
256
|
)}
|
|
@@ -230,18 +287,22 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
230
287
|
)}
|
|
231
288
|
</Box>
|
|
232
289
|
|
|
233
|
-
{
|
|
234
|
-
|
|
290
|
+
{perpetuals}
|
|
291
|
+
|
|
292
|
+
{(hasDayRange || yearRange) && quote && (
|
|
293
|
+
<Box flexDirection={rangeInline ? "row" : "column"} gap={rangeInline ? RANGE_PAIR_GAP : 0} width={contentWidth}>
|
|
235
294
|
{hasDayRange && (
|
|
236
295
|
<CompactRangeBar
|
|
237
296
|
current={quote.price}
|
|
238
297
|
low={quote.low!}
|
|
239
298
|
high={quote.high!}
|
|
240
|
-
label=
|
|
299
|
+
label={dayRangeLabel}
|
|
300
|
+
shortLabel={t("Day")}
|
|
301
|
+
labelWidth={rangeLabelWidth}
|
|
302
|
+
endpointWidth={rangeEndpointCells}
|
|
241
303
|
width={rangeWidth}
|
|
242
304
|
currency={quoteCurrency}
|
|
243
305
|
priceOptions={moneyOptions}
|
|
244
|
-
markerColor={rangeMarkerColor}
|
|
245
306
|
/>
|
|
246
307
|
)}
|
|
247
308
|
{yearRange && (
|
|
@@ -249,11 +310,13 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
249
310
|
current={quote.price}
|
|
250
311
|
low={yearRange.low}
|
|
251
312
|
high={yearRange.high}
|
|
252
|
-
label=
|
|
313
|
+
label={yearRangeLabel}
|
|
314
|
+
shortLabel={t("52W")}
|
|
315
|
+
labelWidth={rangeLabelWidth}
|
|
316
|
+
endpointWidth={rangeEndpointCells}
|
|
253
317
|
width={rangeWidth}
|
|
254
318
|
currency={quoteCurrency}
|
|
255
319
|
priceOptions={moneyOptions}
|
|
256
|
-
markerColor={rangeMarkerColor}
|
|
257
320
|
/>
|
|
258
321
|
)}
|
|
259
322
|
</Box>
|
|
@@ -316,6 +379,8 @@ function ResolvedOverviewTab({ width, focused = false, ticker, financials, onOpe
|
|
|
316
379
|
</Box>
|
|
317
380
|
)}
|
|
318
381
|
|
|
382
|
+
<TrendingSummary symbol={publicTickerKey(ticker.metadata.ticker, ticker.metadata.exchange)} onOpen={onOpenFunction ? () => onOpenFunction({ name: "Research attention", templateId: "attention-pane" }) : undefined} />
|
|
383
|
+
|
|
319
384
|
{/* Description — last, collapsed */}
|
|
320
385
|
{description && (
|
|
321
386
|
<Box flexDirection="column" width={contentWidth}>
|
|
@@ -31,16 +31,30 @@ import { TICKER_RESEARCH_BUILTIN_TABS } from "./research-tabs";
|
|
|
31
31
|
import { useLiveStreamingSetting } from "../../../state/hooks/live-streaming";
|
|
32
32
|
import { useCloudAccessFooter } from "../shared/cloud-upgrade";
|
|
33
33
|
import { CLOUD_QUOTE_DELAY_MINUTES } from "../../../api-client/plan-access";
|
|
34
|
-
import { parsePublicTickerKey } from "../../../utils/exchanges";
|
|
34
|
+
import { parsePublicTickerKey, publicTickerKey } from "../../../utils/exchanges";
|
|
35
|
+
import { captureAttentionAction } from "../../../telemetry/attention-counts";
|
|
35
36
|
import { tickerHasListingSuffix } from "../../../sources/listing-symbols";
|
|
36
37
|
import { tickerQuoteFooterInfo } from "./quote-footer";
|
|
37
38
|
import { ResearchTabKeysProvider, useResearchTabKeysHost } from "./research-tab-keys";
|
|
38
39
|
import { ResearchTabNavigationProvider } from "./research-tab-navigation";
|
|
40
|
+
import { usePluginAppActions } from "../../../public/react";
|
|
41
|
+
import { resolveTickerInstrumentKind } from "../../../tickers/instrument-kind";
|
|
39
42
|
|
|
40
43
|
const TICKER_RESEARCH_TAB_COMMIT_DELAY_MS = 120;
|
|
41
44
|
/** A tab counts as viewed once it stays open this long, not when h/l passes over it. */
|
|
42
45
|
const TICKER_RESEARCH_TAB_VIEW_DWELL_MS = 2_000;
|
|
43
46
|
|
|
47
|
+
const COMPANY_RESEARCH = [
|
|
48
|
+
{ id: "supply-chain-pane", label: "Supply Chain (SPLC)" },
|
|
49
|
+
{ id: "company-kpis-pane", label: "Company KPIs (KPIS)" },
|
|
50
|
+
{ id: "company-guidance-pane", label: "Company Guidance (GUIDE)" },
|
|
51
|
+
{ id: "credit-documents-pane", label: "Credit Documents (CRDOC)" },
|
|
52
|
+
{ id: "awards-pane", label: "Government Awards (AWARDS)" },
|
|
53
|
+
{ id: "catalysts-pane", label: "Catalysts (CATL)" },
|
|
54
|
+
{ id: "hiring-pane", label: "Hiring Momentum (HIRE)" },
|
|
55
|
+
{ id: "apps-pane", label: "App Attention (APPS)" },
|
|
56
|
+
];
|
|
57
|
+
|
|
44
58
|
function sameStringSet(left: Set<string>, right: Set<string>): boolean {
|
|
45
59
|
if (left.size !== right.size) return false;
|
|
46
60
|
for (const value of left) {
|
|
@@ -100,6 +114,7 @@ function getCollectionName(state: AppState, collectionId: string | null): string
|
|
|
100
114
|
|
|
101
115
|
export function TickerResearchPane({ focused, width, height }: PaneProps) {
|
|
102
116
|
const dispatch = useAppDispatch();
|
|
117
|
+
const { createPaneFromTemplate } = usePluginAppActions();
|
|
103
118
|
const config = usePaneAppConfig();
|
|
104
119
|
const paneInstance = usePaneInstance();
|
|
105
120
|
const { ticker, financials, error: instrumentError } = usePaneTicker();
|
|
@@ -220,15 +235,44 @@ export function TickerResearchPane({ focused, width, height }: PaneProps) {
|
|
|
220
235
|
// those keys while it is open; Esc gives them back to the strip.
|
|
221
236
|
const researchTabKeys = useResearchTabKeysHost();
|
|
222
237
|
const stripFocused = focused && !pluginCaptured && !researchTabKeys.claimed;
|
|
238
|
+
const selectResearchTab = useCallback((tabId: string) => {
|
|
239
|
+
if (ticker && tabId !== resolvedTabId) {
|
|
240
|
+
const action = tabId === "chart" ? "chart" : tabId === "options" ? "option_chain" : null;
|
|
241
|
+
if (action) captureAttentionAction()(publicTickerKey(ticker.metadata.ticker, ticker.metadata.exchange), action);
|
|
242
|
+
}
|
|
243
|
+
setActiveTabId(tabId);
|
|
244
|
+
}, [resolvedTabId, setActiveTabId, ticker]);
|
|
223
245
|
const { strip: tabStrip, rows: tabBarHeight } = usePaneTabs(!paneSettings.hideTabs && ticker ? {
|
|
224
246
|
tabs: tabItems,
|
|
225
247
|
activeValue: resolvedTabId,
|
|
226
|
-
onSelect:
|
|
248
|
+
onSelect: selectResearchTab,
|
|
227
249
|
focused: stripFocused,
|
|
228
250
|
} : null);
|
|
229
251
|
// h/l step one tab at a time; with twenty tabs the pane menu jumps straight to one.
|
|
230
252
|
const dialog = useOptionalDialog();
|
|
231
253
|
const showTabs = !paneSettings.hideTabs && !!ticker;
|
|
254
|
+
const companySymbol = ticker && resolveTickerInstrumentKind(ticker, financials) === "equity"
|
|
255
|
+
? tickerHasListingSuffix(ticker.metadata.ticker) ? ticker.metadata.ticker : publicTickerKey(ticker.metadata.ticker, ticker.metadata.exchange)
|
|
256
|
+
: null;
|
|
257
|
+
usePaneMenuItems("ticker-research:company-research", () => {
|
|
258
|
+
if (!companySymbol || !dialog) return null;
|
|
259
|
+
const choices = COMPANY_RESEARCH.filter((item) => {
|
|
260
|
+
if (!registry) return true;
|
|
261
|
+
const owner = registry.getPaneTemplatePluginId?.(item.id);
|
|
262
|
+
return registry.paneTemplates?.has(item.id) && (!owner || !disabledPlugins.includes(owner));
|
|
263
|
+
});
|
|
264
|
+
if (!choices.length) return null;
|
|
265
|
+
return [{ id: "company-research", label: t("Company Research…"), onSelect: () => {
|
|
266
|
+
void dialog.prompt<string>({
|
|
267
|
+
closeOnClickOutside: true,
|
|
268
|
+
content: (context: PromptContext<string>) => <ChoiceDialog {...context}
|
|
269
|
+
title={tf("Research {symbol}", { symbol: companySymbol })}
|
|
270
|
+
choices={choices.map((item) => ({ ...item, label: t(item.label) }))} />,
|
|
271
|
+
}).then((templateId) => {
|
|
272
|
+
if (templateId && choices.some((item) => item.id === templateId)) createPaneFromTemplate(templateId, { symbol: companySymbol });
|
|
273
|
+
}).catch(() => {});
|
|
274
|
+
} }];
|
|
275
|
+
}, [companySymbol, createPaneFromTemplate, dialog, disabledPlugins, registry, tickerResearchTabsSnapshot]);
|
|
232
276
|
usePaneMenuItems("ticker-research:go-to-tab", () => {
|
|
233
277
|
if (!showTabs || !dialog || tabItems.length < 2) return null;
|
|
234
278
|
return [{
|
|
@@ -246,11 +290,11 @@ export function TickerResearchPane({ focused, width, height }: PaneProps) {
|
|
|
246
290
|
/>
|
|
247
291
|
),
|
|
248
292
|
}).then((tabId) => {
|
|
249
|
-
if (tabId)
|
|
293
|
+
if (tabId) selectResearchTab(tabId);
|
|
250
294
|
}).catch(() => {});
|
|
251
295
|
},
|
|
252
296
|
}];
|
|
253
|
-
}, [dialog, resolvedTabId,
|
|
297
|
+
}, [dialog, resolvedTabId, selectResearchTab, showTabs, tabItems]);
|
|
254
298
|
// Which tabs people stay on. A pane pinned to one tab has no strip; opening
|
|
255
299
|
// it is a function open, counted with those.
|
|
256
300
|
useEffect(() => {
|
|
@@ -265,9 +309,9 @@ export function TickerResearchPane({ focused, width, height }: PaneProps) {
|
|
|
265
309
|
// A figure on one tab can open the tab that explains it (holders, short interest).
|
|
266
310
|
const openResearchTab = useCallback((tabId: string) => {
|
|
267
311
|
if (!visibleTabIds.has(tabId)) return false;
|
|
268
|
-
|
|
312
|
+
selectResearchTab(tabId);
|
|
269
313
|
return true;
|
|
270
|
-
}, [
|
|
314
|
+
}, [selectResearchTab, visibleTabIds]);
|
|
271
315
|
const renderedTabIds = useMemo(() => {
|
|
272
316
|
const next = new Set<string>();
|
|
273
317
|
for (const tabId of mountedTabIds) {
|