gloomberb 0.18.4 → 0.19.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 +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +169 -5
- package/src/account/auth-model.ts +7 -3
- package/src/api-client/auth.ts +9 -4
- package/src/api-client/catalysts.ts +2 -1
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +31 -6
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/index.ts +171 -11
- package/src/api-client/live-scan.ts +91 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +13 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/request.ts +222 -41
- package/src/api-client/research-activity.ts +6 -12
- package/src/api-client/types.ts +74 -0
- package/src/app/keybindings/index.ts +3 -0
- package/src/app/keybindings/labels.ts +18 -1
- package/src/app/keybindings/resolve.ts +14 -0
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +42 -27
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +1 -1
- package/src/architecture/pane-tabs-allowlist.json +3 -0
- package/src/architecture/ttl-caches-allowlist.json +19 -0
- package/src/brokers/sync-broker-instance.ts +2 -8
- package/src/capabilities/chart-series.ts +1 -1
- package/src/cli/commands/crypto-hints.ts +40 -24
- package/src/cli/commands/fred-series.ts +5 -0
- package/src/cli/commands/keybindings.ts +23 -0
- package/src/cli/commands/market.ts +138 -46
- package/src/cli/commands/options-chain.ts +107 -10
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +176 -39
- package/src/cli/commands/search.ts +39 -3
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +57 -35
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +10 -2
- package/src/cli/export-source.ts +29 -1
- package/src/cli/glossary.ts +73 -1
- package/src/cli/history-rows.ts +87 -16
- package/src/cli/index.ts +2 -0
- package/src/cli/known-gaps.ts +5 -2
- package/src/cli/listing-arg.ts +195 -56
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +3 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +111 -16
- package/src/cli/pane-functions/function-help.ts +23 -13
- package/src/cli/pane-functions/headless.ts +56 -12
- package/src/cli/pane-functions/index.ts +58 -16
- package/src/cli/pane-functions/market-session.ts +81 -9
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/report.ts +5 -1
- package/src/cli/pane-functions/resolver.ts +35 -8
- package/src/cli/pane-functions/screenshot-assessment.ts +6 -4
- package/src/cli/pane-functions/screenshot-types.ts +5 -0
- package/src/cli/quote-answer.ts +30 -13
- package/src/cli/report-tables.ts +18 -7
- package/src/cli/restore-plugins.ts +13 -1
- package/src/cli/result.ts +57 -5
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +26 -4
- package/src/components/chart/composite/format.ts +27 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/levels.ts +2 -0
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +61 -5
- package/src/components/chart/composite/range-statistics.ts +62 -0
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +46 -7
- package/src/components/chart/composite/series-axis-tags.tsx +16 -9
- package/src/components/chart/composite/series-cues.ts +14 -0
- package/src/components/chart/composite/text-renderer.ts +9 -2
- package/src/components/chart/composite/tool-catalog.ts +36 -0
- package/src/components/chart/composite/tools.ts +203 -44
- package/src/components/chart/composite/types.ts +4 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +11 -4
- package/src/components/command-bar/assist/inventory.ts +2 -1
- package/src/components/command-bar/commands/direct/index.ts +28 -13
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/panel/prompt-binding.ts +0 -8
- package/src/components/command-bar/workflow/alert.ts +1 -1
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/header.tsx +26 -40
- package/src/components/layout/pane/footer/index.tsx +1 -0
- package/src/components/layout/pane/footer/model.ts +27 -0
- package/src/components/onboarding/onboarding-frame.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +14 -9
- package/src/components/onboarding/wizard-broker-sync.ts +0 -1
- package/src/components/onboarding/wizard-positions.ts +3 -3
- package/src/components/ticker/list-table-view.tsx +4 -1
- package/src/components/ui/choice-dialog.tsx +23 -18
- package/src/components/ui/choice-groups.ts +18 -0
- package/src/components/ui/data-table/opentui/index.tsx +9 -7
- package/src/components/ui/data-table/opentui/model.ts +26 -1
- package/src/components/ui/data-table/types.ts +2 -0
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/list-view.tsx +8 -4
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +1 -0
- package/src/components/ui/select-button.tsx +5 -1
- package/src/components/ui/select-field.tsx +1 -0
- package/src/components/ui/table-layout.ts +8 -5
- package/src/core/app-runtime.ts +2 -0
- package/src/core/app-services.ts +2 -2
- package/src/core/state/app/layout.ts +2 -0
- package/src/core/state/app/state.ts +9 -0
- package/src/core/state/app/types.ts +3 -0
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/saved-copies.ts +55 -16
- package/src/data/ticker-repository.ts +16 -9
- package/src/data/ticker-writes.ts +81 -0
- package/src/data/ttl-cache.ts +165 -0
- package/src/docs/snapshot.json +427 -216
- package/src/i18n/es.ts +19 -3
- package/src/i18n/ja.ts +19 -3
- package/src/i18n/ko.ts +19 -3
- package/src/i18n/zh-cn.ts +19 -3
- package/src/i18n/zh-tw.ts +19 -3
- package/src/market-data/coordinator/financials.ts +10 -2
- package/src/market-data/coordinator/index.ts +3 -1
- package/src/market-data/coordinator/quotes.ts +4 -2
- package/src/market-data/depositary-pair.ts +2 -2
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +48 -7
- package/src/market-data/market/dated-previous-close.ts +203 -0
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/market/futures-week.ts +68 -0
- package/src/market-data/market/status.ts +16 -4
- package/src/market-data/options-alternatives.ts +141 -4
- package/src/market-data/quotes/contributions.ts +20 -2
- package/src/market-data/quotes/resolution.ts +3 -0
- package/src/market-data/selectors.ts +3 -0
- package/src/news/aggregator.ts +113 -9
- package/src/news/cloud-session.ts +21 -0
- package/src/news/hooks.ts +1 -0
- package/src/news/news-model.ts +1 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/notification-log.ts +6 -4
- package/src/plugins/builtin/alerts/alert-engine.ts +25 -2
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +57 -6
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +380 -82
- package/src/plugins/builtin/alerts/command.ts +31 -0
- package/src/plugins/builtin/alerts/constants.ts +1 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +19 -4
- package/src/plugins/builtin/alerts/fired-log.ts +113 -8
- package/src/plugins/builtin/alerts/format.ts +80 -4
- package/src/plugins/builtin/alerts/headless.ts +30 -7
- package/src/plugins/builtin/alerts/history-rows.ts +7 -3
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +135 -22
- package/src/plugins/builtin/alerts/live.ts +3 -3
- package/src/plugins/builtin/alerts/metric-command.ts +134 -0
- package/src/plugins/builtin/alerts/metric-data.ts +111 -0
- package/src/plugins/builtin/alerts/metric-model.ts +324 -0
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +725 -0
- package/src/plugins/builtin/alerts/pane.tsx +90 -39
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +37 -10
- package/src/plugins/builtin/alerts/types.ts +7 -0
- package/src/plugins/builtin/analytics/index.tsx +2 -1
- package/src/plugins/builtin/analytics/risk-client.ts +16 -5
- package/src/plugins/builtin/analytics/risk-fx.ts +70 -15
- package/src/plugins/builtin/analytics/risk-headless.ts +27 -0
- package/src/plugins/builtin/analytics/risk-model.ts +55 -9
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -2
- package/src/plugins/builtin/attention/index.tsx +2 -1
- package/src/plugins/builtin/attention/listing.ts +14 -0
- package/src/plugins/builtin/backtest/headless.ts +10 -5
- package/src/plugins/builtin/backtest/pane.tsx +9 -4
- package/src/plugins/builtin/backtest/presets.ts +29 -3
- package/src/plugins/builtin/broker-manager/index.tsx +10 -5
- package/src/plugins/builtin/broker-manager/model.ts +6 -1
- package/src/plugins/builtin/broker-trading/controller.ts +22 -12
- package/src/plugins/builtin/broker-trading/index.tsx +13 -1
- package/src/plugins/builtin/broker-trading/order-feed.ts +9 -4
- package/src/plugins/builtin/broker-trading/pane.tsx +1 -1
- package/src/plugins/builtin/buildout/cells.tsx +12 -4
- package/src/plugins/builtin/buildout/format.ts +38 -0
- package/src/plugins/builtin/buildout/model/normalizers.ts +36 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +4 -1
- package/src/plugins/builtin/buildout/table-model.ts +23 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +7 -3
- package/src/plugins/builtin/catalysts/model.ts +2 -1
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +6 -1
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +1 -1
- package/src/plugins/builtin/chart-composer/cli-options.ts +9 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +12 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +4 -2
- package/src/plugins/builtin/chart-composer/editor/model.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +7 -5
- package/src/plugins/builtin/chart-composer/formula.ts +71 -18
- package/src/plugins/builtin/chart-composer/headless-schema.ts +21 -4
- package/src/plugins/builtin/chart-composer/headless.ts +19 -3
- package/src/plugins/builtin/chart-composer/index.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +53 -9
- package/src/plugins/builtin/chart-composer/presets.ts +50 -15
- package/src/plugins/builtin/chart-composer/quick-add.tsx +40 -25
- package/src/plugins/builtin/chart-composer/session-history.ts +18 -9
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +40 -26
- package/src/plugins/builtin/chat/content/command-suggestions.ts +93 -0
- package/src/plugins/builtin/chat/content/composer.tsx +13 -6
- package/src/plugins/builtin/chat/content/footer.tsx +6 -3
- package/src/plugins/builtin/chat/content/index.tsx +50 -21
- package/src/plugins/builtin/chat/content/open-targets.ts +14 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +4 -2
- package/src/plugins/builtin/chat/index.tsx +23 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +1 -0
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +23 -0
- package/src/plugins/builtin/chat/message/pane-chip.tsx +50 -20
- package/src/plugins/builtin/chat/pane-links/commands.ts +271 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +12 -3
- package/src/plugins/builtin/chat/pane-links/open.ts +8 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +10 -1
- package/src/plugins/builtin/clinical-trials/model.ts +0 -9
- package/src/plugins/builtin/clinical-trials/pane.tsx +15 -22
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +8 -6
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- package/src/plugins/builtin/cloud/plugin.tsx +1 -1
- package/src/plugins/builtin/company-attention/building.tsx +5 -1
- package/src/plugins/builtin/company-attention/client.ts +8 -9
- package/src/plugins/builtin/company-attention/evidence.ts +4 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +9 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/correlation/headless.ts +13 -5
- package/src/plugins/builtin/correlation/history.ts +22 -0
- package/src/plugins/builtin/cot/client.ts +22 -18
- package/src/plugins/builtin/cot/headless.ts +15 -10
- package/src/plugins/builtin/cot/model.ts +14 -1
- package/src/plugins/builtin/cot/pane.tsx +22 -14
- package/src/plugins/builtin/credit-boards/client.ts +6 -10
- package/src/plugins/builtin/credit-conditions/headless.ts +8 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +5 -1
- package/src/plugins/builtin/credit-conditions/model.ts +4 -0
- package/src/plugins/builtin/credit-conditions/series.ts +3 -1
- package/src/plugins/builtin/credit-documents/detail.tsx +2 -2
- package/src/plugins/builtin/credit-documents/export.ts +173 -0
- package/src/plugins/builtin/credit-documents/headless.ts +7 -7
- package/src/plugins/builtin/credit-documents/model.ts +104 -14
- package/src/plugins/builtin/credit-documents/pane.tsx +12 -5
- package/src/plugins/builtin/custom-view/sources.ts +2 -0
- package/src/plugins/builtin/dividend-yield/client.ts +131 -23
- package/src/plugins/builtin/dividend-yield/headless.ts +44 -16
- package/src/plugins/builtin/dividend-yield/model.ts +8 -5
- package/src/plugins/builtin/dividend-yield/pane.tsx +38 -13
- package/src/plugins/builtin/dividend-yield/ranking.ts +37 -14
- package/src/plugins/builtin/dividend-yield/types.ts +20 -2
- package/src/plugins/builtin/dividend-yield/view.ts +30 -2
- package/src/plugins/builtin/docs/targets.ts +5 -1
- package/src/plugins/builtin/earnings/board-model.ts +16 -15
- package/src/plugins/builtin/earnings/board.tsx +62 -71
- package/src/plugins/builtin/earnings/headless.ts +40 -4
- package/src/plugins/builtin/earnings/scope.ts +31 -43
- package/src/plugins/builtin/earnings-calls/calendar.tsx +2 -2
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -2
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +5 -4
- package/src/plugins/builtin/econ/calendar-model.ts +14 -9
- package/src/plugins/builtin/econ/figures.ts +72 -0
- package/src/plugins/builtin/econ/index.tsx +33 -3
- package/src/plugins/builtin/econ/types.ts +4 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +85 -35
- package/src/plugins/builtin/econ-statistics/stats.ts +37 -9
- package/src/plugins/builtin/econ-statistics/view.ts +3 -0
- package/src/plugins/builtin/equity-screener/categories.ts +179 -0
- package/src/plugins/builtin/equity-screener/client.ts +4 -2
- package/src/plugins/builtin/equity-screener/headless.ts +144 -13
- package/src/plugins/builtin/equity-screener/ideas.ts +49 -0
- package/src/plugins/builtin/equity-screener/model.ts +99 -10
- package/src/plugins/builtin/equity-screener/pane.tsx +70 -15
- package/src/plugins/builtin/exposure/charts.tsx +2 -2
- package/src/plugins/builtin/exposure/model.ts +13 -1
- package/src/plugins/builtin/exposure/pane.tsx +4 -4
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/futures/model.ts +2 -1
- package/src/plugins/builtin/futures/table.tsx +2 -2
- package/src/plugins/builtin/futures/use-board-terms.ts +42 -28
- package/src/plugins/builtin/futures/use-front-returns.ts +45 -28
- package/src/plugins/builtin/fx-matrix/client.ts +11 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +6 -3
- package/src/plugins/builtin/fx-matrix/index.tsx +16 -4
- package/src/plugins/builtin/fx-matrix/live-legs.ts +54 -3
- package/src/plugins/builtin/gpu/headless.ts +8 -2
- package/src/plugins/builtin/help/function-index.ts +4 -1
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/help/keybindings-editor.tsx +18 -14
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +18 -1
- package/src/plugins/builtin/iv-history/client.ts +52 -11
- package/src/plugins/builtin/iv-history/format.ts +36 -23
- package/src/plugins/builtin/iv-history/headless.ts +36 -18
- package/src/plugins/builtin/iv-history/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/model.ts +163 -27
- package/src/plugins/builtin/iv-history/pane.tsx +10 -6
- package/src/plugins/builtin/iv-history/screen-pane.tsx +22 -15
- package/src/plugins/builtin/iv-history/universe.ts +5 -1
- package/src/plugins/builtin/jobs/client.ts +25 -29
- package/src/plugins/builtin/kelly-sizer/model.ts +12 -8
- package/src/plugins/builtin/kelly-sizer/pane.tsx +9 -9
- package/src/plugins/builtin/kelly-sizer/sections.tsx +19 -10
- package/src/plugins/builtin/kelly-sizer/types.ts +10 -4
- package/src/plugins/builtin/macro-day/pane.tsx +7 -5
- package/src/plugins/builtin/macro-day/release-table.ts +2 -2
- package/src/plugins/builtin/market-heatmap/data.ts +8 -33
- package/src/plugins/builtin/market-movers/client.ts +25 -7
- package/src/plugins/builtin/market-movers/footer.ts +2 -2
- package/src/plugins/builtin/market-movers/headless.ts +32 -12
- package/src/plugins/builtin/market-movers/index.tsx +26 -14
- package/src/plugins/builtin/market-movers/min-float.ts +74 -0
- package/src/plugins/builtin/market-movers/model.ts +4 -1
- package/src/plugins/builtin/market-movers/screener.ts +14 -0
- package/src/plugins/builtin/market-movers/session-body.tsx +13 -8
- package/src/plugins/builtin/market-movers/session-table.ts +4 -3
- package/src/plugins/builtin/market-movers/table.ts +17 -5
- package/src/plugins/builtin/members/breadth-pane.tsx +82 -0
- package/src/plugins/builtin/members/client.ts +19 -4
- package/src/plugins/builtin/members/headless.ts +20 -7
- package/src/plugins/builtin/members/index.tsx +9 -9
- package/src/plugins/builtin/members/model.ts +23 -4
- package/src/plugins/builtin/members/pane.tsx +25 -15
- package/src/plugins/builtin/news/index.tsx +1 -0
- package/src/plugins/builtin/news/wire/categories.ts +19 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +1 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +31 -5
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +6 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +2 -2
- package/src/plugins/builtin/openfda/client.ts +14 -2
- package/src/plugins/builtin/openfda/index.tsx +3 -2
- package/src/plugins/builtin/openfda/model.ts +9 -0
- package/src/plugins/builtin/openfda/pane.tsx +42 -6
- package/src/plugins/builtin/options/analytics.ts +54 -6
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/model-spot.ts +5 -2
- package/src/plugins/builtin/options/strike-window.ts +2 -1
- package/src/plugins/builtin/options/table.ts +6 -9
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +42 -12
- package/src/plugins/builtin/options-positioning/client.ts +30 -0
- package/src/plugins/builtin/options-positioning/headless.ts +74 -21
- package/src/plugins/builtin/options-positioning/index.tsx +4 -4
- package/src/plugins/builtin/options-positioning/model.ts +122 -14
- package/src/plugins/builtin/options-positioning/pane.tsx +87 -42
- package/src/plugins/builtin/options-scenario/client.ts +116 -47
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +142 -10
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +206 -55
- package/src/plugins/builtin/options-scenario/csp-screen.ts +63 -23
- package/src/plugins/builtin/options-scenario/csp.ts +8 -2
- package/src/plugins/builtin/options-scenario/index.tsx +9 -7
- package/src/plugins/builtin/options-scenario/strategy-screen.ts +532 -0
- package/src/plugins/builtin/pe-band/model.ts +12 -49
- package/src/plugins/builtin/perps/cascade-tabs.tsx +161 -0
- package/src/plugins/builtin/perps/cascade.ts +236 -0
- package/src/plugins/builtin/perps/client.ts +56 -2
- package/src/plugins/builtin/perps/freshness.ts +12 -10
- package/src/plugins/builtin/perps/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/live-rows.ts +10 -3
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +32 -31
- package/src/plugins/builtin/perps/status-line.ts +25 -0
- package/src/plugins/builtin/plugin-module.ts +5 -1
- package/src/plugins/builtin/portfolio-list/cached-account.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +2 -8
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +4 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +12 -7
- package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +4 -1
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +5 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +3 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +3 -1
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +11 -8
- package/src/plugins/builtin/portfolio-list/table.tsx +11 -3
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/rate-path/pane.tsx +2 -2
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/client.ts +18 -4
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +2 -1
- package/src/plugins/builtin/relative-rotation/model.ts +16 -40
- package/src/plugins/builtin/relative-rotation/pane.tsx +3 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +3 -2
- package/src/plugins/builtin/research/event-model.ts +10 -8
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/relative-valuation-headless.ts +5 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +11 -9
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -3
- package/src/plugins/builtin/reverse-dcf/model.ts +61 -6
- package/src/plugins/builtin/reverse-dcf/pane.tsx +7 -4
- package/src/plugins/builtin/scanner/feed.ts +2 -2
- package/src/plugins/builtin/scanner/flow-model.ts +50 -4
- package/src/plugins/builtin/scanner/flow-pane.tsx +367 -65
- package/src/plugins/builtin/scanner/flow-session.ts +146 -0
- package/src/plugins/builtin/scanner/headless.ts +204 -35
- package/src/plugins/builtin/scanner/index.ts +40 -6
- package/src/plugins/builtin/scanner/live-condition-editor.tsx +222 -0
- package/src/plugins/builtin/scanner/live-feed.ts +168 -0
- package/src/plugins/builtin/scanner/live-headless.ts +138 -0
- package/src/plugins/builtin/scanner/live-model.ts +362 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +677 -0
- package/src/plugins/builtin/scanner/live-track.ts +186 -0
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/headless.ts +10 -1
- package/src/plugins/builtin/sec/fund-facts-view.tsx +5 -2
- package/src/plugins/builtin/sec/fund-facts.ts +116 -34
- package/src/plugins/builtin/sec/headless.ts +2 -1
- package/src/plugins/builtin/series-inventory.ts +3 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +3 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +4 -3
- package/src/plugins/builtin/shared/earnings-calendar.ts +6 -2
- package/src/plugins/builtin/shared/earnings-report.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -0
- package/src/plugins/builtin/shared/macro-releases.ts +65 -0
- package/src/plugins/builtin/shared/members-menu.tsx +3 -2
- package/src/plugins/builtin/shared/pro-lock-note.ts +12 -12
- package/src/plugins/builtin/shared/report-freshness.ts +3 -2
- package/src/plugins/builtin/shared/scanner-capture.ts +3 -0
- package/src/plugins/builtin/shared/ticker-choice.tsx +2 -1
- package/src/plugins/builtin/shared/ticker-company.ts +77 -0
- package/src/plugins/builtin/shared/use-quote-board.ts +10 -3
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +26 -1
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/headless.ts +6 -4
- package/src/plugins/builtin/themes/model.ts +17 -8
- package/src/plugins/builtin/themes/pane.tsx +7 -7
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +43 -18
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +3 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +62 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +83 -46
- package/src/plugins/builtin/ticker-detail/headless.ts +31 -16
- package/src/plugins/builtin/ticker-detail/overview/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +6 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/settings.ts +1 -0
- package/src/plugins/builtin/time-sales/pane.tsx +31 -19
- package/src/plugins/builtin/treasury-daily/client.ts +41 -5
- package/src/plugins/builtin/treasury-daily/headless.ts +2 -2
- package/src/plugins/builtin/treasury-daily/index.tsx +1 -1
- package/src/plugins/builtin/treasury-daily/model.ts +50 -3
- package/src/plugins/builtin/treasury-daily/pane.tsx +81 -2
- package/src/plugins/builtin/vol-surface/charts.tsx +9 -4
- package/src/plugins/builtin/vol-surface/client.ts +9 -17
- package/src/plugins/builtin/vol-surface/headless.ts +63 -14
- package/src/plugins/builtin/vol-surface/index.tsx +2 -2
- package/src/plugins/builtin/vol-surface/model.ts +22 -7
- package/src/plugins/builtin/vol-surface/pane.tsx +48 -9
- package/src/plugins/builtin/vol-surface/tables.ts +31 -3
- package/src/plugins/builtin/volatility/dvol.ts +46 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +4 -4
- package/src/plugins/builtin/volatility/series.ts +26 -0
- package/src/plugins/builtin/world-indices/footer.ts +1 -1
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/catalog-browser.ts +13 -8
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +5 -5
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/public/__snapshots__/public-api.test.ts.snap +1 -0
- package/src/remote/resources.ts +2 -1
- package/src/renderers/browser/app-services.ts +1 -7
- package/src/renderers/browser/config-host.ts +2 -55
- package/src/renderers/browser/main.tsx +7 -57
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/list-view.tsx +13 -10
- package/src/renderers/dom/desktop/query-bar.tsx +4 -2
- package/src/renderers/dom/desktop/select-field.tsx +4 -2
- package/src/renderers/dom/host/chart-surface.tsx +21 -0
- package/src/renderers/electrobun/bun/desktop/app-name.ts +222 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +29 -7
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/relaunch.ts +74 -25
- package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +173 -5
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/workspace/index.ts +2 -0
- package/src/renderers/electrobun/bun/index.ts +25 -1
- package/src/renderers/electrobun/shared/app-name.ts +30 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +1 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +3 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- package/src/renderers/opentui/toast-host.tsx +71 -43
- package/src/series/registry.ts +1 -0
- package/src/series/types.ts +6 -0
- package/src/series/validate.ts +1 -0
- package/src/sources/gloomberb-cloud/index.ts +1 -0
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/provider-router/batches.ts +10 -2
- package/src/sources/provider-router/financial-routes.ts +3 -3
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/history.ts +28 -7
- package/src/sources/provider-router/index.ts +149 -10
- package/src/sources/provider-router/search.ts +13 -2
- package/src/state/app/context/index.tsx +3 -0
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/auth-transition.ts +19 -9
- package/src/sync/baseline.ts +10 -4
- package/src/sync/controller.ts +70 -19
- package/src/sync/core-contributors.ts +90 -31
- package/src/sync/react.ts +4 -1
- package/src/sync/types.ts +3 -0
- package/src/telemetry/stall-reports-dom.ts +38 -0
- package/src/telemetry/stall-reports-node.ts +75 -0
- package/src/telemetry/stall-reports.ts +214 -0
- package/src/telemetry/usage-counts.ts +0 -18
- package/src/test-support/preload.ts +14 -0
- package/src/theme/colors.ts +8 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name.ts +103 -3
- package/src/tickers/listing-venues.ts +38 -3
- package/src/tickers/search/bare-symbol.ts +36 -0
- package/src/tickers/search/index.ts +36 -7
- package/src/tickers/search/ranking.ts +10 -1
- package/src/tickers/search/types.ts +5 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/base-series.ts +13 -5
- package/src/time-series/daily-valuation.ts +62 -0
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +2 -4
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/forward-valuation.ts +32 -0
- package/src/time-series/fundamentals.ts +198 -7
- package/src/time-series/hooks.ts +1 -0
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/price-units.ts +72 -2
- package/src/time-series/resolve-context.ts +7 -1
- package/src/time-series/resolve.ts +116 -15
- package/src/time-series/series-presentation.ts +40 -6
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +5 -3
- package/src/time-series/studies.ts +278 -74
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +3 -3
- package/src/time-series/types.ts +27 -1
- package/src/time-series/valuation-releases.ts +39 -0
- package/src/types/data-provider.ts +9 -1
- package/src/types/desktop-window.ts +2 -0
- package/src/types/financials.ts +73 -2
- package/src/types/headless.ts +61 -5
- package/src/types/instrument.ts +3 -0
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +10 -1
- package/src/ui/host.tsx +3 -0
- package/src/updater/command-names.ts +12 -7
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +44 -0
- package/src/utils/financial-statements.ts +6 -1
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +24 -3
- package/src/utils/fx-market-hours.ts +26 -3
- package/src/utils/main-thread-stall.ts +35 -2
- package/src/utils/market-capitalization.ts +24 -1
- package/src/utils/network-failure.ts +9 -6
- package/src/utils/option-expiry.ts +48 -1
- package/src/utils/options.ts +10 -0
- package/src/utils/plugin-proxy-hosts.json +1 -0
- package/src/utils/price-history.ts +12 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
- package/src/renderers/browser/first-screen.ts +0 -193
|
@@ -26,6 +26,9 @@ import type { GloomPlugin } from "../types/plugin";
|
|
|
26
26
|
import type { LoadedExternalPlugin } from "./loader";
|
|
27
27
|
import { portfolioAnalyticsModule } from "./builtin/analytics";
|
|
28
28
|
import { earningsCallsModule } from "./builtin/earnings-calls";
|
|
29
|
+
import { earningsModule } from "./builtin/earnings";
|
|
30
|
+
import { holdersModule } from "./builtin/holders";
|
|
31
|
+
import { thirteenFModule } from "./builtin/thirteenf";
|
|
29
32
|
import { browserDividendYieldModule } from "./builtin/dividend-yield/browser";
|
|
30
33
|
import { executivesModule } from "./builtin/executives";
|
|
31
34
|
import { filingEventsModule } from "./builtin/filing-events";
|
|
@@ -136,9 +139,7 @@ const browserPortfolioPlugin = composeBuiltinPlugin({
|
|
|
136
139
|
modules: [portfolioListModule, portfolioAnalyticsModule, positionSizerModule],
|
|
137
140
|
});
|
|
138
141
|
|
|
139
|
-
// Ticker Research's successors with
|
|
140
|
-
// 13F funds and the Congress tab are terminal-only, so Ownership & Insiders
|
|
141
|
-
// is smaller here.
|
|
142
|
+
// Ticker Research's successors with browser-safe data paths.
|
|
142
143
|
const browserTickerCorePlugin = composeBuiltinPlugin({
|
|
143
144
|
...tickerCorePluginMeta,
|
|
144
145
|
modules: [
|
|
@@ -171,8 +172,12 @@ const browserOptionsVolatilityPlugin = composeBuiltinPlugin({
|
|
|
171
172
|
|
|
172
173
|
const browserOwnershipPlugin = composeBuiltinPlugin({
|
|
173
174
|
...ownershipPluginMeta,
|
|
174
|
-
description: "
|
|
175
|
+
description: "Holders, 13F funds, insider trades, and short interest and volume.",
|
|
176
|
+
// The public 13F fallback goes through the same host proxy as other plugins.
|
|
177
|
+
hosts: ["forms13f.com"],
|
|
175
178
|
modules: [
|
|
179
|
+
holdersModule,
|
|
180
|
+
thirteenFModule,
|
|
176
181
|
// Form 4s come through Gloom Cloud, behind a sign-in wall.
|
|
177
182
|
insiderModule,
|
|
178
183
|
// Daily volume shares open this pane.
|
|
@@ -274,13 +279,13 @@ const browserCreditPlugin = composeBuiltinPlugin({
|
|
|
274
279
|
});
|
|
275
280
|
browserCreditPlugin.hosts = [...FIXED_INCOME_HOSTS];
|
|
276
281
|
|
|
277
|
-
// The
|
|
278
|
-
// and the ripple
|
|
279
|
-
// its namespace, not Macro's as on the terminal.
|
|
282
|
+
// The calendar keeps Macro's state namespace, as on the desktop and terminal.
|
|
283
|
+
// Calls and the ripple keep the Ticker Research namespace they used on the web.
|
|
280
284
|
const browserEarningsPlugin = composeBuiltinPlugin({
|
|
281
285
|
...earningsPluginMeta,
|
|
282
|
-
description: "Earnings call transcripts, and the earnings ripple through customers and suppliers.",
|
|
286
|
+
description: "Earnings calendar, call transcripts, and the earnings ripple through customers and suppliers.",
|
|
283
287
|
modules: [
|
|
288
|
+
earningsModule,
|
|
284
289
|
{ module: earningsCallsModule, stateId: "ticker-research" },
|
|
285
290
|
{ module: earningsRippleModule, stateId: "ticker-research" },
|
|
286
291
|
],
|
|
@@ -75,7 +75,8 @@ const NATIVE_TARGETS: PluginTarget[] = ["cli", "tui", "desktop"];
|
|
|
75
75
|
*/
|
|
76
76
|
function functionsOf(plugin: GloomPlugin) {
|
|
77
77
|
return pluginFunctions({
|
|
78
|
-
|
|
78
|
+
// An unlisted function (`listed: false`) is not published.
|
|
79
|
+
templates: (plugin.paneTemplates ?? []).filter((template) => template.listed !== false).map((template) => ({
|
|
79
80
|
label: template.label,
|
|
80
81
|
prefix: template.shortcut?.prefix,
|
|
81
82
|
description: template.description,
|
|
@@ -186,6 +186,19 @@ function repoDirectory(repo: string | undefined): string | null {
|
|
|
186
186
|
return name ? name.toLowerCase() : null;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Built-ins write their copy as sentences and registry plugins as labels, so a
|
|
191
|
+
* row's short line is read without its closing period, whoever wrote it, and
|
|
192
|
+
* the detail's paragraph always has one. An ellipsis stays as written.
|
|
193
|
+
*/
|
|
194
|
+
function rowLine(text: string | undefined): string {
|
|
195
|
+
return (text ?? "").trim().replace(/(?<!\.)\.$/, "");
|
|
196
|
+
}
|
|
197
|
+
function detailParagraph(text: string | undefined): string | undefined {
|
|
198
|
+
const paragraph = text?.trim();
|
|
199
|
+
return paragraph ? /[\p{L}\p{N}]$/u.test(paragraph) ? `${paragraph}.` : paragraph : undefined;
|
|
200
|
+
}
|
|
201
|
+
|
|
189
202
|
/** The short line a built-in's row reads: its editorial tagline, else its description. */
|
|
190
203
|
function builtinTagline(local: InstalledPlugin): string {
|
|
191
204
|
return BUILTIN_EDITORIAL[local.id]?.tagline ?? local.description ?? "";
|
|
@@ -257,8 +270,8 @@ export function mergeCatalog(options: {
|
|
|
257
270
|
entries.push({
|
|
258
271
|
id: plugin.id,
|
|
259
272
|
name: builtin?.name ?? plugin.name,
|
|
260
|
-
tagline: builtin ? builtinTagline(builtin) : plugin.tagline,
|
|
261
|
-
description: builtin?.description ?? plugin.description,
|
|
273
|
+
tagline: rowLine(builtin ? builtinTagline(builtin) : plugin.tagline),
|
|
274
|
+
description: detailParagraph(builtin?.description ?? plugin.description),
|
|
262
275
|
categories: builtin ? BUILTIN_EDITORIAL[plugin.id]?.categories ?? plugin.categories : plugin.categories,
|
|
263
276
|
tier: plugin.tier,
|
|
264
277
|
targets: plugin.targets,
|
|
@@ -309,10 +322,10 @@ export function mergeCatalog(options: {
|
|
|
309
322
|
entries.push({
|
|
310
323
|
id: local.id,
|
|
311
324
|
name: local.name,
|
|
312
|
-
tagline: local.source === "builtin"
|
|
325
|
+
tagline: rowLine(local.source === "builtin"
|
|
313
326
|
? builtinTagline(local)
|
|
314
|
-
: local.description ?? (local.linked ? "Linked from a local checkout" : "Installed outside the registry"),
|
|
315
|
-
description: local.description,
|
|
327
|
+
: local.description ?? (local.linked ? "Linked from a local checkout" : "Installed outside the registry")),
|
|
328
|
+
description: detailParagraph(local.description),
|
|
316
329
|
categories: local.source === "builtin" ? [...BUILTIN_EDITORIAL[local.id]?.categories ?? []] : ["unlisted"],
|
|
317
330
|
// Shipped by Gloom like every built-in, whether or not the feed lists it.
|
|
318
331
|
tier: local.source === "builtin" ? "official" : "community",
|
|
@@ -6,7 +6,7 @@ import type { ColumnConfig } from "../types/config";
|
|
|
6
6
|
import type { AnalystResearchData, CorporateActionsData, MarketState, Quote, TickerFinancials } from "../types/financials";
|
|
7
7
|
import type { EarningsEvent } from "../types/data-provider";
|
|
8
8
|
import type { TickerRecord } from "../types/ticker";
|
|
9
|
-
import { colors, priceColor } from "../theme/colors";
|
|
9
|
+
import { colors, priceColor, shownPriceColor } from "../theme/colors";
|
|
10
10
|
import { formatQuoteAgeWithSource, resolveQuoteAgeTimestamp } from "../market-data/quotes/time";
|
|
11
11
|
import { delistingStateLabel } from "../market-data/quotes/delisting";
|
|
12
12
|
import { formatFeedTime, formatShortDate, parseDisplayDate, type ShortDateOptions } from "../utils/datetime-format";
|
|
@@ -532,7 +532,7 @@ export function getColumnValue(
|
|
|
532
532
|
case "ext_hours": {
|
|
533
533
|
const changePercent = getExtendedSessionDisplay(quote)?.changePercent;
|
|
534
534
|
if (!isFiniteNumber(changePercent)) return { text: "—" };
|
|
535
|
-
return { text: formatPercentRaw(changePercent), color:
|
|
535
|
+
return { text: formatPercentRaw(changePercent), color: shownPriceColor(changePercent, 2) };
|
|
536
536
|
}
|
|
537
537
|
case "side":
|
|
538
538
|
return { text: positionSideLabel(ticker, ctx.activeTab) ?? "—" };
|
|
@@ -594,13 +594,13 @@ export function getColumnValue(
|
|
|
594
594
|
}
|
|
595
595
|
case "pnl_pct": {
|
|
596
596
|
const percent = portfolioPnlPercent(positionPnl.value, baseMetrics.totalCost);
|
|
597
|
-
return percent === null ? { text: "—" } : { text: formatPercentRaw(percent), color:
|
|
597
|
+
return percent === null ? { text: "—" } : { text: formatPercentRaw(percent), color: shownPriceColor(percent, 2) };
|
|
598
598
|
}
|
|
599
599
|
case "mark_delta":
|
|
600
600
|
if (!liveQuote || brokerMarkPrice == null || liveQuote.price === 0 || positionMetrics.priceBasis !== (quote?.priceBasis ?? "per-unit") || positionCurrency !== quoteCurrency) return { text: "—" };
|
|
601
601
|
{
|
|
602
602
|
const percent = ((brokerMarkPrice - liveQuote.price) / Math.abs(liveQuote.price)) * 100;
|
|
603
|
-
return { text: formatPercentRaw(percent), color:
|
|
603
|
+
return { text: formatPercentRaw(percent), color: shownPriceColor(percent, 2) };
|
|
604
604
|
}
|
|
605
605
|
case "acq_date": {
|
|
606
606
|
return { text: formatShortDate(earliestDateAcquired(ticker, ctx.activeTab), MONTH_DAY) };
|
|
@@ -627,7 +627,7 @@ export function getColumnValue(
|
|
|
627
627
|
const current = targetReferencePrice(analyst.data, quoteCurrency, displayQuote?.price);
|
|
628
628
|
if (value == null || !current) return { text: "—" };
|
|
629
629
|
const percent = ((value - current) / Math.abs(current)) * 100;
|
|
630
|
-
return { text: formatPercentRaw(percent), color:
|
|
630
|
+
return { text: formatPercentRaw(percent), color: shownPriceColor(percent, 2) };
|
|
631
631
|
}
|
|
632
632
|
case "rating": {
|
|
633
633
|
const analyst = mapData(ctx.analystResearch, ticker.metadata.ticker);
|
|
@@ -36,10 +36,12 @@ export interface FuturesSettlement {
|
|
|
36
36
|
previous: number | null;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/**
|
|
39
|
+
/** A future's contract size, settlement and front reference for collection rows. */
|
|
40
40
|
export interface PortfolioFuturesTerms {
|
|
41
41
|
size: FuturesContractSize | null;
|
|
42
42
|
settlement: FuturesSettlement | null;
|
|
43
|
+
/** A different contract that is currently front, when the terms name one. */
|
|
44
|
+
front?: Pick<NonNullable<FuturesContractTermsPayload["front"]>, "contract" | "contractSymbol">;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/** A grain or a soft quotes in US cents, so a dollar point value is a hundred of its price units. */
|
|
@@ -167,7 +169,7 @@ export function previousFuturesSettlement(
|
|
|
167
169
|
|
|
168
170
|
/** What a portfolio reads from a future's terms, with the settlement before the latest when the history has it. */
|
|
169
171
|
export function portfolioFuturesTerms(
|
|
170
|
-
terms: Pick<FuturesContractTermsPayload, "spec" | "settlement"> | null | undefined,
|
|
172
|
+
terms: (Pick<FuturesContractTermsPayload, "spec" | "settlement"> & Partial<Pick<FuturesContractTermsPayload, "front" | "contract">>) | null | undefined,
|
|
171
173
|
history?: readonly PricePoint[] | null,
|
|
172
174
|
): PortfolioFuturesTerms {
|
|
173
175
|
const settlement = terms?.settlement && Number.isFinite(terms.settlement.price) && terms.settlement.price > 0
|
|
@@ -177,7 +179,8 @@ export function portfolioFuturesTerms(
|
|
|
177
179
|
previous: previousFuturesSettlement(history, terms.settlement.date, terms.settlement.price),
|
|
178
180
|
}
|
|
179
181
|
: null;
|
|
180
|
-
|
|
182
|
+
const front = terms?.front && terms.front.contract !== terms.contract ? terms.front : undefined;
|
|
183
|
+
return { size: futuresContractSize(terms?.spec), settlement, ...(front ? { front } : {}) };
|
|
181
184
|
}
|
|
182
185
|
|
|
183
186
|
/**
|
|
@@ -23,21 +23,27 @@ function tradesInWholeUnits(ticker: TickerRecord): boolean {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Why a typed size cannot be stored as read: a dot and three digits (`1.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* command asks which, as it does for `1,250`.
|
|
30
|
-
*
|
|
26
|
+
* Why a typed size cannot be stored as read: a dot and three digits (`1.000`,
|
|
27
|
+
* `1.250`), which is as likely the thousands grouping many locales write
|
|
28
|
+
* (1,000 shares, as cash reads `1.000`) as a fraction of a share, so the
|
|
29
|
+
* command asks which, as it does for `1,250`. On a listing held in whole
|
|
30
|
+
* units the thousands reading is the only one that can be held, and the
|
|
31
|
+
* message says so. Null for any other size (`0.500`, `12.25`).
|
|
31
32
|
*/
|
|
32
|
-
export function
|
|
33
|
+
export function ambiguousQuantityProblem(
|
|
33
34
|
typed: string,
|
|
34
35
|
ticker: TickerRecord,
|
|
35
36
|
options: { label?: PositionQuantityLabel; listing?: string } = {},
|
|
36
37
|
): string | null {
|
|
37
38
|
const reading = thousandsDotReadings(typed);
|
|
38
|
-
if (!reading
|
|
39
|
+
if (!reading) return null;
|
|
39
40
|
const label = options.label ?? positionQuantityLabel(ticker);
|
|
40
41
|
const listing = options.listing ?? ticker.metadata.ticker;
|
|
41
|
-
const because =
|
|
42
|
-
|
|
42
|
+
const because = tradesInWholeUnits(ticker)
|
|
43
|
+
? `${listing} trades in whole ${label === "Contracts" ? "contracts" : "shares"}`
|
|
44
|
+
: undefined;
|
|
45
|
+
// The fraction typed so it does not read two ways itself: 1.234 asks again, 1.2340 does not.
|
|
46
|
+
const fraction = String(reading.decimal);
|
|
47
|
+
const decimalAs = thousandsDotReadings(fraction) ? `${fraction}0` : fraction;
|
|
48
|
+
return `${label} ${ambiguousNumberMessage(typed, reading, { because, decimalAs })}.`;
|
|
43
49
|
}
|
package/src/remote/resources.ts
CHANGED
|
@@ -110,7 +110,8 @@ export function createRemoteResources({
|
|
|
110
110
|
}));
|
|
111
111
|
}
|
|
112
112
|
if (resource === "app://pane-templates") {
|
|
113
|
-
|
|
113
|
+
// An unlisted function (`listed: false`) is left out, as of every list.
|
|
114
|
+
return [...pluginRegistry.paneTemplates.values()].filter((template) => template.listed !== false).map((template) => ({
|
|
114
115
|
id: template.id,
|
|
115
116
|
paneId: template.paneId,
|
|
116
117
|
label: template.label,
|
|
@@ -7,7 +7,6 @@ import { AssetDataRouter } from "../../sources/provider-router";
|
|
|
7
7
|
import { JsonPersistence } from "../../data/json-persistence";
|
|
8
8
|
import { isBrokerAccountSnapshotKey } from "../../brokers/account-cache";
|
|
9
9
|
import { JsonTickerRepository } from "../../data/json-ticker-repository";
|
|
10
|
-
import { noteFirstScreenTicker } from "./first-screen";
|
|
11
10
|
|
|
12
11
|
export function createBrowserAppServices({ config, plugins, externalPlugins }: AppServicesFactoryOptions) {
|
|
13
12
|
const cloudProvider = createGloomberbCloudProvider();
|
|
@@ -28,12 +27,7 @@ export function createBrowserAppServices({ config, plugins, externalPlugins }: A
|
|
|
28
27
|
priority: 0,
|
|
29
28
|
provider: { fetchNews: (query) => cloudNews?.provider.fetchNews(query) ?? Promise.resolve([]) },
|
|
30
29
|
}));
|
|
31
|
-
|
|
32
|
-
const offSelected = pluginRegistry.events.on("ticker:selected", ({ symbol, previous }) => noteFirstScreenTicker(symbol, previous));
|
|
33
|
-
return () => {
|
|
34
|
-
offSaved();
|
|
35
|
-
offSelected();
|
|
36
|
-
};
|
|
30
|
+
return pluginRegistry.events.on("host:portfolio-ticker-saved", () => recordResearchActivity("ticker_saved"));
|
|
37
31
|
},
|
|
38
32
|
});
|
|
39
33
|
}
|
|
@@ -30,7 +30,6 @@ const BROWSER_RESEARCH_NEWS_ID = "ticker-news:research";
|
|
|
30
30
|
const BROWSER_WORLD_INDICES_ID = "world-indices:main";
|
|
31
31
|
const BROWSER_SECTORS_ID = "sectors:main";
|
|
32
32
|
const BROWSER_ECON_CALENDAR_ID = "econ-calendar:main";
|
|
33
|
-
const BROWSER_HELP_ID = "help:main";
|
|
34
33
|
|
|
35
34
|
function column(first: string, second: string, ratio = 0.5): DockLayoutNode {
|
|
36
35
|
return {
|
|
@@ -82,53 +81,14 @@ export function createBrowserResearchLayout(symbol: string): LayoutConfig {
|
|
|
82
81
|
};
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
* The calm first screen (`calm` arm of `web_first_screen`): two of the same
|
|
87
|
-
* panes, the company's research and Help on its basics, side by side in a
|
|
88
|
-
* landscape window and stacked in a portrait one, as on a phone. The research
|
|
89
|
-
* pane owns the symbol exactly as in the six-pane workspace.
|
|
90
|
-
*/
|
|
91
|
-
function createBrowserCalmLayout(symbol: string, portrait: boolean): LayoutConfig {
|
|
92
|
-
return {
|
|
93
|
-
dockRoot: {
|
|
94
|
-
kind: "split",
|
|
95
|
-
axis: portrait ? "vertical" : "horizontal",
|
|
96
|
-
ratio: portrait ? 0.55 : 0.6,
|
|
97
|
-
first: { kind: "pane", instanceId: BROWSER_RESEARCH_PANE_ID },
|
|
98
|
-
second: { kind: "pane", instanceId: BROWSER_HELP_ID },
|
|
99
|
-
},
|
|
100
|
-
instances: [
|
|
101
|
-
{
|
|
102
|
-
instanceId: BROWSER_RESEARCH_PANE_ID,
|
|
103
|
-
paneId: TICKER_RESEARCH_PANE_ID,
|
|
104
|
-
binding: { kind: "fixed", symbol },
|
|
105
|
-
settings: { hideTabs: false },
|
|
106
|
-
},
|
|
107
|
-
{ instanceId: BROWSER_HELP_ID, paneId: "help", binding: { kind: "none" } },
|
|
108
|
-
],
|
|
109
|
-
floating: [],
|
|
110
|
-
detached: [],
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** Which first screen a new visitor opens on; see first-screen.ts. */
|
|
115
|
-
export type BrowserFirstScreen = "control" | "calm";
|
|
116
|
-
|
|
117
|
-
function createBrowserDefaultConfig(
|
|
118
|
-
dataDir: string,
|
|
119
|
-
search = "",
|
|
120
|
-
firstScreen: BrowserFirstScreen = "control",
|
|
121
|
-
portrait = false,
|
|
122
|
-
): AppConfig {
|
|
84
|
+
function createBrowserDefaultConfig(dataDir: string, search = ""): AppConfig {
|
|
123
85
|
const config = createDefaultConfig(dataDir);
|
|
124
86
|
const entry = researchEntryFromSearch(search) ?? { symbol: "NVDA", tab: "overview" };
|
|
125
87
|
// A first visit starts with a research workspace around one company. Saved
|
|
126
88
|
// layouts retain their existing panes and bindings when a visitor returns.
|
|
127
89
|
config.layouts[0] = {
|
|
128
90
|
name: "Research",
|
|
129
|
-
layout:
|
|
130
|
-
? createBrowserCalmLayout(entry.symbol, portrait)
|
|
131
|
-
: createBrowserResearchLayout(entry.symbol),
|
|
91
|
+
layout: createBrowserResearchLayout(entry.symbol),
|
|
132
92
|
paneState: { [BROWSER_RESEARCH_PANE_ID]: { activeTabId: entry.tab } },
|
|
133
93
|
focusedPaneId: BROWSER_RESEARCH_PANE_ID,
|
|
134
94
|
};
|
|
@@ -136,19 +96,6 @@ function createBrowserDefaultConfig(
|
|
|
136
96
|
return browserReady(config);
|
|
137
97
|
}
|
|
138
98
|
|
|
139
|
-
/**
|
|
140
|
-
* A first visit's workspace for the screen it was given, built the way
|
|
141
|
-
* `loadConfig` builds the six-pane one. Only for a browser with no saved
|
|
142
|
-
* workspace: a returning visitor keeps theirs.
|
|
143
|
-
*/
|
|
144
|
-
export function createBrowserFirstScreenConfig(
|
|
145
|
-
dataDir: string,
|
|
146
|
-
firstScreen: BrowserFirstScreen,
|
|
147
|
-
{ search = "", portrait = false }: { search?: string; portrait?: boolean } = {},
|
|
148
|
-
): AppConfig {
|
|
149
|
-
return createBrowserDefaultConfig(dataDir, search, firstScreen, portrait);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
99
|
export function createBrowserConfigStore(storage: StorageLike, search = ""): ConfigStoreHost {
|
|
153
100
|
const data = new SafeJsonStorage<unknown>(storage, BROWSER_STORAGE_KEYS.config, null);
|
|
154
101
|
return {
|
|
@@ -17,29 +17,10 @@ import {
|
|
|
17
17
|
restoreBrowserCloudSession,
|
|
18
18
|
} from "./cloud-transport";
|
|
19
19
|
import { loadWebBundledPlugins } from "./bundled-plugins";
|
|
20
|
-
import {
|
|
21
|
-
BROWSER_DATA_DIR,
|
|
22
|
-
createBrowserFirstScreenConfig,
|
|
23
|
-
hasSavedBrowserConfig,
|
|
24
|
-
installBrowserConfigStore,
|
|
25
|
-
} from "./config-host";
|
|
20
|
+
import { BROWSER_DATA_DIR, hasSavedBrowserConfig, installBrowserConfigStore } from "./config-host";
|
|
26
21
|
import { browserRendererHost, browserUiHost } from "./ui-host";
|
|
27
22
|
import { createBrowserDeepLinkBridge } from "./deeplink-bridge";
|
|
28
|
-
import {
|
|
29
|
-
exposeFirstScreen,
|
|
30
|
-
FIRST_SCREEN_EXPERIMENT,
|
|
31
|
-
FIRST_SCREEN_PLACEMENT,
|
|
32
|
-
observeLandingLinks,
|
|
33
|
-
watchFirstScreenEngagement,
|
|
34
|
-
} from "./first-screen";
|
|
35
|
-
import {
|
|
36
|
-
exposeWebExperiment,
|
|
37
|
-
initializeBrowserResearchActivity,
|
|
38
|
-
recordResearchActivity,
|
|
39
|
-
} from "../../api-client/research-activity";
|
|
40
|
-
import { subscribeCommandBarQuery } from "../../components/command-bar/panel/prompt-binding";
|
|
41
|
-
import { marketplaceLayoutIdFromSearch } from "../../layout-marketplace/api";
|
|
42
|
-
import { paneShareIdFromSearch } from "../../shares/location";
|
|
23
|
+
import { initializeBrowserResearchActivity, recordResearchActivity } from "../../api-client/research-activity";
|
|
43
24
|
import { flushPendingPersistence } from "../../state/persist-scheduler";
|
|
44
25
|
import { loadOfficialPluginIds } from "../../plugins/marketplace/feed";
|
|
45
26
|
import { crashReportsEnabled, installCrashReporter, reportCrash } from "../../telemetry/crash-reports";
|
|
@@ -51,12 +32,7 @@ import {
|
|
|
51
32
|
} from "../../telemetry/crash-reports-dom";
|
|
52
33
|
import { currentTelemetryConfig } from "../../telemetry/live-config";
|
|
53
34
|
import { attentionCountsEnabled, installAttentionCounter } from "../../telemetry/attention-counts";
|
|
54
|
-
import {
|
|
55
|
-
installUsageCounter,
|
|
56
|
-
recordRestoredFunctions,
|
|
57
|
-
subscribeFunctionOpens,
|
|
58
|
-
usageCountsEnabled,
|
|
59
|
-
} from "../../telemetry/usage-counts";
|
|
35
|
+
import { installUsageCounter, recordRestoredFunctions, usageCountsEnabled } from "../../telemetry/usage-counts";
|
|
60
36
|
import { installWindowUsageFlush } from "../../telemetry/usage-counts-dom";
|
|
61
37
|
import type { AppConfig } from "../../types/config";
|
|
62
38
|
|
|
@@ -78,9 +54,8 @@ const releaseBootFrame = releaseBootFrameWhenDrawn(document, appRootElement);
|
|
|
78
54
|
const BOOT_FRAME_RELEASE_FALLBACK_MS = 4_000;
|
|
79
55
|
|
|
80
56
|
async function boot(): Promise<void> {
|
|
81
|
-
// Read before anything can save a workspace
|
|
57
|
+
// Read before anything can save a workspace.
|
|
82
58
|
const savedLayout = hasSavedBrowserConfig();
|
|
83
|
-
const search = location.search;
|
|
84
59
|
installBrowserConfigStore();
|
|
85
60
|
let loadedConfig: AppConfig | null = null;
|
|
86
61
|
installCrashReporter({
|
|
@@ -105,7 +80,7 @@ async function boot(): Promise<void> {
|
|
|
105
80
|
});
|
|
106
81
|
installBrowserFetchTransports();
|
|
107
82
|
// Read the saved Usage switch before any research activity or attribution.
|
|
108
|
-
|
|
83
|
+
const config = await loadConfig(BROWSER_DATA_DIR);
|
|
109
84
|
loadedConfig = config;
|
|
110
85
|
initializeBrowserResearchActivity();
|
|
111
86
|
installFocusScopeRelease();
|
|
@@ -120,34 +95,9 @@ async function boot(): Promise<void> {
|
|
|
120
95
|
recordResearchActivity("workspace_opened");
|
|
121
96
|
// Nothing was restored on a first visit, only the starter workspace shown.
|
|
122
97
|
if (!savedLayout) recordRestoredFunctions([]);
|
|
123
|
-
// A first visit's workspace is chosen before the dock paints, while the
|
|
124
|
-
// plugins download; see first-screen.ts.
|
|
125
|
-
const firstScreen = exposeFirstScreen({
|
|
126
|
-
savedLayout,
|
|
127
|
-
handoff: !!marketplaceLayoutIdFromSearch(search) || !!paneShareIdFromSearch(search),
|
|
128
|
-
expose: (signal) => exposeWebExperiment(FIRST_SCREEN_EXPERIMENT, { placement: FIRST_SCREEN_PLACEMENT, signal }),
|
|
129
|
-
});
|
|
130
|
-
const [externalPlugins, screen] = await Promise.all([bundledPlugins, firstScreen]);
|
|
131
|
-
if (screen === "calm") {
|
|
132
|
-
config = createBrowserFirstScreenConfig(BROWSER_DATA_DIR, "calm", {
|
|
133
|
-
search,
|
|
134
|
-
portrait: window.innerHeight > window.innerWidth,
|
|
135
|
-
});
|
|
136
|
-
loadedConfig = config;
|
|
137
|
-
}
|
|
138
98
|
applyLanguageFromConfig(config);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
counted: screen !== null,
|
|
142
|
-
session: sessionStorage,
|
|
143
|
-
layout: config.layout,
|
|
144
|
-
record: () => recordResearchActivity("first_screen_engaged", undefined, undefined, { placement: FIRST_SCREEN_PLACEMENT }),
|
|
145
|
-
sources: { subscribeFunctionOpens, subscribeCommandBarQuery },
|
|
146
|
-
});
|
|
147
|
-
} catch {
|
|
148
|
-
/* Blocked storage: the first action is not measured. */
|
|
149
|
-
}
|
|
150
|
-
const deepLinkBridge = observeLandingLinks(createBrowserDeepLinkBridge());
|
|
99
|
+
const externalPlugins = await bundledPlugins;
|
|
100
|
+
const deepLinkBridge = createBrowserDeepLinkBridge();
|
|
151
101
|
root.render(
|
|
152
102
|
<DomErrorBoundary label="Browser renderer crashed" fallback={(error) => (
|
|
153
103
|
<div className="gloom-fatal">
|
|
@@ -457,6 +457,32 @@ function WebDataTableRowInner<
|
|
|
457
457
|
|
|
458
458
|
function CellText({ cell, column, color }: { cell: DataTableCell; column: DataTableColumn; color: string }) {
|
|
459
459
|
const style = clippedCellTextStyle(column, color, cell.attributes ?? TextAttributes.NONE);
|
|
460
|
+
if (cell.note) {
|
|
461
|
+
const text = (
|
|
462
|
+
<div
|
|
463
|
+
style={{
|
|
464
|
+
display: "flex",
|
|
465
|
+
flexWrap: "wrap",
|
|
466
|
+
alignContent: "flex-start",
|
|
467
|
+
justifyContent: contentJustifyForAlign(column.align),
|
|
468
|
+
columnGap: "var(--gloom-space-sm)",
|
|
469
|
+
width: "100%",
|
|
470
|
+
height: "100%",
|
|
471
|
+
minWidth: 0,
|
|
472
|
+
overflow: "hidden",
|
|
473
|
+
}}
|
|
474
|
+
>
|
|
475
|
+
<span title={cell.text} style={{ ...style, width: "auto", flex: "0 1 auto", minWidth: 0 }}>{cell.text}</span>
|
|
476
|
+
<span data-gloom-role="data-table-cell-note" style={{ ...cellTextStyle(CSS_TEXT_DIM, TextAttributes.NONE), flex: "none" }}>{cell.note}</span>
|
|
477
|
+
</div>
|
|
478
|
+
);
|
|
479
|
+
return cell.leading === undefined ? text : (
|
|
480
|
+
<div style={{ display: "flex", alignItems: "center", gap: LABEL_GAP_PX, width: "100%", height: "100%", minWidth: 0, overflow: "hidden" }}>
|
|
481
|
+
<Leading>{cell.leading}</Leading>
|
|
482
|
+
{text}
|
|
483
|
+
</div>
|
|
484
|
+
);
|
|
485
|
+
}
|
|
460
486
|
if (cell.leading === undefined) return <span title={cell.text} style={style}>{cell.text}</span>;
|
|
461
487
|
return (
|
|
462
488
|
<div
|
|
@@ -27,6 +27,7 @@ function DefaultDesktopRow({
|
|
|
27
27
|
stacked: boolean;
|
|
28
28
|
}) {
|
|
29
29
|
const colors = useThemeColors();
|
|
30
|
+
if (item.kind === "heading") return <Text fg={colors.textMuted}>{item.label}</Text>;
|
|
30
31
|
return (
|
|
31
32
|
<Box
|
|
32
33
|
flexDirection="row"
|
|
@@ -142,6 +143,7 @@ export function WebListView({
|
|
|
142
143
|
const rowHoverBg = hoverBgColor ?? hoverBg(colors);
|
|
143
144
|
const selectedItem = selectedIndex >= 0 ? items[selectedIndex] : undefined;
|
|
144
145
|
const activeScrollIndex = scrollIndex ?? selectedIndex;
|
|
146
|
+
const headingAboveSelection = items[activeScrollIndex - 1]?.kind === "heading";
|
|
145
147
|
const rowStride = rowHeight + rowGap;
|
|
146
148
|
const tabStopIndex = selectedIndex >= 0 && items[selectedIndex] && !items[selectedIndex].disabled
|
|
147
149
|
? selectedIndex : items.findIndex((item) => !item.disabled);
|
|
@@ -176,14 +178,14 @@ export function WebListView({
|
|
|
176
178
|
if (!scrollBox) return;
|
|
177
179
|
const safeIndex = Math.min(activeScrollIndex, items.length - 1);
|
|
178
180
|
const viewportHeight = Math.max(scrollBox.viewport?.height ?? 0, 1);
|
|
179
|
-
const rowTop = safeIndex * rowStride;
|
|
180
|
-
const rowBottom =
|
|
181
|
+
const rowTop = Math.max(0, safeIndex - (headingAboveSelection ? 1 : 0)) * rowStride;
|
|
182
|
+
const rowBottom = safeIndex * rowStride + rowHeight;
|
|
181
183
|
if (rowTop < scrollBox.scrollTop) {
|
|
182
184
|
scrollBox.scrollTo(rowTop);
|
|
183
185
|
} else if (rowBottom > scrollBox.scrollTop + viewportHeight) {
|
|
184
186
|
scrollBox.scrollTo(rowBottom - viewportHeight);
|
|
185
187
|
}
|
|
186
|
-
}, [activeScrollIndex, autoScrollToIndex, items.length, rowHeight, rowStride, scrolls]);
|
|
188
|
+
}, [activeScrollIndex, autoScrollToIndex, headingAboveSelection, items.length, rowHeight, rowStride, scrolls]);
|
|
187
189
|
|
|
188
190
|
useEffect(() => {
|
|
189
191
|
if (!scrolls) return;
|
|
@@ -202,7 +204,7 @@ export function WebListView({
|
|
|
202
204
|
const list = document.getElementById(listDomId);
|
|
203
205
|
const active = document.activeElement;
|
|
204
206
|
if (!list || !active || !list.contains(active) || isEditableKeyboardTarget(active)) return;
|
|
205
|
-
const row = list.
|
|
207
|
+
const row = list.querySelector<HTMLElement>(`[data-gloom-list-index="${selectedIndex}"]`);
|
|
206
208
|
if (row && !row.contains(active)) row.focus({ preventScroll: scrolls });
|
|
207
209
|
}, [listDomId, scrolls, selectedIndex]);
|
|
208
210
|
|
|
@@ -246,10 +248,11 @@ export function WebListView({
|
|
|
246
248
|
onActivate?.(item, index);
|
|
247
249
|
}}
|
|
248
250
|
data-gloom-role="desktop-list-row"
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
aria-
|
|
252
|
-
|
|
251
|
+
data-gloom-list-index={index}
|
|
252
|
+
role={item.kind === "heading" ? "presentation" : "option"}
|
|
253
|
+
aria-selected={item.kind === "heading" ? undefined : selected}
|
|
254
|
+
aria-disabled={item.kind === "heading" ? undefined : disabled || undefined}
|
|
255
|
+
tabIndex={item.kind === "heading" ? undefined : index === tabStopIndex ? 0 : -1}
|
|
253
256
|
onKeyDown={(event: React.KeyboardEvent<HTMLElement>) => {
|
|
254
257
|
if (disabled) return;
|
|
255
258
|
if (event.key === " " || (event.key === "Enter" && !checkboxRows)) {
|
|
@@ -267,8 +270,8 @@ export function WebListView({
|
|
|
267
270
|
while (items[nextIndex]?.disabled) nextIndex += direction;
|
|
268
271
|
if (!items[nextIndex]) return;
|
|
269
272
|
onSelect?.(nextIndex);
|
|
270
|
-
const
|
|
271
|
-
|
|
273
|
+
const row = event.currentTarget.parentElement?.querySelector<HTMLElement>(`[data-gloom-list-index="${nextIndex}"]`);
|
|
274
|
+
row?.focus();
|
|
272
275
|
}}
|
|
273
276
|
style={listRowStyle(selected, disabled, colors, selection === "frame")}
|
|
274
277
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @jsxImportSource react */
|
|
2
2
|
import { useCallback, useContext, useEffect, useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode } from "react";
|
|
3
3
|
import type { HostQueryBarItem, HostQueryBarProps } from "../../../ui/host";
|
|
4
|
+
import { withChoiceGroupHeadings } from "../../../components/ui/choice-groups";
|
|
4
5
|
import { WebPopover } from "./popover";
|
|
5
6
|
import { WebMenu } from "./menu";
|
|
6
7
|
import { useHorizontalOverflow } from "../host/overflow-fade";
|
|
@@ -75,15 +76,16 @@ function QueryMenu({ item, onClose }: { item: HostQueryBarItem; onClose: () => v
|
|
|
75
76
|
<WebMenu
|
|
76
77
|
label={item.label}
|
|
77
78
|
selection={item.kind === "multi" ? "multi" : "single"}
|
|
78
|
-
items={item.options.map((option) => ({
|
|
79
|
+
items={withChoiceGroupHeadings(item.options.map((option) => ({
|
|
79
80
|
id: option.value,
|
|
80
81
|
label: option.label,
|
|
82
|
+
group: option.group,
|
|
81
83
|
description: option.description,
|
|
82
84
|
disabled: option.disabled,
|
|
83
85
|
selected: item.kind === "select" ? option.selected : undefined,
|
|
84
86
|
checked: item.kind === "multi" ? option.selected : undefined,
|
|
85
87
|
color: option.color,
|
|
86
|
-
}))}
|
|
88
|
+
})))}
|
|
87
89
|
onSelect={(value) => {
|
|
88
90
|
item.onSelect(value);
|
|
89
91
|
if (item.kind === "select") onClose();
|
|
@@ -5,6 +5,7 @@ import { WEB_CELL_HEIGHT } from "../../../theme/font-scale";
|
|
|
5
5
|
import { Box } from "../../../ui";
|
|
6
6
|
import { MenuPopover } from "../../../components/ui/menu";
|
|
7
7
|
import type { SelectFieldHandle, SelectFieldProps } from "../../../components/ui/select-field";
|
|
8
|
+
import { withChoiceGroupHeadings } from "../../../components/ui/choice-groups";
|
|
8
9
|
import { WebIcon } from "./icons";
|
|
9
10
|
import { isInsideDialogSurface } from "../host/focus-scope";
|
|
10
11
|
|
|
@@ -136,13 +137,14 @@ export function WebSelectField({
|
|
|
136
137
|
minWidth={typeof resolvedWidth === "number" ? Math.max(160, resolvedWidth) : 170}
|
|
137
138
|
items={[
|
|
138
139
|
...(showUnset ? [{ id: UNSET_VALUE, label: "Unset", selected: true, disabled: true }] : []),
|
|
139
|
-
...options.map((option) => ({
|
|
140
|
+
...withChoiceGroupHeadings(options.map((option) => ({
|
|
140
141
|
id: option.value,
|
|
141
142
|
label: option.label,
|
|
143
|
+
group: option.group,
|
|
142
144
|
description: option.description,
|
|
143
145
|
disabled: option.disabled,
|
|
144
146
|
selected: option.value === value,
|
|
145
|
-
})),
|
|
147
|
+
}))),
|
|
146
148
|
]}
|
|
147
149
|
onSelect={(id) => {
|
|
148
150
|
if (id !== UNSET_VALUE && id !== value) onChange(id);
|
|
@@ -168,6 +168,27 @@ const ChartVectors = memo(function ChartVectors({ vectors }: { vectors: readonly
|
|
|
168
168
|
/>
|
|
169
169
|
))
|
|
170
170
|
: [])}
|
|
171
|
+
{vectors.map((shape) => shape.label && shape.points[0]
|
|
172
|
+
? (
|
|
173
|
+
<div
|
|
174
|
+
key={`${shape.id}:label`}
|
|
175
|
+
style={{
|
|
176
|
+
position: "absolute",
|
|
177
|
+
left: `${shape.points[0].x * 100}%`,
|
|
178
|
+
top: `${shape.points[0].y * 100}%`,
|
|
179
|
+
transform: "translate(2px, -100%)",
|
|
180
|
+
color: shape.color,
|
|
181
|
+
fontSize: "var(--gloom-type-caption)",
|
|
182
|
+
lineHeight: 1.2,
|
|
183
|
+
whiteSpace: "nowrap",
|
|
184
|
+
pointerEvents: "none",
|
|
185
|
+
zIndex: 10,
|
|
186
|
+
}}
|
|
187
|
+
>
|
|
188
|
+
{shape.label}
|
|
189
|
+
</div>
|
|
190
|
+
)
|
|
191
|
+
: null)}
|
|
171
192
|
</>
|
|
172
193
|
);
|
|
173
194
|
});
|