@gloom-sh/terminal 0.18.5 → 0.19.1
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 +163 -8
- package/src/api-client/app-attention.ts +3 -0
- package/src/api-client/beneficial-owners.ts +3 -0
- package/src/api-client/company-kpis.ts +3 -0
- package/src/api-client/cot.ts +6 -2
- package/src/api-client/credit-documents.ts +6 -0
- package/src/api-client/data.ts +19 -7
- package/src/api-client/equity-screener.ts +24 -0
- package/src/api-client/fund-facts.ts +45 -4
- package/src/api-client/hiring.ts +3 -0
- package/src/api-client/index.ts +15 -0
- package/src/api-client/ipo.ts +24 -1
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/market-movers.ts +7 -0
- package/src/api-client/members.ts +1 -1
- package/src/api-client/mna.ts +3 -0
- package/src/api-client/paths.ts +9 -1
- package/src/api-client/perps.ts +43 -0
- package/src/api-client/research-activity.ts +3 -2
- package/src/api-client/roadmap.ts +85 -0
- package/src/api-client/types.ts +82 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -5
- package/src/app/runtime/broker-import.ts +0 -2
- package/src/app/runtime/plugin-bindings.ts +73 -56
- package/src/architecture/core-builtin-allowlist.json +2 -2
- 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/market.ts +107 -38
- package/src/cli/commands/news-search.ts +22 -0
- package/src/cli/commands/options-chain.ts +48 -7
- package/src/cli/commands/options-leaps.ts +9 -3
- package/src/cli/commands/overview.ts +147 -32
- package/src/cli/commands/search.ts +21 -1
- package/src/cli/commands/themes.ts +11 -2
- package/src/cli/commands/ticker.ts +87 -36
- package/src/cli/company-name-hint.ts +41 -0
- package/src/cli/earnings-calendar.ts +1 -1
- package/src/cli/errors.ts +25 -2
- package/src/cli/glossary.ts +31 -2
- package/src/cli/history-rows.ts +57 -9
- package/src/cli/index-roots.ts +0 -7
- package/src/cli/index.ts +2 -0
- package/src/cli/listing-arg.ts +235 -60
- package/src/cli/output-file.ts +68 -0
- package/src/cli/pane-functions/capabilities.ts +4 -0
- package/src/cli/pane-functions/catalog.ts +80 -7
- package/src/cli/pane-functions/discovery.ts +21 -1
- package/src/cli/pane-functions/dom.ts +13 -3
- package/src/cli/pane-functions/freshness.ts +93 -4
- package/src/cli/pane-functions/function-help.ts +20 -10
- package/src/cli/pane-functions/headless.ts +17 -7
- package/src/cli/pane-functions/index.ts +54 -16
- package/src/cli/pane-functions/market-session.ts +66 -4
- package/src/cli/pane-functions/options.ts +19 -1
- package/src/cli/pane-functions/resolver.ts +19 -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 +22 -11
- package/src/cli/saved-copy-persistence.ts +88 -0
- package/src/cli/ticker-resolution.ts +3 -2
- package/src/components/chart/composite/composite-chart.tsx +4 -0
- package/src/components/chart/composite/interactions.ts +6 -0
- package/src/components/chart/composite/legend.tsx +45 -7
- package/src/components/chart/composite/panel-gestures.ts +33 -0
- package/src/components/chart/composite/panel-surface.tsx +52 -3
- package/src/components/chart/composite/rasterizer.ts +24 -13
- package/src/components/chart/composite/scene.ts +39 -4
- 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/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/list/model.ts +5 -0
- package/src/components/command-bar/pane-templates/items.ts +3 -2
- package/src/components/command-bar/routes/root/runtime.ts +6 -7
- package/src/components/command-bar/selection-runtime.ts +52 -3
- package/src/components/command-bar/surface/index.tsx +2 -0
- package/src/components/command-bar/workflow/collection-actions.ts +3 -3
- package/src/components/layout/pane/capture-stamp.ts +2 -2
- package/src/components/layout/pane/footer/index.tsx +22 -6
- package/src/components/layout/pane/footer/model.ts +83 -15
- package/src/components/layout/pane/status-footer.ts +35 -2
- package/src/components/layout/status-widget-space.ts +9 -0
- package/src/components/onboarding/onboarding-wizard.tsx +4 -1
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +12 -7
- 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 +8 -21
- 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 +18 -3
- package/src/components/ui/icon.tsx +4 -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/data/config/chart-settings.ts +1 -1
- package/src/data/json-ticker-repository.ts +17 -8
- package/src/data/plugin-cache.ts +5 -3
- package/src/data/saved-copies.ts +8 -0
- 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 +103 -142
- package/src/i18n/es.ts +20 -6
- package/src/i18n/ja.ts +20 -6
- package/src/i18n/ko.ts +20 -6
- package/src/i18n/zh-cn.ts +20 -6
- package/src/i18n/zh-tw.ts +20 -6
- package/src/market-data/depositary-pair.ts +27 -3
- package/src/market-data/fund-facts.ts +50 -0
- package/src/market-data/market/change-basis.ts +16 -3
- package/src/market-data/market/format.ts +25 -0
- package/src/market-data/market/freshness.ts +2 -1
- package/src/market-data/options-alternatives.ts +81 -4
- package/src/market-data/quotes/metadata.ts +7 -0
- package/src/news/aggregator.ts +119 -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 +17 -0
- package/src/plugins/builtin/alerts/alert-engine.ts +20 -1
- package/src/plugins/builtin/alerts/alert-log.ts +33 -0
- package/src/plugins/builtin/alerts/calendar-events.ts +10 -4
- package/src/plugins/builtin/alerts/cli-forms.ts +216 -0
- package/src/plugins/builtin/alerts/cli.ts +362 -80
- package/src/plugins/builtin/alerts/command.ts +25 -1
- package/src/plugins/builtin/alerts/event-rows.ts +24 -3
- package/src/plugins/builtin/alerts/events-pane.tsx +34 -10
- package/src/plugins/builtin/alerts/fired-log.ts +73 -9
- package/src/plugins/builtin/alerts/format.ts +75 -5
- package/src/plugins/builtin/alerts/headless.ts +34 -12
- package/src/plugins/builtin/alerts/history-rows.ts +3 -2
- package/src/plugins/builtin/alerts/history.ts +1 -1
- package/src/plugins/builtin/alerts/index.tsx +79 -16
- package/src/plugins/builtin/alerts/metric-command.ts +77 -4
- package/src/plugins/builtin/alerts/metric-data.ts +54 -13
- package/src/plugins/builtin/alerts/metric-model.ts +163 -14
- package/src/plugins/builtin/alerts/metric-parity-fixture.json +1 -1
- package/src/plugins/builtin/alerts/pane.tsx +61 -23
- package/src/plugins/builtin/alerts/quotes.ts +6 -0
- package/src/plugins/builtin/alerts/storage.ts +12 -8
- package/src/plugins/builtin/alerts/types.ts +4 -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/broker-manager/index.tsx +7 -3
- 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 +6 -2
- package/src/plugins/builtin/cds/client.ts +142 -30
- package/src/plugins/builtin/cds/headless.ts +35 -8
- package/src/plugins/builtin/cds/model.ts +145 -18
- package/src/plugins/builtin/cds/pane.tsx +16 -5
- package/src/plugins/builtin/changelog/index.tsx +9 -6
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +3 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +4 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +7 -0
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -2
- package/src/plugins/builtin/chart-composer/follow-binding.ts +14 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +7 -1
- package/src/plugins/builtin/chart-composer/headless.ts +6 -1
- package/src/plugins/builtin/chart-composer/index.tsx +5 -6
- package/src/plugins/builtin/chart-composer/pane.tsx +37 -8
- package/src/plugins/builtin/chart-composer/settings.ts +27 -0
- package/src/plugins/builtin/chat/content/command-suggestions.ts +1 -0
- package/src/plugins/builtin/chat/controller/index.ts +5 -1
- package/src/plugins/builtin/chat/controller/notifications.ts +33 -3
- package/src/plugins/builtin/chat/controller/state.ts +25 -2
- package/src/plugins/builtin/chat/controller/unread-people.ts +89 -23
- package/src/plugins/builtin/chat/controller/utils.ts +7 -2
- package/src/plugins/builtin/chat/pane-links/commands.ts +7 -1
- package/src/plugins/builtin/chat/status-preview.ts +79 -0
- package/src/plugins/builtin/chat/status-widget.tsx +147 -10
- package/src/plugins/builtin/chat/unread-badge.ts +51 -10
- package/src/plugins/builtin/clinical-trials/client.ts +49 -4
- package/src/plugins/builtin/clinical-trials/model.ts +86 -31
- package/src/plugins/builtin/clinical-trials/pane.tsx +61 -49
- package/src/plugins/builtin/clinical-trials/sponsor-listing.ts +90 -0
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +95 -15
- package/src/plugins/builtin/clinical-trials/trial-pages.ts +50 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +2 -0
- 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/headless.ts +2 -1
- package/src/plugins/builtin/company-attention/moves.tsx +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +12 -2
- package/src/plugins/builtin/company-attention/signals.tsx +5 -1
- package/src/plugins/builtin/company-kpis/headless.ts +8 -3
- package/src/plugins/builtin/company-kpis/model.ts +73 -5
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/composite-plugins.ts +2 -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 +10 -10
- 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/doe/headless.ts +3 -2
- package/src/plugins/builtin/doe/pane.tsx +13 -3
- 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/data.ts +18 -6
- package/src/plugins/builtin/earnings-calls/format.ts +31 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +20 -5
- package/src/plugins/builtin/earnings-calls/model.ts +6 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +12 -4
- package/src/plugins/builtin/econ/calendar-model.ts +48 -1
- package/src/plugins/builtin/econ/calendar-source.ts +4 -2
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/figures.ts +48 -0
- package/src/plugins/builtin/econ/index.tsx +14 -5
- package/src/plugins/builtin/econ/print-watch.ts +3 -1
- package/src/plugins/builtin/econ/types.ts +2 -0
- package/src/plugins/builtin/econ-statistics/client.ts +11 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +6 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +16 -6
- package/src/plugins/builtin/econ-statistics/pane.tsx +8 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +39 -9
- 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 +68 -13
- package/src/plugins/builtin/fixed-income/pane.tsx +2 -1
- 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 +6 -3
- package/src/plugins/builtin/fx-matrix/headless.ts +1 -1
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -2
- package/src/plugins/builtin/fx-matrix/live-legs.ts +42 -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 +62 -59
- package/src/plugins/builtin/help/shortcut-model.ts +1 -1
- package/src/plugins/builtin/help/shortcut-table.tsx +5 -6
- package/src/plugins/builtin/help/table-cells.tsx +13 -2
- package/src/plugins/builtin/holders/beneficial-client.ts +5 -1
- package/src/plugins/builtin/holders/beneficial-view.tsx +3 -0
- package/src/plugins/builtin/holders/fund-holders.ts +51 -0
- package/src/plugins/builtin/holders/headless.ts +22 -3
- package/src/plugins/builtin/holders/pane.tsx +3 -0
- package/src/plugins/builtin/holders/report-rows.ts +4 -1
- package/src/plugins/builtin/insider/headless.ts +2 -2
- package/src/plugins/builtin/ipo-calendar/client.ts +18 -2
- package/src/plugins/builtin/ipo-calendar/headless.ts +75 -11
- package/src/plugins/builtin/ipo-calendar/listing-ipo.ts +160 -0
- package/src/plugins/builtin/ipo-calendar/model.ts +98 -2
- 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 +33 -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/headless.ts +12 -5
- package/src/plugins/builtin/macro-day/index.tsx +1 -1
- package/src/plugins/builtin/macro-day/model.ts +39 -5
- package/src/plugins/builtin/macro-day/pane.tsx +27 -19
- 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 +27 -7
- package/src/plugins/builtin/market-movers/headless.ts +34 -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 +22 -4
- 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 +2 -1
- package/src/plugins/builtin/mna/headless.ts +2 -0
- package/src/plugins/builtin/mna/pane.tsx +3 -1
- package/src/plugins/builtin/news/headless.ts +3 -1
- package/src/plugins/builtin/news/index.tsx +4 -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 +29 -5
- package/src/plugins/builtin/options/enrichment.ts +17 -5
- package/src/plugins/builtin/options/table.ts +5 -2
- package/src/plugins/builtin/options/types.ts +2 -0
- package/src/plugins/builtin/options/view.tsx +17 -4
- package/src/plugins/builtin/options-positioning/client.ts +11 -0
- package/src/plugins/builtin/options-positioning/headless.ts +21 -8
- package/src/plugins/builtin/options-positioning/index.tsx +1 -1
- package/src/plugins/builtin/options-positioning/model.ts +78 -9
- package/src/plugins/builtin/options-positioning/pane.tsx +21 -6
- 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/headless.ts +65 -9
- package/src/plugins/builtin/perps/index.tsx +7 -5
- package/src/plugins/builtin/perps/model.ts +18 -4
- package/src/plugins/builtin/perps/pane.tsx +19 -22
- 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 +7 -5
- package/src/plugins/builtin/portfolio-list/pane/futures-front.ts +40 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -7
- 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/index.tsx +0 -14
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +5 -2
- package/src/plugins/builtin/portfolio-list/table.tsx +15 -9
- package/src/plugins/builtin/primary-dealers/client.ts +13 -38
- package/src/plugins/builtin/realized-vol/client.ts +13 -5
- package/src/plugins/builtin/realized-vol/evidence.ts +29 -4
- package/src/plugins/builtin/realized-vol/headless.ts +8 -4
- package/src/plugins/builtin/realized-vol/index.tsx +2 -2
- package/src/plugins/builtin/realized-vol/model.ts +37 -6
- package/src/plugins/builtin/realized-vol/pane.tsx +11 -9
- 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 +40 -12
- package/src/plugins/builtin/research/headless.ts +1 -1
- package/src/plugins/builtin/research/index.tsx +7 -3
- package/src/plugins/builtin/research/relative-valuation-headless.ts +13 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +31 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +59 -20
- package/src/plugins/builtin/research/relative-valuation-peers.ts +217 -20
- package/src/plugins/builtin/research/relative-valuation-settings.ts +44 -0
- 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/risk-factors/data.ts +4 -2
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/roadmap/index.tsx +28 -0
- package/src/plugins/builtin/roadmap/model.ts +67 -0
- package/src/plugins/builtin/roadmap/pane.tsx +244 -0
- 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 +16 -5
- package/src/plugins/builtin/scanner/live-headless.ts +48 -5
- package/src/plugins/builtin/scanner/live-model.ts +11 -0
- package/src/plugins/builtin/scanner/live-pane.tsx +3 -3
- 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 +4 -2
- package/src/plugins/builtin/sec/index.tsx +3 -0
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +16 -7
- 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/headless-market-data.ts +2 -2
- package/src/plugins/builtin/shared/job-posting.ts +1 -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 +11 -2
- package/src/plugins/builtin/shared/research-cells.tsx +1 -1
- package/src/plugins/builtin/shared/series-cache.ts +4 -4
- 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 +2 -1
- package/src/plugins/builtin/shared/volatility/live-session.ts +34 -8
- package/src/plugins/builtin/shared/volatility/pricing.ts +19 -0
- package/src/plugins/builtin/shared/wall-view-lifecycle.ts +3 -1
- package/src/plugins/builtin/themes/model.ts +16 -7
- package/src/plugins/builtin/themes/pane.tsx +5 -5
- package/src/plugins/builtin/thirteenf/api.ts +12 -1
- package/src/plugins/builtin/thirteenf/data.ts +7 -7
- package/src/plugins/builtin/thirteenf/headless.ts +31 -4
- 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 +11 -3
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/pane.tsx +14 -8
- 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-auctions/headless.ts +21 -12
- package/src/plugins/builtin/treasury-auctions/pane.tsx +9 -3
- 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/client.ts +3 -13
- package/src/plugins/builtin/vol-surface/headless.ts +3 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/vol-surface/pane.tsx +7 -5
- package/src/plugins/builtin/volatility/index.tsx +2 -2
- package/src/plugins/builtin/volatility/pane.tsx +7 -4
- package/src/plugins/builtin/world-venue-map/headless.ts +3 -3
- package/src/plugins/builtin/yield-curve/client.ts +61 -1
- package/src/plugins/builtin/yield-curve/headless.ts +9 -6
- package/src/plugins/builtin/yield-curve/index.tsx +34 -10
- package/src/plugins/builtin/yield-curve/swaps.tsx +9 -5
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/catalog-manifest.ts +2 -1
- package/src/plugins/host-link.ts +1 -1
- package/src/plugins/marketplace/model.ts +18 -5
- package/src/portfolio/column-values.ts +11 -7
- package/src/portfolio/futures-positions.ts +6 -3
- package/src/portfolio/position-quantity.ts +15 -9
- package/src/remote/resources.ts +2 -1
- package/src/renderers/dom/data-table/row.tsx +26 -0
- package/src/renderers/dom/desktop/icons.tsx +7 -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 +3 -3
- package/src/renderers/electrobun/bun/desktop/backend.ts +21 -10
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +15 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/installer-folder.ts +731 -0
- package/src/renderers/electrobun/bun/desktop/relaunch.ts +102 -10
- package/src/renderers/electrobun/bun/desktop/update.ts +115 -14
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +52 -0
- package/src/renderers/electrobun/bun/desktop/windows-script.ts +92 -0
- package/src/renderers/electrobun/bun/index.ts +26 -2
- package/src/renderers/electrobun/bun/window/create.ts +43 -4
- package/src/renderers/electrobun/bun/window/events.ts +20 -0
- package/src/renderers/electrobun/bun/window/windows-custom-chrome.ts +9 -2
- package/src/renderers/electrobun/bun/window/windows-native.ts +78 -0
- package/src/renderers/electrobun/bun/window/windows-quit.ts +57 -0
- package/src/renderers/electrobun/shared/app-name.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +12 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +6 -0
- package/src/renderers/electrobun/view/main.tsx +24 -1
- package/src/renderers/electrobun/view/news-source.ts +5 -1
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +14 -7
- package/src/renderers/electrobun/view/ui-host.tsx +8 -0
- package/src/renderers/electrobun/view/view-ids.ts +85 -0
- package/src/renderers/opentui/start.tsx +5 -0
- 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/fred-series.ts +3 -1
- package/src/sources/gloomberb-cloud/index.ts +43 -8
- package/src/sources/gloomberb-cloud/news.ts +47 -7
- package/src/sources/provider-router/financials.ts +15 -3
- package/src/sources/provider-router/index.ts +8 -5
- package/src/state/ticker-cleanup.ts +50 -0
- package/src/sync/controller.ts +4 -3
- package/src/sync/core-contributors.ts +90 -31
- 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/test-support/preload.ts +14 -0
- package/src/theme/themes.ts +10 -0
- package/src/tickers/company-name-listing.ts +53 -13
- package/src/tickers/company-name.ts +50 -4
- package/src/tickers/index-roots.ts +7 -0
- package/src/tickers/listing-fate.ts +2 -2
- package/src/tickers/listing-venues.ts +15 -3
- package/src/tickers/search/index.ts +6 -2
- package/src/tickers/search/ranking.ts +5 -1
- package/src/tickers/search/upsert.ts +13 -0
- package/src/tickers/terminal-codes.ts +19 -0
- package/src/tickers/ticker-changes.ts +8 -4
- package/src/time-series/alignment.ts +1 -1
- package/src/time-series/economic.ts +18 -4
- package/src/time-series/field-catalog.ts +1 -1
- package/src/time-series/filed-trailing-eps.ts +197 -0
- package/src/time-series/fundamentals.ts +44 -1
- package/src/time-series/ice-credit.ts +3 -0
- package/src/time-series/price-comparison.ts +30 -2
- package/src/time-series/resolve-context.ts +3 -1
- package/src/time-series/resolve.ts +56 -4
- package/src/time-series/session-bar.ts +11 -0
- package/src/time-series/spec.ts +3 -2
- package/src/time-series/studies.ts +8 -2
- package/src/time-series/total-return.ts +160 -0
- package/src/time-series/transforms.ts +2 -3
- package/src/time-series/types.ts +22 -1
- package/src/types/company-from.ts +40 -0
- package/src/types/data-provider.ts +7 -0
- package/src/types/financials.ts +59 -1
- package/src/types/headless.ts +27 -3
- package/src/types/news-source.ts +1 -0
- package/src/types/plugin.ts +9 -0
- package/src/ui/host.tsx +3 -0
- package/src/updater/failure.ts +4 -1
- package/src/utils/cli-output.ts +42 -1
- package/src/utils/crypto-pair.ts +165 -7
- package/src/utils/declared-dividends.ts +1 -1
- package/src/utils/forward-dividend.ts +2 -0
- package/src/utils/fundamentals.ts +60 -8
- 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/price-history.ts +7 -1
- package/src/utils/shell-word.ts +8 -0
- package/src/utils/trailing-dividend.ts +53 -4
- package/src/version.ts +2 -2
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +0 -17
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { displayWidth } from "../../../../utils/format";
|
|
2
|
-
import { tableColumnLeadGap } from "../../table-layout";
|
|
2
|
+
import { fitTableCellText, tableColumnLeadGap } from "../../table-layout";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Where the viewport cuts a column: `inset` cells hidden on its left (past the
|
|
@@ -46,6 +46,31 @@ export function cutColumnText(
|
|
|
46
46
|
return `${" ".repeat(start - clip.inset)}${body}${" ".repeat(shownEnd - end)}`;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/** A note uses only spare room: neither the label nor part of the note is cut to fit it. */
|
|
50
|
+
export function fitColumnCellText(
|
|
51
|
+
text: string,
|
|
52
|
+
width: number,
|
|
53
|
+
align: string | undefined,
|
|
54
|
+
clip: DataTableColumnClip | null,
|
|
55
|
+
note?: string,
|
|
56
|
+
): { text: string; note?: string; padding?: string } {
|
|
57
|
+
const fit = (value: string) => clip
|
|
58
|
+
? cutColumnText(value, align, width, clip, (body, shown) => fitTableCellText(body, shown, align))
|
|
59
|
+
: width > 0 ? fitTableCellText(value, width, align) : "";
|
|
60
|
+
const combined = note ? `${text} ${note}` : "";
|
|
61
|
+
if (combined && displayWidth(combined) <= (clip?.width ?? width)) {
|
|
62
|
+
const fitted = fit(combined);
|
|
63
|
+
const start = fitted.indexOf(combined);
|
|
64
|
+
// A right-aligned value may fit the visible width but sit beyond its edge.
|
|
65
|
+
if (start >= 0) return {
|
|
66
|
+
text: fitted.slice(0, start + text.length + 1),
|
|
67
|
+
note,
|
|
68
|
+
padding: fitted.slice(start + combined.length),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return { text: fit(text) };
|
|
72
|
+
}
|
|
73
|
+
|
|
49
74
|
function sameClip(a: DataTableColumnClip | null, b: DataTableColumnClip | null): boolean {
|
|
50
75
|
return a === b || (a !== null && b !== null && a.inset === b.inset && a.width === b.width);
|
|
51
76
|
}
|
|
@@ -24,6 +24,8 @@ export type DataTableColumn = Pick<
|
|
|
24
24
|
|
|
25
25
|
export interface DataTableCell {
|
|
26
26
|
text: string;
|
|
27
|
+
/** Muted context after `text`, shown whole only when both fit on one line. Does not change the exported value. */
|
|
28
|
+
note?: string;
|
|
27
29
|
/**
|
|
28
30
|
* What CSV export writes instead of `text`: the full-precision number behind
|
|
29
31
|
* it (3.45 for +3.45%, 1234567890 for 1.23B), or a date as an ISO string or
|
|
@@ -7,6 +7,7 @@ import { Box, Text, TextAttributes, useUiCapabilities } from "../../ui";
|
|
|
7
7
|
import { truncateToDisplayWidth } from "../../utils/format";
|
|
8
8
|
import { CountryFlagLead } from "./country-flag";
|
|
9
9
|
import { usePaneLinkMenuEntry } from "./external-link";
|
|
10
|
+
import { ICON_GLYPHS, Icon, type IconName } from "./icon";
|
|
10
11
|
import { titleCase } from "./header-case";
|
|
11
12
|
import { statToneColor, type StatTone } from "./stat-grid";
|
|
12
13
|
|
|
@@ -199,6 +200,10 @@ export interface BadgeProps {
|
|
|
199
200
|
/** For a domain scale, such as a sentiment score or chart series. */
|
|
200
201
|
color?: string;
|
|
201
202
|
variant?: "subtle" | "solid";
|
|
203
|
+
/** A mark before the label, in its colour: an SVG on the desktop, its glyph in the terminal. */
|
|
204
|
+
icon?: IconName;
|
|
205
|
+
/** False for a label that is not English to translate, such as a username. */
|
|
206
|
+
translate?: boolean;
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
/**
|
|
@@ -210,8 +215,9 @@ export const NATIVE_BADGE_STYLE = { height: "calc(100% - 2px)", borderRadius: "v
|
|
|
210
215
|
/** How far a subtle chip's fill is tinted toward its tone. */
|
|
211
216
|
export const BADGE_TINT = 0.28;
|
|
212
217
|
const NATIVE_BADGE_TEXT_STYLE = { fontWeight: "var(--gloom-weight-regular)" };
|
|
218
|
+
const NATIVE_ICON_BADGE_STYLE = { ...NATIVE_BADGE_STYLE, gap: "var(--gloom-space-xs)" };
|
|
213
219
|
|
|
214
|
-
export function Badge({ label, tone = "neutral", color, variant = "subtle" }: BadgeProps) {
|
|
220
|
+
export function Badge({ label, tone = "neutral", color, variant = "subtle", icon, translate = true }: BadgeProps) {
|
|
215
221
|
const colors = useThemeColors();
|
|
216
222
|
const { nativePaneChrome } = useUiCapabilities();
|
|
217
223
|
const accent = color ?? (tone === "neutral" ? colors.textDim : tone === "accent" ? colors.borderFocused : colors[tone]);
|
|
@@ -220,10 +226,19 @@ export function Badge({ label, tone = "neutral", color, variant = "subtle" }: Ba
|
|
|
220
226
|
const background = neutral ? colors.selected : solid ? accent : blendHex(colors.bg, accent, BADGE_TINT);
|
|
221
227
|
const baseForeground = neutral ? colors.selectedText : solid ? colors.bg : accent;
|
|
222
228
|
const foreground = blendForContrast(baseForeground, background, higherContrast("#000000", "#ffffff", background), 4.5);
|
|
229
|
+
const text = translate ? t(label) : label;
|
|
230
|
+
const nativeIcon = nativePaneChrome && icon;
|
|
231
|
+
// The terminal draws the icon's glyph as text in front of the label.
|
|
232
|
+
const shown = icon && !nativePaneChrome ? [ICON_GLYPHS[icon], text].filter(Boolean).join(" ") : text;
|
|
223
233
|
const chip = (
|
|
224
234
|
<Box height={nativePaneChrome ? undefined : 1} paddingX={1} backgroundColor={background}
|
|
225
|
-
data-gloom-ui="badge"
|
|
226
|
-
|
|
235
|
+
data-gloom-ui="badge" {...(nativeIcon ? { flexDirection: "row", alignItems: "center" } as const : {})}
|
|
236
|
+
justifyContent={nativePaneChrome && !icon ? "center" : undefined}
|
|
237
|
+
style={nativePaneChrome ? icon ? NATIVE_ICON_BADGE_STYLE : NATIVE_BADGE_STYLE : undefined}>
|
|
238
|
+
{nativeIcon ? <Icon name={nativeIcon} color={foreground} /> : null}
|
|
239
|
+
{shown || !nativeIcon ? (
|
|
240
|
+
<Text fg={foreground} attributes={TextAttributes.BOLD} style={nativePaneChrome ? NATIVE_BADGE_TEXT_STYLE : undefined}>{shown}</Text>
|
|
241
|
+
) : null}
|
|
227
242
|
</Box>
|
|
228
243
|
);
|
|
229
244
|
return nativePaneChrome ? <Box height={1} flexShrink={0} justifyContent="center">{chip}</Box> : chip;
|
|
@@ -38,7 +38,8 @@ export type IconName =
|
|
|
38
38
|
| "team"
|
|
39
39
|
| "pro"
|
|
40
40
|
| "clock"
|
|
41
|
-
| "edit"
|
|
41
|
+
| "edit"
|
|
42
|
+
| "mail";
|
|
42
43
|
|
|
43
44
|
/** Terminal glyph for each icon; the desktop host draws SVG. */
|
|
44
45
|
export const ICON_GLYPHS: Record<IconName, string> = {
|
|
@@ -84,6 +85,8 @@ export const ICON_GLYPHS: Record<IconName, string> = {
|
|
|
84
85
|
// Time, for data that arrives late (a delayed quote).
|
|
85
86
|
clock: "◷",
|
|
86
87
|
edit: "✎",
|
|
88
|
+
// A message written to you (a DM): text presentation, one cell.
|
|
89
|
+
mail: "✉",
|
|
87
90
|
};
|
|
88
91
|
|
|
89
92
|
export interface IconProps {
|
|
@@ -15,6 +15,7 @@ export interface ListViewItem {
|
|
|
15
15
|
description?: string;
|
|
16
16
|
detail?: string;
|
|
17
17
|
category?: string;
|
|
18
|
+
/** `heading` draws a muted group label; pair it with `disabled: true`. */
|
|
18
19
|
kind?: string;
|
|
19
20
|
right?: string;
|
|
20
21
|
checked?: boolean;
|
|
@@ -148,6 +149,7 @@ function DefaultRow({
|
|
|
148
149
|
selected: boolean;
|
|
149
150
|
}) {
|
|
150
151
|
const colors = useThemeColors();
|
|
152
|
+
if (item.kind === "heading") return <Text fg={colors.textMuted}>{t(item.label)}</Text>;
|
|
151
153
|
// The label gives way to the detail: a long label is cut with an ellipsis
|
|
152
154
|
// instead of wrapping under the row or running into the right column.
|
|
153
155
|
return (
|
|
@@ -289,6 +291,7 @@ export function ListView({
|
|
|
289
291
|
const rowHoverBg = hoverBgColor ?? hoverBg(colors);
|
|
290
292
|
const selectedItem = selectedIndex >= 0 ? items[selectedIndex] : undefined;
|
|
291
293
|
const activeScrollIndex = scrollIndex ?? selectedIndex;
|
|
294
|
+
const headingAboveSelection = items[activeScrollIndex - 1]?.kind === "heading";
|
|
292
295
|
const terminalRowHeight = rowHeight ?? 1;
|
|
293
296
|
const terminalRowGap = rowGap ?? 0;
|
|
294
297
|
const rowStride = terminalRowHeight + terminalRowGap;
|
|
@@ -299,13 +302,14 @@ export function ListView({
|
|
|
299
302
|
if (!sb) return;
|
|
300
303
|
const safeIndex = Math.min(activeScrollIndex, items.length - 1);
|
|
301
304
|
const viewportH = Math.max(sb.viewport?.height ?? 1, 1);
|
|
302
|
-
const rowTop = safeIndex * rowStride;
|
|
305
|
+
const rowTop = Math.max(0, safeIndex - (headingAboveSelection ? 1 : 0)) * rowStride;
|
|
306
|
+
const rowBottom = safeIndex * rowStride + terminalRowHeight;
|
|
303
307
|
if (rowTop < sb.scrollTop) {
|
|
304
308
|
sb.scrollTo(rowTop);
|
|
305
|
-
} else if (
|
|
306
|
-
sb.scrollTo(
|
|
309
|
+
} else if (rowBottom > sb.scrollTop + viewportH) {
|
|
310
|
+
sb.scrollTo(rowBottom - viewportH);
|
|
307
311
|
}
|
|
308
|
-
}, [activeScrollIndex, autoScrollToIndex, items.length, rowStride, scrollable, terminalRowHeight]);
|
|
312
|
+
}, [activeScrollIndex, autoScrollToIndex, headingAboveSelection, items.length, rowStride, scrollable, terminalRowHeight]);
|
|
309
313
|
useEffect(revealActiveRow, [revealActiveRow]);
|
|
310
314
|
// A list that opens on a row past the fold has nothing to scroll until its
|
|
311
315
|
// first computed layout sizes the viewport and the rows.
|
|
@@ -12,6 +12,7 @@ import type { QueryBarFilter, QueryBarSearch, QueryBarView } from "./query-bar";
|
|
|
12
12
|
interface ChoiceOption {
|
|
13
13
|
value: string;
|
|
14
14
|
label: string;
|
|
15
|
+
group?: string;
|
|
15
16
|
description?: string;
|
|
16
17
|
disabled?: boolean;
|
|
17
18
|
color?: string;
|
|
@@ -70,6 +71,7 @@ export function useQueryBarKeys({
|
|
|
70
71
|
choices={options.map((option) => ({
|
|
71
72
|
id: option.value,
|
|
72
73
|
label: option.label,
|
|
74
|
+
group: option.group,
|
|
73
75
|
description: option.description,
|
|
74
76
|
disabled: option.disabled,
|
|
75
77
|
color: option.color,
|
|
@@ -417,6 +417,7 @@ export function QueryBar({ width, search, filters = [], view, meta: given, asOf,
|
|
|
417
417
|
options: filter.options.map((option) => ({
|
|
418
418
|
value: option.value,
|
|
419
419
|
label: option.label,
|
|
420
|
+
group: option.group,
|
|
420
421
|
description: option.description,
|
|
421
422
|
disabled: option.disabled,
|
|
422
423
|
selected: option.value === filter.value,
|
|
@@ -18,6 +18,8 @@ export interface SelectControl {
|
|
|
18
18
|
export interface SelectButtonOption<T extends string = string> {
|
|
19
19
|
value: T;
|
|
20
20
|
label: string;
|
|
21
|
+
/** Heading for a contiguous group of choices; never selectable itself. */
|
|
22
|
+
group?: string;
|
|
21
23
|
/** Trigger wording when the full label is too wide for a pane header. */
|
|
22
24
|
short?: string;
|
|
23
25
|
description?: string;
|
|
@@ -130,6 +132,7 @@ export function SelectButton<T extends string = string>({
|
|
|
130
132
|
choices={options.map((option) => ({
|
|
131
133
|
id: option.value,
|
|
132
134
|
label: option.label,
|
|
135
|
+
group: option.group,
|
|
133
136
|
description: option.description,
|
|
134
137
|
disabled: option.disabled,
|
|
135
138
|
color: option.color,
|
|
@@ -158,7 +161,7 @@ export function SelectButton<T extends string = string>({
|
|
|
158
161
|
selectRef={(element) => { selectFieldRef.current = element; }}
|
|
159
162
|
onFocus={onFocus}
|
|
160
163
|
value={value}
|
|
161
|
-
options={options.map((option) => ({ value: option.value, label: option.label, disabled: option.disabled }))}
|
|
164
|
+
options={options.map((option) => ({ value: option.value, label: option.label, group: option.group, disabled: option.disabled }))}
|
|
162
165
|
disabled={disabled}
|
|
163
166
|
onChange={selectValue}
|
|
164
167
|
/>
|
|
@@ -180,6 +183,7 @@ export function SelectButton<T extends string = string>({
|
|
|
180
183
|
options={options.map((option) => ({
|
|
181
184
|
value: option.value,
|
|
182
185
|
label: option.label,
|
|
186
|
+
group: option.group,
|
|
183
187
|
disabled: option.disabled,
|
|
184
188
|
}))}
|
|
185
189
|
disabled={disabled}
|
|
@@ -106,18 +106,21 @@ export function getTableWidth(
|
|
|
106
106
|
* The columns that fit in `width` cells: whole columns in `dropOrder` (least
|
|
107
107
|
* needed first) give way until the rest fit, rather than the table's right
|
|
108
108
|
* edge cutting a value, so a narrow pane drops a name that repeats its ticker
|
|
109
|
-
* before it cuts a date.
|
|
110
|
-
*
|
|
109
|
+
* before it cuts a date. An entry that lists several ids drops them together,
|
|
110
|
+
* for columns that mean little apart (a bid's venue and an ask's). Columns not
|
|
111
|
+
* listed stay at every width. A table that scrolls vertically passes its width
|
|
112
|
+
* less the scrollbar's cell.
|
|
111
113
|
*/
|
|
112
114
|
export function dropColumnsToFit<C extends TableWidthColumn & { id: string }>(
|
|
113
115
|
columns: readonly C[],
|
|
114
116
|
width: number,
|
|
115
|
-
dropOrder: readonly string[],
|
|
117
|
+
dropOrder: readonly (string | readonly string[])[],
|
|
116
118
|
): C[] {
|
|
117
119
|
let shown = [...columns];
|
|
118
|
-
for (const
|
|
120
|
+
for (const step of dropOrder) {
|
|
119
121
|
if (getTableWidth(shown) <= width) break;
|
|
120
|
-
|
|
122
|
+
const ids = typeof step === "string" ? [step] : step;
|
|
123
|
+
shown = shown.filter((column) => !ids.includes(column.id));
|
|
121
124
|
}
|
|
122
125
|
return shown;
|
|
123
126
|
}
|
package/src/core/app-runtime.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MarketDataCoordinator, getSharedMarketDataCoordinator, setSharedMarketDataCoordinator } from "../market-data/coordinator";
|
|
2
2
|
import { NewsService, type NewsServiceOptions } from "../news/aggregator";
|
|
3
|
+
import { cloudNewsSession } from "../news/cloud-session";
|
|
3
4
|
import { getSharedNewsService, setSharedNewsService } from "../news/hooks";
|
|
4
5
|
import { PluginRegistry } from "../plugins/registry";
|
|
5
6
|
import { releaseSharedRegistry } from "../plugins/registry/shared";
|
|
@@ -61,6 +62,7 @@ export function createAppRuntime({
|
|
|
61
62
|
const newsService = new NewsService({
|
|
62
63
|
connectionHealth: pluginRegistry.connectionHealth,
|
|
63
64
|
pollIntervalMs: () => Math.max(1, config.refreshIntervalMinutes) * 60_000,
|
|
65
|
+
session: cloudNewsSession,
|
|
64
66
|
...newsOptions,
|
|
65
67
|
});
|
|
66
68
|
const modules = { pluginRegistry, marketData, newsService };
|
package/src/core/app-services.ts
CHANGED
|
@@ -27,8 +27,8 @@ export function createAppServices({ config, plugins, externalPlugins }: AppServi
|
|
|
27
27
|
provider: {
|
|
28
28
|
fetchNews: async (query) => (await newsService.load(query)).articles,
|
|
29
29
|
fetchNewsPage: async (query) => {
|
|
30
|
-
const { articles, error, nextCursor } = await newsService.load(query);
|
|
31
|
-
return { articles, error, nextCursor };
|
|
30
|
+
const { articles, error, nextCursor, access } = await newsService.load(query);
|
|
31
|
+
return { articles, error, nextCursor, access };
|
|
32
32
|
},
|
|
33
33
|
getCachedNews: (query) => newsService.getQueryState(query).articles,
|
|
34
34
|
},
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { recordOrNull } from "../../utils/guards";
|
|
21
21
|
|
|
22
22
|
const CHART_RANGES = new Set<TimeRange>(TIME_RANGES);
|
|
23
|
-
const PRICE_RENDER_MODES = new Set<SeriesStyle>(["area", "line", "candles", "ohlc", "hlc"]);
|
|
23
|
+
const PRICE_RENDER_MODES = new Set<SeriesStyle>(["area", "line", "candles", "hollow", "heikin-ashi", "ohlc", "hlc"]);
|
|
24
24
|
const LEGACY_INDICATOR_IDS = new Set<LegacyChartIndicatorId>([
|
|
25
25
|
"volume",
|
|
26
26
|
"sma20",
|
|
@@ -4,6 +4,7 @@ import { hydrateTickerMetadata } from "../tickers/metadata";
|
|
|
4
4
|
import type { TickerMetadata, TickerRecord } from "../types/ticker";
|
|
5
5
|
import { BROWSER_STORAGE_KEYS, SafeJsonStorage, type StorageLike } from "./json-storage";
|
|
6
6
|
import { isRecord } from "../utils/guards";
|
|
7
|
+
import { runTickerWrite } from "./ticker-writes";
|
|
7
8
|
|
|
8
9
|
type StoredTickers = Record<string, TickerMetadata>;
|
|
9
10
|
|
|
@@ -39,20 +40,28 @@ export class JsonTickerRepository implements AppTickerRepositoryPort {
|
|
|
39
40
|
return metadata ? hydrate(metadata) : null;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
private writeTicker(ticker: TickerRecord): void {
|
|
43
44
|
const symbol = normalizeSymbol(ticker.metadata.ticker);
|
|
44
45
|
this.data.set({ ...this.data.get(), [symbol]: ticker.metadata });
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
saveTicker(ticker: TickerRecord): Promise<void> {
|
|
49
|
+
return runTickerWrite(this, ticker.metadata.ticker, () => this.writeTicker(ticker));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
createTicker(metadata: TickerMetadata): Promise<TickerRecord> {
|
|
48
53
|
const ticker = { metadata };
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
return runTickerWrite(this, metadata.ticker, () => {
|
|
55
|
+
this.writeTicker(ticker);
|
|
56
|
+
return ticker;
|
|
57
|
+
});
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
deleteTicker(symbol: string): Promise<void> {
|
|
61
|
+
return runTickerWrite(this, symbol, () => {
|
|
62
|
+
const tickers = { ...this.data.get() };
|
|
63
|
+
delete tickers[normalizeSymbol(symbol)];
|
|
64
|
+
this.data.set(tickers);
|
|
65
|
+
});
|
|
57
66
|
}
|
|
58
67
|
}
|
package/src/data/plugin-cache.ts
CHANGED
|
@@ -108,11 +108,13 @@ export function createPluginCache<T, Stored = T>(options: {
|
|
|
108
108
|
}
|
|
109
109
|
return { value, fetchedAt, staleAt: fetchedAt + options.policy.staleMs, expiresAt: fetchedAt + options.policy.expireMs, source: options.source };
|
|
110
110
|
} });
|
|
111
|
+
// A retained copy carries its refresh failure, whatever was thrown (an Error without a message included).
|
|
112
|
+
const failed = "refreshError" in result;
|
|
111
113
|
const error = result.refreshError;
|
|
112
114
|
return {
|
|
113
|
-
data: result.value, fetchedAt: result.fetchedAt, stale:
|
|
114
|
-
source:
|
|
115
|
-
...(
|
|
115
|
+
data: result.value, fetchedAt: result.fetchedAt, stale: failed || result.staleAt <= Date.now(),
|
|
116
|
+
source: failed ? "stale-fallback" : result === before ? "cache" : "network",
|
|
117
|
+
...(failed ? { error, refreshError: error instanceof Error ? error.message : String(error) } : {}),
|
|
116
118
|
};
|
|
117
119
|
},
|
|
118
120
|
};
|
package/src/data/saved-copies.ts
CHANGED
|
@@ -56,6 +56,14 @@ export function savedCopyMark(value: unknown): object {
|
|
|
56
56
|
return savedAt != null ? { [SAVED_AT]: savedAt } : {};
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* The refresh failure a command still prints for `result`: none when a saved
|
|
61
|
+
* copy answered for it (`servedFromSavedCopy`), whose closing line says so.
|
|
62
|
+
*/
|
|
63
|
+
export function unansweredRefreshError(result: { refreshError?: string | null } | null | undefined): string | null {
|
|
64
|
+
return result?.refreshError && savedCopyAt(result) == null ? result.refreshError : null;
|
|
65
|
+
}
|
|
66
|
+
|
|
59
67
|
/** When `value` itself was saved, if it is a saved copy served after a failed refresh; null otherwise. */
|
|
60
68
|
export function savedCopyAt(value: unknown): number | null {
|
|
61
69
|
const savedAt = value && typeof value === "object" ? (value as Marked)[SAVED_AT] : undefined;
|
|
@@ -2,6 +2,7 @@ import { logFailure } from "../utils/log-failure";
|
|
|
2
2
|
import type { TickerRecord, TickerMetadata } from "../types/ticker";
|
|
3
3
|
import type { TickerStore } from "./ticker-store";
|
|
4
4
|
import { hydrateTickerMetadata } from "../tickers/metadata";
|
|
5
|
+
import { runTickerWrite } from "./ticker-writes";
|
|
5
6
|
|
|
6
7
|
function parseTickerMetadata(json: string): TickerMetadata {
|
|
7
8
|
return hydrateTickerMetadata(JSON.parse(json) as Record<string, unknown>);
|
|
@@ -32,22 +33,28 @@ export class TickerRepository {
|
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
this
|
|
36
|
+
saveTicker(ticker: TickerRecord): Promise<void> {
|
|
37
|
+
return runTickerWrite(this, ticker.metadata.ticker, () => {
|
|
38
|
+
this.tickers.save(ticker.metadata.ticker, ticker.metadata);
|
|
39
|
+
});
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/** Saves several tickers in one write. */
|
|
40
|
-
|
|
41
|
-
this
|
|
43
|
+
saveTickers(tickers: readonly TickerRecord[]): Promise<void> {
|
|
44
|
+
return runTickerWrite(this, tickers.map((ticker) => ticker.metadata.ticker), () => {
|
|
45
|
+
this.tickers.saveMany(tickers.map((ticker) => ({ symbol: ticker.metadata.ticker, metadata: ticker.metadata })));
|
|
46
|
+
});
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
createTicker(metadata: TickerMetadata): Promise<TickerRecord> {
|
|
45
50
|
const ticker: TickerRecord = { metadata };
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
return runTickerWrite(this, metadata.ticker, () => {
|
|
52
|
+
this.tickers.save(metadata.ticker, metadata);
|
|
53
|
+
return ticker;
|
|
54
|
+
});
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
this.tickers.delete(symbol);
|
|
57
|
+
deleteTicker(symbol: string): Promise<void> {
|
|
58
|
+
return runTickerWrite(this, symbol, () => this.tickers.delete(symbol));
|
|
52
59
|
}
|
|
53
60
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
interface TickerWrites {
|
|
2
|
+
revisions: Map<string, number>;
|
|
3
|
+
tails: Map<string, Promise<unknown>>;
|
|
4
|
+
pending: Set<Promise<unknown>>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const repositories = new WeakMap<object, TickerWrites>();
|
|
8
|
+
|
|
9
|
+
function writesFor(repository: object): TickerWrites {
|
|
10
|
+
let writes = repositories.get(repository);
|
|
11
|
+
if (!writes) {
|
|
12
|
+
writes = { revisions: new Map(), tails: new Map(), pending: new Set() };
|
|
13
|
+
repositories.set(repository, writes);
|
|
14
|
+
}
|
|
15
|
+
return writes;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function tickerKey(symbol: string): string {
|
|
19
|
+
return symbol.trim().toUpperCase();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Reserve writes when requested, including ones waiting for an earlier acknowledgement. */
|
|
23
|
+
export function runTickerWrite<Result>(
|
|
24
|
+
repository: object,
|
|
25
|
+
symbols: string | readonly string[],
|
|
26
|
+
write: () => Result | PromiseLike<Result>,
|
|
27
|
+
): Promise<Result> {
|
|
28
|
+
const writes = writesFor(repository);
|
|
29
|
+
const keys = [...new Set((typeof symbols === "string" ? [symbols] : symbols).map(tickerKey))];
|
|
30
|
+
const previous = [...new Set(keys.flatMap((key) => {
|
|
31
|
+
const tail = writes.tails.get(key);
|
|
32
|
+
return tail ? [tail] : [];
|
|
33
|
+
}))];
|
|
34
|
+
let resolve!: (value: Result | PromiseLike<Result>) => void;
|
|
35
|
+
let reject!: (error: unknown) => void;
|
|
36
|
+
const result = new Promise<Result>((accept, fail) => {
|
|
37
|
+
resolve = accept;
|
|
38
|
+
reject = fail;
|
|
39
|
+
});
|
|
40
|
+
for (const key of keys) {
|
|
41
|
+
writes.revisions.set(key, (writes.revisions.get(key) ?? 0) + 1);
|
|
42
|
+
writes.tails.set(key, result);
|
|
43
|
+
}
|
|
44
|
+
writes.pending.add(result);
|
|
45
|
+
const finished = () => {
|
|
46
|
+
writes.pending.delete(result);
|
|
47
|
+
for (const key of keys) {
|
|
48
|
+
if (writes.tails.get(key) === result) writes.tails.delete(key);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
void result.then(finished, finished);
|
|
52
|
+
const start = () => {
|
|
53
|
+
try {
|
|
54
|
+
resolve(write());
|
|
55
|
+
} catch (error) {
|
|
56
|
+
reject(error);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
if (previous.length) void Promise.allSettled(previous).then(start);
|
|
60
|
+
else start();
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Changes immediately when a save or deletion is requested, before its acknowledgement. */
|
|
65
|
+
export function tickerWriteRevision(repository: object, symbol: string): number {
|
|
66
|
+
return repositories.get(repository)?.revisions.get(tickerKey(symbol)) ?? 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Whether a write arrived after a caller last waited for acknowledgements. */
|
|
70
|
+
export function hasPendingTickerWrites(repository: object): boolean {
|
|
71
|
+
return (repositories.get(repository)?.pending.size ?? 0) > 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Let save-await callers publish their edits before cleanup reads the current rows. */
|
|
75
|
+
export async function settleTickerWrites(repository: object): Promise<void> {
|
|
76
|
+
const writes = writesFor(repository);
|
|
77
|
+
do {
|
|
78
|
+
// Each writer handles its own failure; cleanup still needs the last published row.
|
|
79
|
+
await Promise.allSettled([...writes.pending]);
|
|
80
|
+
} while (writes.pending.size);
|
|
81
|
+
}
|