gloomberb 0.16.3 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +34 -16
- package/src/api-client/index.ts +12 -0
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +88 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +31 -0
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +57 -1
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/app/global-shortcuts.ts +11 -1
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +18 -1
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +70 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +23 -9
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +12 -4
- package/src/cli/commands/market.ts +359 -99
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +422 -0
- package/src/cli/commands/overview.ts +164 -26
- package/src/cli/commands/search.ts +29 -8
- package/src/cli/commands/system.ts +99 -19
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +62 -30
- package/src/cli/desktop-pane-shot.ts +97 -16
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +7 -4
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/index-roots.ts +51 -0
- package/src/cli/index.ts +9 -6
- package/src/cli/listing-arg.ts +211 -3
- package/src/cli/not-a-ticker.ts +37 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/capabilities.ts +8 -2
- package/src/cli/pane-functions/catalog.ts +13 -2
- package/src/cli/pane-functions/data.ts +36 -5
- package/src/cli/pane-functions/dom.ts +21 -13
- package/src/cli/pane-functions/freshness.ts +205 -26
- package/src/cli/pane-functions/function-help.ts +67 -22
- package/src/cli/pane-functions/headless.ts +5 -4
- package/src/cli/pane-functions/index.ts +3 -0
- package/src/cli/pane-functions/market-session.ts +133 -0
- package/src/cli/pane-functions/options.ts +15 -4
- package/src/cli/pane-functions/report-notices.ts +63 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +4 -6
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +105 -23
- package/src/cli/registry.ts +2 -1
- package/src/cli/result.ts +50 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/components/chart/composite/composite-chart.tsx +43 -4
- package/src/components/chart/composite/legend.tsx +39 -6
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/floating-pane.tsx +6 -2
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +46 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/header.tsx +2 -1
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +1 -1
- package/src/components/layout/shell/drag/index.ts +4 -0
- package/src/components/layout/shell/drag/live.ts +76 -5
- package/src/components/layout/shell/drag/runtime.ts +8 -8
- package/src/components/layout/shell/index.tsx +47 -6
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +28 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +51 -10
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +9 -5
- package/src/components/metric-treemap/heat-surface.tsx +27 -8
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-wizard.tsx +49 -40
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +6 -2
- package/src/components/ui/button.tsx +10 -0
- package/src/components/ui/data-table/index.tsx +38 -0
- package/src/components/ui/data-table/types.ts +8 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/icon.tsx +11 -2
- package/src/components/ui/index.ts +1 -1
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +37 -3
- package/src/i18n/es.ts +14 -1
- package/src/i18n/ja.ts +14 -1
- package/src/i18n/ko.ts +14 -1
- package/src/i18n/zh-cn.ts +14 -1
- package/src/i18n/zh-tw.ts +14 -1
- package/src/layout/desks.ts +1 -2
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/market-data/market/freshness.ts +118 -18
- package/src/market-data/market/status.ts +40 -0
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/quotes/contributions.ts +19 -2
- package/src/market-data/quotes/metadata.ts +16 -0
- package/src/market-data/quotes/screener-live-quotes.ts +56 -5
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -4
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
- package/src/plugins/builtin/analytics/risk-model.ts +37 -8
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +48 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +112 -4
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
- package/src/plugins/builtin/cloud/askg/model.ts +129 -70
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
- package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +360 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/starter-symbols.ts +8 -0
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +666 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +234 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/upgrade-dialog.tsx +26 -2
- package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
- package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +107 -64
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/index.tsx +68 -22
- package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/headless.ts +9 -3
- package/src/plugins/builtin/gpu/model.ts +14 -5
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/headless.ts +6 -1
- package/src/plugins/builtin/holders/pane.tsx +3 -0
- package/src/plugins/builtin/insider/index.tsx +4 -4
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +12 -2
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +22 -10
- package/src/plugins/builtin/iv-history/index.tsx +3 -3
- package/src/plugins/builtin/iv-history/model.ts +61 -13
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +109 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +24 -0
- package/src/plugins/builtin/macro-day/headless.ts +11 -8
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +11 -6
- package/src/plugins/builtin/macro-day/pane.tsx +12 -8
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +94 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +8 -1
- package/src/plugins/builtin/market-movers/model.ts +71 -17
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +161 -12
- package/src/plugins/builtin/options-positioning/headless.ts +4 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +73 -17
- package/src/plugins/builtin/options-scenario/headless.ts +71 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +284 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/equity-row.tsx +8 -5
- package/src/plugins/builtin/perps/model.ts +16 -5
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +344 -32
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +87 -4
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
- package/src/plugins/builtin/portfolio-list/cli/render.ts +87 -18
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
- package/src/plugins/builtin/portfolio-list/headless.ts +38 -7
- package/src/plugins/builtin/realized-vol/headless.ts +3 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/pane.tsx +1 -1
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/shared/command-tab.ts +51 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/report-freshness.ts +50 -2
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/index.tsx +19 -4
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +1 -10
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
- package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +197 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +124 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +1 -1
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +127 -63
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +84 -24
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +5 -0
- package/src/remote/controller.ts +3 -53
- package/src/remote/matching.ts +69 -0
- package/src/remote/schema.ts +1 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/host/box.tsx +1 -1
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +10 -2
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +13 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
- package/src/renderers/electrobun/view/main.tsx +4 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +19 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +4 -1
- package/src/sources/listing-symbols.ts +11 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/cached-routes.ts +8 -4
- package/src/sources/provider-router/financial-routes.ts +11 -5
- package/src/sources/provider-router/financials.ts +42 -15
- package/src/sources/provider-router/history.ts +27 -11
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +4 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/search/index.ts +22 -2
- package/src/tickers/search/ranking.ts +45 -1
- package/src/tickers/search/types.ts +3 -1
- package/src/time-series/resolve.ts +1 -14
- package/src/types/config.ts +61 -1
- package/src/types/headless.ts +11 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +49 -3
- package/src/ui/host.tsx +8 -4
- package/src/ui/index.tsx +2 -0
- package/src/utils/cli-output.ts +14 -1
- package/src/utils/exchanges.ts +13 -0
- package/src/utils/format.ts +2 -1
- package/src/utils/fx-market-hours.ts +34 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +39 -6
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +159 -30
- package/src/utils/sec.ts +38 -34
- package/src/utils/throttled-fetch.ts +51 -22
|
@@ -23,6 +23,21 @@ export const ONBOARDING_DESKTOP = {
|
|
|
23
23
|
buttonHeight: "28px",
|
|
24
24
|
} as const;
|
|
25
25
|
|
|
26
|
+
/** Cells the terminal card spends on its border and padding: what its content does not get. */
|
|
27
|
+
export const TERMINAL_CARD_INSET = { columns: 6, rows: 4 } as const;
|
|
28
|
+
|
|
29
|
+
/** The terminal card's size in cells: what a step asks for, clamped to what the viewport leaves. */
|
|
30
|
+
export function terminalCardSize(viewport: { width: number; height: number }, width: number, height: number) {
|
|
31
|
+
const overlayHeight = Math.max(1, viewport.height - 1);
|
|
32
|
+
const availableWidth = Math.max(1, viewport.width - 4);
|
|
33
|
+
const availableHeight = Math.max(1, overlayHeight - 1);
|
|
34
|
+
return {
|
|
35
|
+
overlayHeight,
|
|
36
|
+
width: Math.min(Math.max(42, Math.min(width, availableWidth)), availableWidth),
|
|
37
|
+
height: Math.min(Math.max(10, Math.min(height, availableHeight)), availableHeight),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
export function OnboardingModal({
|
|
27
42
|
children,
|
|
28
43
|
width = 66,
|
|
@@ -81,11 +96,7 @@ export function OnboardingModal({
|
|
|
81
96
|
);
|
|
82
97
|
}
|
|
83
98
|
|
|
84
|
-
const overlayHeight =
|
|
85
|
-
const availableWidth = Math.max(1, viewport.width - 4);
|
|
86
|
-
const availableHeight = Math.max(1, overlayHeight - 1);
|
|
87
|
-
const cardWidth = Math.min(Math.max(42, Math.min(width, availableWidth)), availableWidth);
|
|
88
|
-
const cardHeight = Math.min(Math.max(10, Math.min(height, availableHeight)), availableHeight);
|
|
99
|
+
const { overlayHeight, width: cardWidth, height: cardHeight } = terminalCardSize(viewport, width, height);
|
|
89
100
|
const top = Math.max(0, Math.floor((overlayHeight - cardHeight) / 2));
|
|
90
101
|
const left = Math.max(0, Math.floor((viewport.width - cardWidth) / 2));
|
|
91
102
|
|
|
@@ -216,11 +227,14 @@ export function OnboardingTitle({
|
|
|
216
227
|
titleSuffix,
|
|
217
228
|
description,
|
|
218
229
|
standalone = false,
|
|
230
|
+
compact = false,
|
|
219
231
|
}: {
|
|
220
232
|
step?: string;
|
|
221
233
|
title: string;
|
|
222
234
|
/** No progress header above it, so it sits at the top of the card. */
|
|
223
235
|
standalone?: boolean;
|
|
236
|
+
/** Terminal only: no blank rows around the description, for a card with no rows to spare. */
|
|
237
|
+
compact?: boolean;
|
|
224
238
|
/** Short qualifier after the title, e.g. how many months yearly saves. */
|
|
225
239
|
titleSuffix?: string;
|
|
226
240
|
description?: string;
|
|
@@ -282,8 +296,8 @@ export function OnboardingTitle({
|
|
|
282
296
|
</Box>
|
|
283
297
|
{description ? (
|
|
284
298
|
<>
|
|
285
|
-
<Box height={1} />
|
|
286
|
-
<Box minHeight={2}>
|
|
299
|
+
{compact ? null : <Box height={1} />}
|
|
300
|
+
<Box minHeight={compact ? undefined : 2}>
|
|
287
301
|
<Text fg={colors.textDim} wrapText>{description}</Text>
|
|
288
302
|
</Box>
|
|
289
303
|
</>
|
|
@@ -420,12 +434,15 @@ export function OnboardingActions({ children, hint }: { children: ReactNode; hin
|
|
|
420
434
|
</Box>
|
|
421
435
|
);
|
|
422
436
|
}
|
|
437
|
+
// A button that does not fit beside the one before it wraps under it: the
|
|
438
|
+
// card is narrower than the row in a long language or a narrow terminal.
|
|
423
439
|
return (
|
|
424
440
|
<Box
|
|
425
441
|
flexDirection="row"
|
|
442
|
+
flexWrap="wrap"
|
|
426
443
|
justifyContent="flex-start"
|
|
427
444
|
alignItems="center"
|
|
428
|
-
|
|
445
|
+
columnGap={1}
|
|
429
446
|
>
|
|
430
447
|
{children}
|
|
431
448
|
</Box>
|
|
@@ -531,19 +548,25 @@ export function OnboardingChoiceList({
|
|
|
531
548
|
export function OnboardingFeature({
|
|
532
549
|
title,
|
|
533
550
|
description,
|
|
551
|
+
rows = 2,
|
|
534
552
|
}: {
|
|
535
553
|
title: string;
|
|
536
554
|
description: string;
|
|
555
|
+
/** Terminal rows for the title and the description under it; 1 keeps the title alone. The DOM card sizes to its text. */
|
|
556
|
+
rows?: number;
|
|
537
557
|
}) {
|
|
538
558
|
const colors = useThemeColors();
|
|
539
559
|
const desktop = useUiCapabilities().nativePaneChrome === true;
|
|
540
560
|
if (!desktop) {
|
|
561
|
+
const descriptionRows = Math.max(0, rows - 1);
|
|
541
562
|
return (
|
|
542
|
-
<Box height={
|
|
563
|
+
<Box height={1 + descriptionRows} flexDirection="row" minWidth={0}>
|
|
543
564
|
<Box width={2} height={1}><Text fg={colors.positive}>· </Text></Box>
|
|
544
565
|
<Box flexDirection="column" flexGrow={1} minWidth={0}>
|
|
545
566
|
<Box height={1} overflow="hidden"><Text fg={colors.textBright} attributes={TextAttributes.BOLD}>{title}</Text></Box>
|
|
546
|
-
|
|
567
|
+
{descriptionRows > 0 ? (
|
|
568
|
+
<Box height={descriptionRows} overflow="hidden"><Text fg={colors.textMuted}>{description}</Text></Box>
|
|
569
|
+
) : null}
|
|
547
570
|
</Box>
|
|
548
571
|
</Box>
|
|
549
572
|
);
|
|
@@ -20,8 +20,8 @@ import { t, tf } from "../../i18n";
|
|
|
20
20
|
import { useAppLanguage } from "../../i18n/react";
|
|
21
21
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
22
22
|
import { formatCloudPrice, monthsFreeYearly } from "../../plugins/builtin/account-management/model";
|
|
23
|
-
import { proStepCopy } from "../../plugins/builtin/cloud/upgrade-dialog";
|
|
24
|
-
import { Button, SegmentedControl } from "../ui";
|
|
23
|
+
import { proStepCopy, proStepRealtimeTitle } from "../../plugins/builtin/cloud/upgrade-dialog";
|
|
24
|
+
import { Button, SegmentedControl, terminalButtonColumns } from "../ui";
|
|
25
25
|
import { AccountStep, PortfolioStep } from "./onboarding-steps";
|
|
26
26
|
import {
|
|
27
27
|
ONBOARDING_DESKTOP,
|
|
@@ -32,8 +32,11 @@ import {
|
|
|
32
32
|
OnboardingHeader,
|
|
33
33
|
OnboardingModal,
|
|
34
34
|
OnboardingTitle,
|
|
35
|
+
TERMINAL_CARD_INSET,
|
|
36
|
+
terminalCardSize,
|
|
35
37
|
type OnboardingSectionId,
|
|
36
38
|
} from "./onboarding-frame";
|
|
39
|
+
import { planProStep } from "./pro-step-layout";
|
|
37
40
|
import { useOnboardingAccount } from "./wizard-account";
|
|
38
41
|
import { useOnboardingBrokerSync } from "./wizard-broker-sync";
|
|
39
42
|
import { useOnboardingPositions } from "./wizard-positions";
|
|
@@ -77,7 +80,7 @@ function useOnboardingWizard({ pluginRegistry, importBrokerPositions, onComplete
|
|
|
77
80
|
const keybindings = useKeybindings();
|
|
78
81
|
const dialogOpen = useDialogState((dialog) => dialog.isOpen);
|
|
79
82
|
const commandBarOpen = useAppSelector((state) => state.commandBarOpen);
|
|
80
|
-
const { height: viewportHeight } = useViewport();
|
|
83
|
+
const { width: viewportWidth, height: viewportHeight } = useViewport();
|
|
81
84
|
const dispatch = useAppDispatch();
|
|
82
85
|
const stateRef = useAppStateRef();
|
|
83
86
|
const config = useAppSelector((state) => state.config);
|
|
@@ -195,12 +198,6 @@ function useOnboardingWizard({ pluginRegistry, importBrokerPositions, onComplete
|
|
|
195
198
|
researchOpenedRef.current = progress.tickerSymbol;
|
|
196
199
|
recordResearchActivity("ticker_saved");
|
|
197
200
|
}, [stage, progress.tickerSymbol]);
|
|
198
|
-
const {
|
|
199
|
-
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree,
|
|
200
|
-
} = useOnboardingUpgrade({
|
|
201
|
-
stage, progress, saveProgressInBackground, persistProgress,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
201
|
const movePositionCursor = useCallback((delta: number) => {
|
|
205
202
|
if (positionCursorIndex < 0) return;
|
|
206
203
|
const next = Math.max(0, Math.min(positionCount - 1, positionCursorIndex + delta));
|
|
@@ -240,6 +237,12 @@ function useOnboardingWizard({ pluginRegistry, importBrokerPositions, onComplete
|
|
|
240
237
|
? findPaneInstance(config.layout, focusedPaneId)
|
|
241
238
|
: null;
|
|
242
239
|
const helpFocused = focusedInstance?.paneId === "help";
|
|
240
|
+
const {
|
|
241
|
+
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree, personalTickers,
|
|
242
|
+
} = useOnboardingUpgrade({
|
|
243
|
+
stage, progress, saveProgressInBackground, persistProgress,
|
|
244
|
+
shown: !helpFocused && !dialogOpen && !commandBarOpen,
|
|
245
|
+
});
|
|
243
246
|
|
|
244
247
|
const goToSection = useCallback((section: OnboardingSectionId) => {
|
|
245
248
|
if (finishingRef.current || isBrokerCommitting) return;
|
|
@@ -289,8 +292,9 @@ function useOnboardingWizard({ pluginRegistry, importBrokerPositions, onComplete
|
|
|
289
292
|
chooseBroker, activeBrokerFields, brokerFieldIdx, brokerSelectIdx, setBrokerSelectIdx, brokerValues,
|
|
290
293
|
setBrokerFieldValue, isBrokerSyncing, brokerSyncError, persistenceError, positionCount,
|
|
291
294
|
openBrokerConnect, continueFromPositions, backPortfolio, continuePortfolio, chosenDesks, deskCursor,
|
|
292
|
-
setDeskCursor, setChosenDesks, buildingDesks, finishDesks, account, viewportHeight, continueAccount,
|
|
295
|
+
setDeskCursor, setChosenDesks, buildingDesks, finishDesks, account, viewportWidth, viewportHeight, continueAccount,
|
|
293
296
|
offer, planAccess, pricing, billingInterval, setBillingInterval, continueFree, primaryUpgradeAction,
|
|
297
|
+
personalTickers,
|
|
294
298
|
};
|
|
295
299
|
}
|
|
296
300
|
|
|
@@ -303,8 +307,9 @@ export function OnboardingWizard(props: OnboardingWizardProps) {
|
|
|
303
307
|
chooseBroker, activeBrokerFields, brokerFieldIdx, brokerSelectIdx, setBrokerSelectIdx, brokerValues,
|
|
304
308
|
setBrokerFieldValue, isBrokerSyncing, brokerSyncError, persistenceError, positionCount,
|
|
305
309
|
openBrokerConnect, continueFromPositions, backPortfolio, continuePortfolio, chosenDesks, deskCursor,
|
|
306
|
-
setDeskCursor, setChosenDesks, buildingDesks, finishDesks, account, viewportHeight, continueAccount,
|
|
310
|
+
setDeskCursor, setChosenDesks, buildingDesks, finishDesks, account, viewportWidth, viewportHeight, continueAccount,
|
|
307
311
|
offer, planAccess, pricing, billingInterval, setBillingInterval, continueFree, primaryUpgradeAction,
|
|
312
|
+
personalTickers,
|
|
308
313
|
} = useOnboardingWizard(props);
|
|
309
314
|
|
|
310
315
|
if (helpFocused) {
|
|
@@ -604,6 +609,33 @@ export function OnboardingWizard(props: OnboardingWizardProps) {
|
|
|
604
609
|
const monthsFree = monthsFreeYearly(pricing);
|
|
605
610
|
const yearlyLabel = monthsFree > 0 ? tf("Yearly, {months} months free", { months: monthsFree }) : t("Yearly");
|
|
606
611
|
const priceNote = billingInterval === "year" && monthsFree > 0 ? tf("{months} months free", { months: monthsFree }) : null;
|
|
612
|
+
const proNote = planAccess.hasProAccess
|
|
613
|
+
? t("This account already has real-time Cloud data.")
|
|
614
|
+
: proCopy.note;
|
|
615
|
+
// Ranked: the data itself first, then what reads it.
|
|
616
|
+
const features = [
|
|
617
|
+
{ title: proStepRealtimeTitle(personalTickers), description: t("Free is 15 minutes behind on quotes and 12 hours on news.") },
|
|
618
|
+
{ title: t("MCP server"), description: t("Claude Code, Codex or Cursor call Gloom's research tools.") },
|
|
619
|
+
{ title: t("Ask Gloom"), description: t("Answers cite filings, calls and news.") },
|
|
620
|
+
{ title: t("Earnings calls"), description: t("Transcripts, summaries, guidance and scores.") },
|
|
621
|
+
{ title: t("Equity Diagnostic"), description: t("Full report: red and green flags with evidence.") },
|
|
622
|
+
{ title: t("Search, theses and flow"), description: t("Instant search with alerts, thesis monitoring, options flow, hiring and compensation data.") },
|
|
623
|
+
];
|
|
624
|
+
// The terminal card is clamped to the viewport, so the list gets the rows
|
|
625
|
+
// the card leaves it. The DOM card grows with its content instead.
|
|
626
|
+
const card = terminalCardSize({ width: viewportWidth, height: viewportHeight }, 70, 28);
|
|
627
|
+
const layout = desktop ? null : planProStep({
|
|
628
|
+
rows: card.height - TERMINAL_CARD_INSET.rows,
|
|
629
|
+
columns: card.width - TERMINAL_CARD_INSET.columns,
|
|
630
|
+
note: proNote,
|
|
631
|
+
interval: !planAccess.hasProAccess,
|
|
632
|
+
error: persistenceError,
|
|
633
|
+
actions: [
|
|
634
|
+
...(planAccess.hasProAccess ? [] : [terminalButtonColumns({ label: "Keep Free for now", shortcut: KEEP_FREE_KEY })]),
|
|
635
|
+
terminalButtonColumns({ label: primaryLabel }),
|
|
636
|
+
],
|
|
637
|
+
descriptions: features.map((feature) => feature.description),
|
|
638
|
+
});
|
|
607
639
|
return (
|
|
608
640
|
<OnboardingModal width={70} height={28}>
|
|
609
641
|
<OnboardingHeader
|
|
@@ -618,12 +650,11 @@ export function OnboardingWizard(props: OnboardingWizardProps) {
|
|
|
618
650
|
step={desktop ? undefined : t("GLOOM CLOUD PRO")}
|
|
619
651
|
title={planAccess.hasProAccess ? t("Pro is active") : price}
|
|
620
652
|
titleSuffix={!planAccess.hasProAccess && priceNote ? priceNote : undefined}
|
|
621
|
-
description={
|
|
622
|
-
|
|
623
|
-
: proCopy.note}
|
|
653
|
+
description={proNote}
|
|
654
|
+
compact={layout?.compact}
|
|
624
655
|
/>
|
|
625
656
|
{!planAccess.hasProAccess ? (
|
|
626
|
-
<Box flexDirection="row" style={desktop ? { marginTop: 12 } : undefined} paddingTop={desktop ? undefined : 1}>
|
|
657
|
+
<Box flexDirection="row" style={desktop ? { marginTop: 12 } : undefined} paddingTop={desktop || layout?.compact ? undefined : 1}>
|
|
627
658
|
<SegmentedControl
|
|
628
659
|
options={[
|
|
629
660
|
{ label: t("Monthly"), value: "month" },
|
|
@@ -636,32 +667,10 @@ export function OnboardingWizard(props: OnboardingWizardProps) {
|
|
|
636
667
|
/>
|
|
637
668
|
</Box>
|
|
638
669
|
) : null}
|
|
639
|
-
{/* Ranked: the data itself first, then what reads it. */}
|
|
640
670
|
<Box flexDirection="column" style={desktop ? { marginTop: ONBOARDING_DESKTOP.afterHeader, gap: 10 } : undefined}>
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
/>
|
|
645
|
-
<OnboardingFeature
|
|
646
|
-
title={t("MCP server")}
|
|
647
|
-
description={t("Claude Code, Codex or Cursor call Gloom's research tools.")}
|
|
648
|
-
/>
|
|
649
|
-
<OnboardingFeature
|
|
650
|
-
title={t("Ask Gloom")}
|
|
651
|
-
description={t("Answers cite filings, calls and news.")}
|
|
652
|
-
/>
|
|
653
|
-
<OnboardingFeature
|
|
654
|
-
title={t("Earnings calls")}
|
|
655
|
-
description={t("Transcripts, summaries, guidance and scores.")}
|
|
656
|
-
/>
|
|
657
|
-
<OnboardingFeature
|
|
658
|
-
title={t("Equity Diagnostic")}
|
|
659
|
-
description={t("Full report: red and green flags with evidence.")}
|
|
660
|
-
/>
|
|
661
|
-
<OnboardingFeature
|
|
662
|
-
title={t("Search, theses and flow")}
|
|
663
|
-
description={t("Instant search with alerts, thesis monitoring, options flow, hiring and compensation data.")}
|
|
664
|
-
/>
|
|
671
|
+
{features.map((feature, index) => layout?.featureRows[index] === 0 ? null : (
|
|
672
|
+
<OnboardingFeature key={index} {...feature} rows={layout?.featureRows[index]} />
|
|
673
|
+
))}
|
|
665
674
|
</Box>
|
|
666
675
|
{persistenceError ? (
|
|
667
676
|
<Text fg={colors.negative} wrapText style={desktop ? { marginTop: 10 } : undefined}>
|
|
@@ -4,6 +4,7 @@ import { useThemeColors } from "../../../theme/theme-context";
|
|
|
4
4
|
import { blendHex, priceColor } from "../../../theme/colors";
|
|
5
5
|
import { t, tf } from "../../../i18n";
|
|
6
6
|
import { formatMarketPrice } from "../../../market-data/market/format";
|
|
7
|
+
import { getRegularSessionDisplay } from "../../../market-data/market/status";
|
|
7
8
|
import { formatPercentRaw } from "../../../utils/format";
|
|
8
9
|
import { Button, NumberField, TextField } from "../../ui";
|
|
9
10
|
import { ONBOARDING_DESKTOP } from "../onboarding-frame";
|
|
@@ -47,8 +48,10 @@ function PreviewLine({ preview, error }: Pick<OnboardingPositionsState, "preview
|
|
|
47
48
|
return <Text fg={colors.textDim}>{tf("{query} checking...", { query: preview.query })}</Text>;
|
|
48
49
|
}
|
|
49
50
|
if (preview.status === "missing") return <Text fg={colors.textMuted}>{preview.message}</Text>;
|
|
50
|
-
|
|
51
|
-
const
|
|
51
|
+
// The regular session's last and move, as `ticker` headlines them: after the close, that close.
|
|
52
|
+
const headline = getRegularSessionDisplay(preview.quote);
|
|
53
|
+
const price = headline?.price;
|
|
54
|
+
const change = headline?.changePercent;
|
|
52
55
|
return (
|
|
53
56
|
<Box flexDirection="row" minWidth={0} overflow="hidden">
|
|
54
57
|
<Text fg={colors.text} attributes={TextAttributes.BOLD}>{preview.symbol}</Text>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { wrapTextLines } from "../../utils/text-wrap";
|
|
2
|
+
|
|
3
|
+
function wrappedRows(text: string, width: number): number {
|
|
4
|
+
return Math.max(1, wrapTextLines(text, Math.max(1, width)).length);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Rows for each feature of a ranked list in `budget` rows: a title and its
|
|
9
|
+
* wrapped description (`1 + descriptionRows[i]`), a title alone (1) or nothing
|
|
10
|
+
* (0). As many features from the top keep their description as leave a row for
|
|
11
|
+
* every one below them; when not even the titles fit, the lowest ranked drop.
|
|
12
|
+
*/
|
|
13
|
+
export function planProFeatureRows(budget: number, descriptionRows: readonly number[]): number[] {
|
|
14
|
+
const count = descriptionRows.length;
|
|
15
|
+
if (budget < count) return descriptionRows.map((_, index) => (index < budget ? 1 : 0));
|
|
16
|
+
let spare = budget - count;
|
|
17
|
+
const rows = descriptionRows.map(() => 1);
|
|
18
|
+
for (const [index, description] of descriptionRows.entries()) {
|
|
19
|
+
if (description > spare) break;
|
|
20
|
+
spare -= description;
|
|
21
|
+
rows[index] = 1 + description;
|
|
22
|
+
}
|
|
23
|
+
return rows;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Rows a row of buttons takes in `columns` cells when it wraps to the next row
|
|
28
|
+
* instead of running off the card: `widths` are the buttons' cells in order,
|
|
29
|
+
* with one cell between neighbours on a row. A button wider than the row still
|
|
30
|
+
* gets a row of its own.
|
|
31
|
+
*/
|
|
32
|
+
export function wrappedActionRows(widths: readonly number[], columns: number): number {
|
|
33
|
+
let rows = 1;
|
|
34
|
+
let used = 0;
|
|
35
|
+
for (const width of widths) {
|
|
36
|
+
if (used > 0 && used + 1 + width > columns) {
|
|
37
|
+
rows += 1;
|
|
38
|
+
used = width;
|
|
39
|
+
} else {
|
|
40
|
+
used += (used > 0 ? 1 : 0) + width;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return rows;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ProStepLayoutInput {
|
|
47
|
+
/** Rows and columns inside the card's border and padding. */
|
|
48
|
+
rows: number;
|
|
49
|
+
columns: number;
|
|
50
|
+
/** The line under the price. */
|
|
51
|
+
note: string;
|
|
52
|
+
/** The Monthly/Yearly control is shown. */
|
|
53
|
+
interval: boolean;
|
|
54
|
+
/** A persistence error line above the actions, or null. */
|
|
55
|
+
error: string | null;
|
|
56
|
+
/** Cells each action button takes; a row that does not fit wraps and costs a row more. */
|
|
57
|
+
actions: readonly number[];
|
|
58
|
+
/** Feature descriptions, ranked. */
|
|
59
|
+
descriptions: readonly string[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* What the terminal Pro step shows in a card of a given size: the whole list
|
|
64
|
+
* with the step's usual blank rows while it fits, otherwise those rows go
|
|
65
|
+
* (`compact`) and the list degrades as `planProFeatureRows` says. The actions
|
|
66
|
+
* are never part of the budget the list gets: they keep the rows they need,
|
|
67
|
+
* more than one when the buttons wrap.
|
|
68
|
+
*/
|
|
69
|
+
export function planProStep(input: ProStepLayoutInput): { compact: boolean; featureRows: number[] } {
|
|
70
|
+
const { rows, columns, note, interval, error, actions, descriptions } = input;
|
|
71
|
+
const noteRows = wrappedRows(note, columns);
|
|
72
|
+
const errorRows = error ? wrappedRows(error, columns) : 0;
|
|
73
|
+
const actionRows = wrappedActionRows(actions, columns);
|
|
74
|
+
const descriptionRows = descriptions.map((description) => wrappedRows(description, columns - 2));
|
|
75
|
+
// Header, step and title lines, the note, the control, the error, the actions.
|
|
76
|
+
const around = (compact: boolean) => 1 + 2
|
|
77
|
+
+ (compact ? noteRows : 1 + Math.max(2, noteRows))
|
|
78
|
+
+ (interval ? (compact ? 1 : 2) : 0)
|
|
79
|
+
+ errorRows + actionRows;
|
|
80
|
+
|
|
81
|
+
const roomy = planProFeatureRows(rows - around(false), descriptionRows);
|
|
82
|
+
if (roomy.every((featureRows, index) => featureRows === 1 + descriptionRows[index]!)) {
|
|
83
|
+
return { compact: false, featureRows: roomy };
|
|
84
|
+
}
|
|
85
|
+
return { compact: true, featureRows: planProFeatureRows(rows - around(true), descriptionRows) };
|
|
86
|
+
}
|
|
@@ -6,12 +6,14 @@ import { chatController } from "../../plugins/builtin/chat/controller";
|
|
|
6
6
|
import type { CloudBillingInterval } from "../../plugins/builtin/account-management/model";
|
|
7
7
|
import { loadUpgradeOffer, type UpgradeOffer } from "../../plugins/builtin/cloud/upgrade-dialog";
|
|
8
8
|
import { useCloudUpgradeAction } from "../../plugins/builtin/shared/cloud-upgrade";
|
|
9
|
+
import { useUpgradePersonalization } from "../../plugins/builtin/cloud/upgrade-personalization";
|
|
9
10
|
import { usePlanAccess } from "../../api-client/plan-access";
|
|
10
11
|
|
|
11
12
|
export function useOnboardingUpgrade({
|
|
12
|
-
stage, progress, saveProgressInBackground, persistProgress,
|
|
13
|
+
stage, progress, saveProgressInBackground, persistProgress, shown,
|
|
13
14
|
}: {
|
|
14
15
|
stage: OnboardingStage;
|
|
16
|
+
shown: boolean;
|
|
15
17
|
progress: OnboardingProgress;
|
|
16
18
|
saveProgressInBackground: (patch: Partial<OnboardingProgress> & Pick<OnboardingProgress, "stage">, baseConfig?: AppConfig | undefined) => void;
|
|
17
19
|
persistProgress: (patch: Partial<OnboardingProgress> & Pick<OnboardingProgress, "stage">, baseConfig?: AppConfig | undefined) => Promise<AppConfig>;
|
|
@@ -23,6 +25,8 @@ export function useOnboardingUpgrade({
|
|
|
23
25
|
const appActive = useAppActive();
|
|
24
26
|
const planAccess = usePlanAccess();
|
|
25
27
|
const openUpgrade = useCloudUpgradeAction("onboarding-pro");
|
|
28
|
+
// The step lists the features from its first frame, so that is when it is shown.
|
|
29
|
+
const personalTickers = useUpgradePersonalization("onboarding-pro", shown && stage === "upgrade");
|
|
26
30
|
// The price and whether this account still has its trial, asked again for
|
|
27
31
|
// whichever account reaches the step.
|
|
28
32
|
const accountId = planAccess.signedIn ? apiClient.getCurrentUser()?.id ?? null : null;
|
|
@@ -78,6 +82,6 @@ export function useOnboardingUpgrade({
|
|
|
78
82
|
}, [progress.accountStatus, saveProgressInBackground]);
|
|
79
83
|
|
|
80
84
|
return {
|
|
81
|
-
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree,
|
|
85
|
+
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree, personalTickers,
|
|
82
86
|
};
|
|
83
87
|
}
|
|
@@ -4,6 +4,7 @@ import { type ComponentType, type ReactNode } from "react";
|
|
|
4
4
|
import type { ThemeColors } from "../../theme/colors";
|
|
5
5
|
import { useThemeColors } from "../../theme/theme-context";
|
|
6
6
|
import { t } from "../../i18n";
|
|
7
|
+
import { displayWidth } from "../../utils/format";
|
|
7
8
|
import { useRemoteUiNode, useRemoteUiScope } from "../../remote/semantic-tree";
|
|
8
9
|
import { useScopedButtonAction } from "./action-scope";
|
|
9
10
|
|
|
@@ -66,6 +67,15 @@ function resolveButtonColors(variant: ButtonVariant, active: boolean, disabled:
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Terminal cells a button takes: the padded label, then its key. For a row that
|
|
72
|
+
* has to know whether its buttons fit before it lays them out.
|
|
73
|
+
*/
|
|
74
|
+
export function terminalButtonColumns({ label, displayLabel, shortcut, compact = false }: Pick<ButtonProps, "label" | "displayLabel" | "shortcut" | "compact">): number {
|
|
75
|
+
const text = displayLabel ?? t(label);
|
|
76
|
+
return displayWidth(compact ? text : ` ${text} `) + (shortcut ? 1 + displayWidth(shortcut) : 0);
|
|
77
|
+
}
|
|
78
|
+
|
|
69
79
|
export function Button({
|
|
70
80
|
label: rawLabel,
|
|
71
81
|
displayLabel,
|
|
@@ -27,6 +27,8 @@ export function DataTable<T, C extends DataTableColumn = DataTableColumn>(
|
|
|
27
27
|
const renderer = useRendererHost();
|
|
28
28
|
const propsRef = useRef(props);
|
|
29
29
|
propsRef.current = props;
|
|
30
|
+
// The semantic snapshot can be taken every frame; the rows are rebuilt only when what they are drawn from changes.
|
|
31
|
+
const reportedRowsRef = useRef<{ source: readonly unknown[]; rows: ReturnType<typeof reportedRows> } | null>(null);
|
|
30
32
|
|
|
31
33
|
useEffect(() => {
|
|
32
34
|
if (!paneId || !renderer.saveTextFile) return;
|
|
@@ -90,6 +92,7 @@ export function DataTable<T, C extends DataTableColumn = DataTableColumn>(
|
|
|
90
92
|
columns: props.columns.map((column) => ({ id: column.id, label: column.label })),
|
|
91
93
|
rowCount: props.items.length,
|
|
92
94
|
selectedId: firstSelectedId(props),
|
|
95
|
+
...(props.reportEveryRow ? { rows: cachedReportedRows(props, reportedRowsRef) } : {}),
|
|
93
96
|
}),
|
|
94
97
|
});
|
|
95
98
|
// Header labels read the same in every table whatever case a pane wrote
|
|
@@ -119,6 +122,41 @@ function resolveTableIndex<T, C extends DataTableColumn>(
|
|
|
119
122
|
return resolveRemoteItemIndex(input, props.items, { id: key, key });
|
|
120
123
|
}
|
|
121
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Every row as a report reads it: the key, whether it is selected and each
|
|
127
|
+
* column's text, the same text the cells draw. Captured with the semantic
|
|
128
|
+
* snapshot, so a row scrolled out of the viewport still reaches the report.
|
|
129
|
+
*/
|
|
130
|
+
function reportedRows<T, C extends DataTableColumn>(props: DataTableProps<T, C>) {
|
|
131
|
+
const normalize = (text: string) => text.replace(/\s+/g, " ").trim();
|
|
132
|
+
return props.items.map((item, index) => {
|
|
133
|
+
const selected = props.isSelected(item, index);
|
|
134
|
+
const section = props.renderSectionHeader?.(item, index);
|
|
135
|
+
const cells = section
|
|
136
|
+
? [{ columnLabel: "Row", text: normalize(section.text) }]
|
|
137
|
+
: props.columns.map((column) => ({
|
|
138
|
+
columnId: column.id,
|
|
139
|
+
columnLabel: column.label,
|
|
140
|
+
text: normalize(props.renderCell(item, column, index, { selected }).text),
|
|
141
|
+
}));
|
|
142
|
+
return { key: props.getItemKey(item, index), selected, cells: cells.filter((cell) => cell.text.length > 0) };
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function cachedReportedRows<T, C extends DataTableColumn>(
|
|
147
|
+
props: DataTableProps<T, C>,
|
|
148
|
+
cache: { current: { source: readonly unknown[]; rows: ReturnType<typeof reportedRows> } | null },
|
|
149
|
+
) {
|
|
150
|
+
const source = [props.items, props.columns, props.renderCell, props.isSelected, props.renderSectionHeader];
|
|
151
|
+
const cached = cache.current;
|
|
152
|
+
if (cached && cached.source.length === source.length && cached.source.every((value, index) => value === source[index])) {
|
|
153
|
+
return cached.rows;
|
|
154
|
+
}
|
|
155
|
+
const rows = reportedRows(props);
|
|
156
|
+
cache.current = { source, rows };
|
|
157
|
+
return rows;
|
|
158
|
+
}
|
|
159
|
+
|
|
122
160
|
function firstSelectedId<T, C extends DataTableColumn>(props: DataTableProps<T, C>): string | null {
|
|
123
161
|
const index = props.items.findIndex((item, itemIndex) => props.isSelected(item, itemIndex));
|
|
124
162
|
const item = props.items[index];
|
|
@@ -60,7 +60,8 @@ export interface DataTableSectionHeader {
|
|
|
60
60
|
expanded?: boolean;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
/** Where `scrollToIndex` puts its row: the nearest edge, the middle, or the top of the viewport. */
|
|
64
|
+
export type DataTableScrollAlign = "nearest" | "center" | "start";
|
|
64
65
|
|
|
65
66
|
interface DataTableRowState {
|
|
66
67
|
selected: boolean;
|
|
@@ -146,6 +147,12 @@ export interface DataTableProps<
|
|
|
146
147
|
freezeFirstColumn?: boolean;
|
|
147
148
|
/** Append export-only source records after the displayed table. */
|
|
148
149
|
getExportMetadata?: () => readonly (readonly unknown[])[];
|
|
150
|
+
/**
|
|
151
|
+
* A rendered-view report (`gloomberb fn`) reads every row, not only those
|
|
152
|
+
* the viewport shows. For a bounded table a reader needs whole, such as an
|
|
153
|
+
* option chain's strike window; leave it off for long or paged lists.
|
|
154
|
+
*/
|
|
155
|
+
reportEveryRow?: boolean;
|
|
149
156
|
scrollToIndex?: number | null;
|
|
150
157
|
scrollToIndexAlign?: DataTableScrollAlign;
|
|
151
158
|
scrollToIndexVersion?: number;
|
|
@@ -36,6 +36,8 @@ export function resolveDataTableScrollTop(
|
|
|
36
36
|
let nextTop = currentTop;
|
|
37
37
|
if (align === "center") {
|
|
38
38
|
nextTop = targetIndex - Math.floor(visibleHeight / 2);
|
|
39
|
+
} else if (align === "start") {
|
|
40
|
+
nextTop = targetIndex;
|
|
39
41
|
} else if (targetIndex < currentTop) {
|
|
40
42
|
nextTop = targetIndex;
|
|
41
43
|
} else if (targetIndex >= currentTop + visibleHeight) {
|
|
@@ -27,7 +27,9 @@ export type IconName =
|
|
|
27
27
|
| "sort-up"
|
|
28
28
|
| "sort-down"
|
|
29
29
|
| "grip"
|
|
30
|
-
| "image"
|
|
30
|
+
| "image"
|
|
31
|
+
| "thumbs-up"
|
|
32
|
+
| "thumbs-down";
|
|
31
33
|
|
|
32
34
|
/** Terminal glyph for each icon; the desktop host draws SVG. */
|
|
33
35
|
export const ICON_GLYPHS: Record<IconName, string> = {
|
|
@@ -54,6 +56,10 @@ export const ICON_GLYPHS: Record<IconName, string> = {
|
|
|
54
56
|
"sort-down": "▼",
|
|
55
57
|
grip: "::",
|
|
56
58
|
image: "▣",
|
|
59
|
+
// Votes rather than emoji: an emoji keeps its own colours, so it could not
|
|
60
|
+
// show which thumb is chosen.
|
|
61
|
+
"thumbs-up": "+1",
|
|
62
|
+
"thumbs-down": "-1",
|
|
57
63
|
};
|
|
58
64
|
|
|
59
65
|
export interface IconProps {
|
|
@@ -160,7 +166,10 @@ export function IconButton({
|
|
|
160
166
|
if (!disabled) onPress?.(event);
|
|
161
167
|
}}
|
|
162
168
|
>
|
|
163
|
-
|
|
169
|
+
{/* Pressed takes the colour the desktop and the terminal pane header give an active toggle. */}
|
|
170
|
+
<Text fg={disabled ? colors.textMuted : color ?? (pressed ? colors.warning : colors.textDim)} selectable={false}>
|
|
171
|
+
{` ${ICON_GLYPHS[icon]} `}
|
|
172
|
+
</Text>
|
|
164
173
|
</Box>
|
|
165
174
|
);
|
|
166
175
|
}
|
|
@@ -5,7 +5,7 @@ export type { ListViewItem, ListViewProps, ListRowState } from "./list-view";
|
|
|
5
5
|
export { DataTable } from "./data-table";
|
|
6
6
|
export type { DataTableCell, DataTableColumn, DataTableProps, DataTableVisibleRange } from "./data-table";
|
|
7
7
|
|
|
8
|
-
export { Button } from "./button";
|
|
8
|
+
export { Button, terminalButtonColumns } from "./button";
|
|
9
9
|
export { Icon, IconButton, ICON_GLYPHS } from "./icon";
|
|
10
10
|
export type { IconButtonPressEvent, IconButtonProps, IconName, IconProps } from "./icon";
|
|
11
11
|
export { ActionRow } from "./action-row";
|
|
@@ -280,7 +280,7 @@ export function registerGloomCloudConnectionSources(health: ConnectionHealthRegi
|
|
|
280
280
|
id: GLOOM_CLOUD_FRED_CONNECTION_ID,
|
|
281
281
|
name: "Gloom / FRED",
|
|
282
282
|
kind: "api",
|
|
283
|
-
ownerId: "macro",
|
|
283
|
+
ownerId: "rates-macro",
|
|
284
284
|
priority: 2,
|
|
285
285
|
detail: "api.gloom.sh/cloud/econ/series",
|
|
286
286
|
}),
|