gloomberb 0.11.2 → 0.12.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 +7 -4
- package/README.zh-CN.md +4 -2
- package/package.json +28 -1
- package/src/api-client/auth.ts +10 -0
- package/src/api-client/data.ts +108 -1
- package/src/api-client/index.test.ts +127 -0
- package/src/api-client/index.ts +134 -1
- package/src/api-client/normalizers.ts +39 -0
- package/src/api-client/paths.ts +85 -1
- package/src/api-client/types.ts +220 -0
- package/src/app/pane-runtime/index.tsx +15 -12
- package/src/app/pane-runtime/layout-placement.test.ts +27 -0
- package/src/app/pane-runtime/layout-placement.ts +13 -0
- package/src/app/pane-runtime/plugin-bindings.ts +62 -0
- package/src/app.tsx +60 -18
- package/src/architecture/browser-entry-graph.test.ts +96 -0
- package/src/brokers/profile-form.test.ts +25 -27
- package/src/brokers/test-broker.ts +68 -0
- package/src/capabilities/chart-series.ts +3 -2
- package/src/cli/commands/market.ts +2 -2
- package/src/cli/commands/plugins.ts +39 -11
- package/src/cli/desktop-pane-shot.ts +285 -16
- package/src/cli/index.ts +1 -1
- package/src/cli/pane-functions/capabilities.ts +61 -31
- package/src/cli/pane-functions/catalog.ts +16 -4
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/headless.test.ts +247 -0
- package/src/cli/pane-functions/headless.ts +423 -0
- package/src/cli/pane-functions/index.test.ts +9 -0
- package/src/cli/pane-functions/index.ts +6 -2
- package/src/cli/pane-functions/options.ts +27 -2
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +26 -8
- package/src/cli/pane-functions/screenshot.test.ts +76 -0
- package/src/cli/pane-functions/screenshot.ts +236 -20
- package/src/cli/registry.ts +0 -22
- package/src/cli/restore-plugins.ts +34 -0
- package/src/cli/result.ts +7 -10
- package/src/components/chart/{static/chart → composite}/axis-overlays.test.tsx +3 -3
- package/src/components/chart/{static/chart → composite}/axis-overlays.tsx +6 -11
- package/src/components/chart/{static/chart → composite}/bitmap.ts +17 -3
- package/src/components/chart/composite/composite-chart.test.tsx +68 -20
- package/src/components/chart/composite/composite-chart.tsx +301 -204
- package/src/components/chart/composite/format.ts +8 -2
- package/src/components/chart/composite/interactions.test.ts +68 -102
- package/src/components/chart/composite/interactions.ts +214 -264
- package/src/components/chart/composite/price-axis-labels.test.ts +21 -0
- package/src/components/chart/{price-axis-labels.tsx → composite/price-axis-labels.tsx} +9 -4
- package/src/components/chart/composite/scene.ts +57 -3
- package/src/components/chart/composite/text-renderer.ts +3 -2
- package/src/components/chart/composite/time-scale.ts +138 -57
- package/src/components/chart/composite/types.ts +25 -1
- package/src/components/chart/core/data.ts +9 -13
- package/src/components/chart/core/date-window.ts +7 -1
- package/src/components/chart/core/pointer.ts +3 -0
- package/src/components/chart/core/types.ts +0 -45
- package/src/components/chart/native/chart-rasterizer.ts +0 -1
- package/src/components/chart/native/kitty/index.test.ts +0 -188
- package/src/components/chart/native/raster/crosshair.ts +6 -5
- package/src/components/chart/native/raster/primitives.ts +0 -23
- package/src/components/chart/native/renderer-selection.ts +81 -31
- package/src/components/chart/static/{chart/surface.test.tsx → chart-surface.test.tsx} +28 -80
- package/src/components/chart/static/chart-surface.tsx +150 -0
- package/src/components/chart/static/index.ts +8 -0
- package/src/components/chart/static/multi-line-chart-surface.tsx +51 -166
- package/src/components/chart/static/scatter-chart-surface.test.ts +30 -0
- package/src/components/chart/static/scatter-chart-surface.tsx +135 -34
- package/src/components/chart/static/series.ts +49 -0
- package/src/components/command-bar/action-runtime.ts +1 -3
- package/src/components/command-bar/assist/model.test.ts +17 -2
- package/src/components/command-bar/assist/model.ts +40 -9
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +1 -1
- package/src/components/command-bar/commands/registry.ts +0 -11
- package/src/components/command-bar/helpers.test.ts +2 -2
- package/src/components/command-bar/helpers.ts +2 -6
- package/src/components/command-bar/keyboard-shortcuts.ts +0 -11
- package/src/components/command-bar/list/badge.test.ts +54 -0
- package/src/components/command-bar/list/badge.ts +62 -0
- package/src/components/command-bar/list/model.test.ts +103 -0
- package/src/components/command-bar/list/model.ts +61 -4
- package/src/components/command-bar/list/view.test.tsx +113 -0
- package/src/components/command-bar/list/view.tsx +147 -131
- package/src/components/command-bar/pane-templates/workflow.ts +1 -1
- package/src/components/command-bar/panel/body.tsx +51 -65
- package/src/components/command-bar/panel/index.tsx +48 -13
- package/src/components/command-bar/panel/layout.test.ts +139 -0
- package/src/components/command-bar/panel/layout.ts +65 -28
- package/src/components/command-bar/panel/native-surface.ts +24 -0
- package/src/components/command-bar/panel/prompt-binding.ts +54 -0
- package/src/components/command-bar/panel/runtime.ts +6 -3
- package/src/components/command-bar/panel/state.ts +41 -7
- package/src/components/command-bar/panel/types.ts +7 -1
- package/src/components/command-bar/routes/root/provider-search.ts +34 -15
- package/src/components/command-bar/routes/root/results.test.ts +161 -0
- package/src/components/command-bar/routes/root/results.ts +30 -28
- package/src/components/command-bar/routes/root/runtime.ts +37 -20
- package/src/components/command-bar/routes/root/search-providers.test.tsx +224 -0
- package/src/components/command-bar/routes/root/search-providers.ts +205 -0
- package/src/components/command-bar/routes/root/selection.ts +1 -12
- package/src/components/command-bar/routes/root/shortcuts.test.ts +8 -8
- package/src/components/command-bar/routes/ticker-search/actions.ts +10 -9
- package/src/components/command-bar/routes/ticker-search/results.test.ts +54 -1
- package/src/components/command-bar/routes/ticker-search/results.ts +60 -19
- package/src/components/command-bar/routes/ticker-search/route.ts +1 -0
- package/src/components/command-bar/routing/actions.ts +1 -81
- package/src/components/command-bar/routing/launch-request.ts +1 -1
- package/src/components/command-bar/routing/list-state.ts +6 -21
- package/src/components/command-bar/selection-runtime.ts +1 -1
- package/src/components/command-bar/surface/assist.test.tsx +14 -10
- package/src/components/command-bar/surface/environment.ts +8 -1
- package/src/components/command-bar/surface/index.test.tsx +84 -68
- package/src/components/command-bar/surface/index.tsx +33 -36
- package/src/components/command-bar/surface/test-harness.tsx +15 -3
- package/src/components/command-bar/theme-picker.tsx +43 -15
- package/src/components/command-bar/view-model.test.ts +53 -8
- package/src/components/command-bar/view-model.ts +43 -14
- package/src/components/command-bar/workflow/tickers.ts +1 -0
- package/src/components/command-bar/workflow/types.ts +1 -1
- package/src/components/data-table/export.test.ts +21 -0
- package/src/components/data-table/export.ts +21 -0
- package/src/components/data-table/view.test.tsx +45 -6
- package/src/components/data-table/view.tsx +55 -9
- package/src/components/index.ts +10 -2
- package/src/components/input-search-bar.test.tsx +36 -2
- package/src/components/input-search-bar.tsx +18 -1
- package/src/components/layout/header.test.tsx +57 -10
- package/src/components/layout/header.tsx +292 -149
- package/src/components/layout/market-summary.test.ts +81 -0
- package/src/components/layout/market-summary.ts +109 -0
- package/src/components/layout/shell/chrome.ts +96 -1
- package/src/components/layout/shell/index.tsx +11 -3
- package/src/components/layout/shell/menu.ts +9 -0
- package/src/components/layout/shell/pane/actions.ts +29 -0
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/shortcuts.ts +3 -0
- package/src/components/layout/status-bar.test.tsx +9 -8
- package/src/components/layout/status-bar.tsx +85 -54
- package/src/components/onboarding/onboarding-frame.tsx +2 -26
- package/src/components/price-sparkline/index.ts +61 -34
- package/src/components/price-sparkline/view.tsx +1 -1
- package/src/components/sign-in-gate.test.tsx +128 -0
- package/src/components/sign-in-gate.tsx +149 -0
- package/src/components/speedometer-gauge/desktop.tsx +2 -12
- package/src/components/ticker/badge/list.tsx +17 -3
- package/src/components/ticker/list-table-view.tsx +6 -3
- package/src/components/ui/data-table/index.tsx +22 -4
- package/src/components/ui/data-table/opentui/index.tsx +165 -120
- package/src/components/ui/frame.tsx +28 -0
- package/src/components/ui/index.ts +3 -0
- package/src/components/ui/native-select.tsx +20 -10
- package/src/components/ui/select-button.tsx +138 -0
- package/src/components/ui/status.tsx +2 -2
- package/src/components/ui/table-layout.ts +1 -1
- package/src/components/use-double-click-activation.ts +7 -3
- package/src/core/app-services.ts +3 -3
- package/src/data/config/chart-settings.ts +4 -4
- package/src/data/config/layout.ts +12 -6
- package/src/data/config/store/index.test.ts +97 -0
- package/src/data/config/store/migrations.ts +41 -0
- package/src/data/config/store/normalize.ts +5 -3
- package/src/i18n/es.ts +6 -2
- package/src/i18n/ja.ts +6 -2
- package/src/i18n/ko.ts +6 -2
- package/src/i18n/zh-cn.ts +6 -2
- package/src/i18n/zh-tw.ts +6 -2
- package/src/layout-marketplace/gallery-terminal.tsx +126 -96
- package/src/layout-marketplace/gallery.test.tsx +65 -1
- package/src/layout-marketplace/pane-imagery.ts +1 -0
- package/src/layout-marketplace/payload.test.ts +17 -0
- package/src/layout-marketplace/payload.ts +40 -5
- package/src/market-data/coordinator/index.ts +3 -2
- package/src/market-data/coordinator/quotes.ts +173 -66
- package/src/market-data/coordinator/subscriptions.test.ts +215 -37
- package/src/pane-settings.ts +1 -1
- package/src/plugins/builtin/analytics/pane-model.ts +1 -1
- package/src/plugins/builtin/analytics/view.tsx +1 -1
- package/src/plugins/builtin/broker-manager/index.test.tsx +3 -2
- package/src/plugins/builtin/broker-manager/model.test.ts +2 -2
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +16 -2
- package/src/plugins/builtin/chart-composer/cli-options.ts +12 -9
- package/src/plugins/builtin/chart-composer/pane.tsx +22 -8
- package/src/plugins/builtin/chart-composer/settings.ts +2 -13
- package/src/plugins/builtin/chat/content/composer.tsx +8 -4
- package/src/plugins/builtin/cloud/auth-dialog.tsx +14 -228
- package/src/plugins/builtin/cloud/auth-form.tsx +277 -0
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/composite-plugins.ts +16 -1
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +2 -6
- package/src/plugins/builtin/correlation/relationship/view-model.ts +2 -2
- package/src/plugins/builtin/credit-conditions/index.test.tsx +12 -6
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -21
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/earnings/index.tsx +1 -0
- package/src/plugins/builtin/earnings-calls/data.ts +223 -0
- package/src/plugins/builtin/earnings-calls/format.ts +49 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +69 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +756 -0
- package/src/plugins/builtin/earnings-calls/prose.test.ts +36 -0
- package/src/plugins/builtin/earnings-calls/prose.ts +59 -0
- package/src/plugins/builtin/earnings-calls/transcript-view.tsx +334 -0
- package/src/plugins/builtin/econ/detail-view.tsx +1 -2
- package/src/plugins/builtin/econ/fred-series-map.ts +16 -1
- package/src/plugins/builtin/econ/index.tsx +3 -1
- package/src/plugins/builtin/econ-statistics/cache.ts +4 -0
- package/src/plugins/builtin/econ-statistics/client.ts +92 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +66 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +154 -0
- package/src/plugins/builtin/econ-statistics/headless.test.ts +54 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +171 -0
- package/src/plugins/builtin/econ-statistics/index.tsx +54 -0
- package/src/plugins/builtin/econ-statistics/pane.tsx +356 -0
- package/src/plugins/builtin/econ-statistics/stats.ts +522 -0
- package/src/plugins/builtin/econ-statistics/transform.test.ts +86 -0
- package/src/plugins/builtin/econ-statistics/transform.ts +85 -0
- package/src/plugins/builtin/econ-statistics/trend.ts +57 -0
- package/src/plugins/builtin/econ-statistics/view.ts +90 -0
- package/src/plugins/builtin/fear-greed/charts.tsx +7 -18
- package/src/plugins/builtin/fear-greed/data.ts +6 -1
- package/src/plugins/builtin/futures/index.tsx +1 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +1 -0
- package/src/plugins/builtin/help/index.tsx +4 -0
- package/src/plugins/builtin/holders/index.tsx +1 -0
- package/src/plugins/builtin/insider/index.tsx +1 -0
- package/src/plugins/builtin/ipo-calendar/index.tsx +1 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/sections.tsx +2 -3
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-movers/index.tsx +1 -0
- package/src/plugins/builtin/market-valuation/align.ts +122 -0
- package/src/plugins/builtin/market-valuation/cache.ts +32 -0
- package/src/plugins/builtin/market-valuation/chart-projection.ts +217 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +89 -0
- package/src/plugins/builtin/market-valuation/client.test.ts +141 -0
- package/src/plugins/builtin/market-valuation/client.ts +116 -0
- package/src/plugins/builtin/market-valuation/defs.ts +251 -0
- package/src/plugins/builtin/market-valuation/detail.tsx +159 -0
- package/src/plugins/builtin/market-valuation/headless.test.ts +58 -0
- package/src/plugins/builtin/market-valuation/headless.ts +170 -0
- package/src/plugins/builtin/market-valuation/index.tsx +64 -0
- package/src/plugins/builtin/market-valuation/indicators.ts +422 -0
- package/src/plugins/builtin/market-valuation/model.test.ts +350 -0
- package/src/plugins/builtin/market-valuation/model.ts +8 -0
- package/src/plugins/builtin/market-valuation/pane.test.tsx +247 -0
- package/src/plugins/builtin/market-valuation/pane.tsx +344 -0
- package/src/plugins/builtin/market-valuation/series.ts +12 -0
- package/src/plugins/builtin/market-valuation/settings.ts +38 -0
- package/src/plugins/builtin/market-valuation/sources.ts +130 -0
- package/src/plugins/builtin/market-valuation/trend.ts +89 -0
- package/src/plugins/builtin/market-valuation/view.ts +137 -0
- package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +123 -0
- package/src/plugins/builtin/market-valuation/zone-scale/index.tsx +12 -0
- package/src/plugins/builtin/market-valuation/zone-scale/model.ts +60 -0
- package/src/plugins/builtin/market-valuation/zone-scale/terminal.tsx +94 -0
- package/src/plugins/builtin/news/wire/breaking/filters.test.ts +99 -0
- package/src/plugins/builtin/news/wire/breaking/filters.ts +110 -0
- package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +157 -53
- package/src/plugins/builtin/news/wire/breaking/notifications.ts +91 -25
- package/src/plugins/builtin/news/wire/index.tsx +31 -44
- package/src/plugins/builtin/options/analytics.test.ts +83 -0
- package/src/plugins/builtin/options/analytics.ts +110 -0
- package/src/plugins/builtin/options/index.tsx +18 -2
- package/src/plugins/builtin/options/table.ts +121 -51
- package/src/plugins/builtin/options/types.ts +22 -15
- package/src/plugins/builtin/options/view.test.tsx +53 -1
- package/src/plugins/builtin/options/view.tsx +92 -41
- package/src/plugins/builtin/plugin-marketplace/feed.ts +80 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +31 -0
- package/src/plugins/builtin/plugin-marketplace/model.test.ts +200 -0
- package/src/plugins/builtin/plugin-marketplace/model.ts +204 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +385 -0
- package/src/plugins/builtin/plugin-marketplace/store.ts +46 -0
- package/src/plugins/builtin/plugin-module.test.ts +2 -4
- package/src/plugins/builtin/plugin-module.ts +9 -8
- package/src/plugins/builtin/portfolio-list/index.tsx +1 -0
- package/src/plugins/builtin/research/index.tsx +4 -0
- package/src/plugins/builtin/research-search/command-bar-search.test.ts +81 -0
- package/src/plugins/builtin/research-search/command-bar-search.ts +175 -0
- package/src/plugins/builtin/research-search/data.ts +109 -0
- package/src/plugins/builtin/research-search/document-view.test.tsx +75 -0
- package/src/plugins/builtin/research-search/document-view.tsx +254 -0
- package/src/plugins/builtin/research-search/filter-bar.tsx +62 -0
- package/src/plugins/builtin/research-search/focus-handoff.ts +47 -0
- package/src/plugins/builtin/research-search/index.tsx +85 -0
- package/src/plugins/builtin/research-search/model.test.ts +40 -0
- package/src/plugins/builtin/research-search/model.ts +291 -0
- package/src/plugins/builtin/research-search/pane.test.tsx +241 -0
- package/src/plugins/builtin/research-search/pane.tsx +678 -0
- package/src/plugins/builtin/research-search/saved-view.tsx +171 -0
- package/src/plugins/builtin/research-search/snippet-text.tsx +35 -0
- package/src/plugins/builtin/research-search/snippet.test.ts +78 -0
- package/src/plugins/builtin/research-search/snippet.ts +134 -0
- package/src/plugins/builtin/scanner/flow-model.test.ts +11 -1
- package/src/plugins/builtin/scanner/flow-model.ts +29 -1
- package/src/plugins/builtin/scanner/flow-pane.tsx +78 -22
- package/src/plugins/builtin/scanner/index.ts +2 -0
- package/src/plugins/builtin/sec/index.tsx +1 -0
- package/src/plugins/builtin/sectors/index.tsx +1 -0
- package/src/plugins/builtin/shared/series-cache.ts +93 -0
- package/src/plugins/builtin/short-interest/index.tsx +1 -0
- package/src/plugins/builtin/short-interest/pane.tsx +1 -1
- package/src/plugins/builtin/thirteenf/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +3 -5
- package/src/plugins/builtin/ticker-detail/index.tsx +2 -14
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/volatility/index.tsx +1 -1
- package/src/plugins/builtin/world-indices/index.tsx +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +27 -0
- package/src/plugins/builtin/world-venue-map/map.desktop.test.tsx +106 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +481 -0
- package/src/plugins/builtin/world-venue-map/model.test.ts +85 -0
- package/src/plugins/builtin/world-venue-map/model.ts +268 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +300 -0
- package/src/plugins/builtin/world-venue-map/world-outlines.ts +2 -0
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/bundle.test.ts +109 -0
- package/src/plugins/bundle.ts +139 -0
- package/src/plugins/catalog-backend.ts +6 -44
- package/src/plugins/catalog-browser.test.ts +1 -0
- package/src/plugins/catalog-browser.ts +12 -0
- package/src/plugins/catalog-manifest.test.ts +43 -0
- package/src/plugins/catalog-manifest.ts +92 -0
- package/src/plugins/catalog-ui.ts +20 -4
- package/src/plugins/catalog.ts +9 -2
- package/src/plugins/current-target.ts +28 -0
- package/src/plugins/host-contract.ts +37 -0
- package/src/plugins/host-link.ts +158 -0
- package/src/plugins/host-modules.ts +61 -0
- package/src/plugins/loader.ts +41 -22
- package/src/plugins/ownership.ts +1 -0
- package/src/plugins/prediction-markets/index.tsx +1 -0
- package/src/plugins/registry/context.ts +3 -0
- package/src/plugins/registry/contributions.ts +27 -0
- package/src/plugins/registry/index.test.ts +25 -0
- package/src/plugins/registry/index.ts +8 -0
- package/src/plugins/registry/pane-settings.test.ts +53 -0
- package/src/plugins/registry/pane-settings.ts +29 -3
- package/src/plugins/seed.test.ts +83 -0
- package/src/plugins/seed.ts +80 -0
- package/src/public/broker.ts +31 -0
- package/src/public/market-data.ts +9 -0
- package/src/public/pane-hooks.ts +57 -0
- package/src/public/public-api.test.ts +285 -0
- package/src/public/react.ts +62 -0
- package/src/public/test-support.ts +23 -0
- package/src/public/time-series.ts +8 -0
- package/src/public/utils.ts +77 -0
- package/src/remote/layout-helpers.ts +6 -8
- package/src/remote/resources.ts +2 -0
- package/src/remote/schema.ts +1 -0
- package/src/remote/semantic-tree.test.tsx +105 -0
- package/src/remote/semantic-tree.tsx +53 -35
- package/src/renderers/browser/main.tsx +6 -0
- package/src/renderers/browser/ui-host.tsx +11 -0
- package/src/renderers/cloudflare/worker.test.ts +19 -0
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -2
- package/src/renderers/electrobun/bun/external-plugins.ts +140 -0
- package/src/renderers/electrobun/bun/index.ts +6 -2
- package/src/renderers/electrobun/shared/protocol.ts +25 -0
- package/src/renderers/electrobun/view/build-assets.ts +0 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +51 -1
- package/src/renderers/electrobun/view/external-plugins.test.ts +45 -0
- package/src/renderers/electrobun/view/external-plugins.ts +63 -0
- package/src/renderers/electrobun/view/host/ascii-text.test.ts +48 -0
- package/src/renderers/electrobun/view/host/ascii-text.ts +11 -1
- package/src/renderers/electrobun/view/host/chart-surface.tsx +38 -32
- package/src/renderers/electrobun/view/host/mouse.ts +16 -2
- package/src/renderers/electrobun/view/main.tsx +27 -2
- package/src/renderers/electrobun/view/styles.css +5 -0
- package/src/renderers/electrobun/view/toast-host.tsx +18 -0
- package/src/renderers/electrobun/view/ui-host.tsx +3 -0
- package/src/renderers/opentui/chart-surface.tsx +5 -1
- package/src/renderers/opentui/host.tsx +20 -2
- package/src/renderers/opentui/interaction-performance.test.ts +79 -0
- package/src/renderers/opentui/interaction-performance.ts +188 -0
- package/src/renderers/opentui/start.tsx +26 -1
- package/src/renderers/opentui/test-utils.tsx +13 -0
- package/src/renderers/opentui/toast-host.tsx +26 -2
- package/src/renderers/opentui/ui-host.tsx +1 -0
- package/src/sources/provider-router/search.test.ts +191 -0
- package/src/sources/provider-router/search.ts +92 -39
- package/src/state/app/context/index.tsx +2 -0
- package/src/state/app/context/selector.test.tsx +33 -1
- package/src/state/hooks/quote-streaming.test.tsx +93 -0
- package/src/state/hooks/quote-streaming.ts +106 -30
- package/src/state/pane-table-export-registry.ts +50 -0
- package/src/theme/color-utils.ts +1 -1
- package/src/theme/colors.ts +50 -0
- package/src/theme/themes.test.ts +15 -2
- package/src/theme/themes.ts +19 -1
- package/src/tickers/search/index.test.ts +26 -0
- package/src/tickers/search/index.ts +42 -17
- package/src/tickers/search/ranking.ts +14 -0
- package/src/time-series/chart-data.test.ts +216 -0
- package/src/time-series/range.ts +12 -0
- package/src/time-series/resolution.test.ts +25 -26
- package/src/time-series/resolution.ts +44 -25
- package/src/time-series/resolve.ts +7 -0
- package/src/time-series/spec.ts +5 -5
- package/src/time-series/types.ts +3 -1
- package/src/time-series/use-chart-resolution.ts +5 -0
- package/src/types/config.ts +123 -3
- package/src/types/data-provider.ts +11 -0
- package/src/types/headless.ts +161 -0
- package/src/types/plugin.ts +104 -20
- package/src/ui/host.tsx +19 -1
- package/src/ui/index.tsx +1 -0
- package/src/ui/toast.tsx +8 -4
- package/src/utils/csv.test.ts +13 -0
- package/src/utils/csv.ts +37 -0
- package/src/utils/format.ts +35 -0
- package/src/utils/fuzzy-search.test.ts +94 -0
- package/src/utils/fuzzy-search.ts +81 -22
- package/src/utils/save-text-file.test.ts +24 -0
- package/src/utils/save-text-file.ts +36 -0
- package/src/utils/shortcut-labels.ts +14 -0
- package/src/components/chart/core/axis-format.ts +0 -157
- package/src/components/chart/core/index.test.ts +0 -1075
- package/src/components/chart/core/projection.ts +0 -357
- package/src/components/chart/core/render-utils.ts +0 -4
- package/src/components/chart/core/renderer.ts +0 -244
- package/src/components/chart/core/scene.ts +0 -180
- package/src/components/chart/core/time-axis.ts +0 -330
- package/src/components/chart/cursor-motion.ts +0 -47
- package/src/components/chart/indicators/types.ts +0 -26
- package/src/components/chart/market-session.ts +0 -176
- package/src/components/chart/multi-line/renderer.test.ts +0 -83
- package/src/components/chart/multi-line/renderer.ts +0 -161
- package/src/components/chart/multi-line/scene.ts +0 -188
- package/src/components/chart/native/raster/layout.ts +0 -129
- package/src/components/chart/native/raster/price-chart.ts +0 -244
- package/src/components/chart/rendering/chart-draw.ts +0 -270
- package/src/components/chart/rendering/geometry.ts +0 -95
- package/src/components/chart/rendering/pixel-buffer.ts +0 -267
- package/src/components/chart/scatter-chart-renderer.test.ts +0 -31
- package/src/components/chart/scatter-chart-renderer.ts +0 -223
- package/src/components/chart/static/chart/surface.tsx +0 -358
- package/src/components/command-bar/routes/root/article-results.test.ts +0 -83
- package/src/components/command-bar/routes/root/article-results.ts +0 -55
- package/src/plugins/builtin/news/wire/article-search.test.ts +0 -72
- package/src/plugins/builtin/news/wire/article-search.ts +0 -140
- package/src/plugins/builtin/substack/api/auth.ts +0 -185
- package/src/plugins/builtin/substack/api/cache.ts +0 -82
- package/src/plugins/builtin/substack/api/loaders.ts +0 -170
- package/src/plugins/builtin/substack/api/store.ts +0 -186
- package/src/plugins/builtin/substack/api/types.ts +0 -42
- package/src/plugins/builtin/substack/api.test.ts +0 -298
- package/src/plugins/builtin/substack/article-detail.tsx +0 -397
- package/src/plugins/builtin/substack/article-stack.tsx +0 -133
- package/src/plugins/builtin/substack/content.ts +0 -478
- package/src/plugins/builtin/substack/feed-tabs.tsx +0 -44
- package/src/plugins/builtin/substack/index.tsx +0 -49
- package/src/plugins/builtin/substack/login-view.tsx +0 -126
- package/src/plugins/builtin/substack/model.test.ts +0 -155
- package/src/plugins/builtin/substack/normalize.ts +0 -343
- package/src/plugins/builtin/substack/pane-footer.ts +0 -52
- package/src/plugins/builtin/substack/pane-state.ts +0 -170
- package/src/plugins/builtin/substack/pane.tsx +0 -547
- package/src/plugins/builtin/substack/read-state.ts +0 -30
- package/src/plugins/builtin/substack/table.ts +0 -111
- package/src/plugins/builtin/substack/types.ts +0 -71
- package/src/plugins/builtin/substack/utils.ts +0 -131
- package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +0 -229
- package/src/plugins/ibkr/account-cache.test.ts +0 -102
- package/src/plugins/ibkr/account-cache.ts +0 -24
- package/src/plugins/ibkr/broker-adapter.ts +0 -286
- package/src/plugins/ibkr/config.test.ts +0 -79
- package/src/plugins/ibkr/config.ts +0 -250
- package/src/plugins/ibkr/dialogs.tsx +0 -40
- package/src/plugins/ibkr/flex/index.test.ts +0 -264
- package/src/plugins/ibkr/flex/index.ts +0 -367
- package/src/plugins/ibkr/flex/statement-client.ts +0 -235
- package/src/plugins/ibkr/fundamental-parser.ts +0 -149
- package/src/plugins/ibkr/gateway/account-loaders.ts +0 -266
- package/src/plugins/ibkr/gateway/account-summary.ts +0 -164
- package/src/plugins/ibkr/gateway/client-lock.ts +0 -154
- package/src/plugins/ibkr/gateway/connection-events.ts +0 -114
- package/src/plugins/ibkr/gateway/connection.ts +0 -152
- package/src/plugins/ibkr/gateway/contracts.ts +0 -132
- package/src/plugins/ibkr/gateway/fundamentals.ts +0 -83
- package/src/plugins/ibkr/gateway/helpers.ts +0 -33
- package/src/plugins/ibkr/gateway/history-requests.ts +0 -158
- package/src/plugins/ibkr/gateway/history.ts +0 -120
- package/src/plugins/ibkr/gateway/instrument-lookup.ts +0 -117
- package/src/plugins/ibkr/gateway/market-data.ts +0 -345
- package/src/plugins/ibkr/gateway/order-execution.ts +0 -218
- package/src/plugins/ibkr/gateway/orders.ts +0 -63
- package/src/plugins/ibkr/gateway/price-normalization.test.ts +0 -44
- package/src/plugins/ibkr/gateway/price-normalization.ts +0 -50
- package/src/plugins/ibkr/gateway/quote-stream-controller.ts +0 -203
- package/src/plugins/ibkr/gateway/quote-stream.ts +0 -171
- package/src/plugins/ibkr/gateway/selection.ts +0 -51
- package/src/plugins/ibkr/gateway/service/index.test.ts +0 -675
- package/src/plugins/ibkr/gateway/service/index.ts +0 -429
- package/src/plugins/ibkr/gateway/service/lifecycle.ts +0 -191
- package/src/plugins/ibkr/gateway/service/manager.ts +0 -52
- package/src/plugins/ibkr/gateway/service/market-data.ts +0 -48
- package/src/plugins/ibkr/gateway/service/native-loader.ts +0 -12
- package/src/plugins/ibkr/gateway/service/native.ts +0 -543
- package/src/plugins/ibkr/gateway/timeouts.ts +0 -13
- package/src/plugins/ibkr/gateway/types.ts +0 -27
- package/src/plugins/ibkr/index.test.tsx +0 -162
- package/src/plugins/ibkr/index.tsx +0 -159
- package/src/plugins/ibkr/instance-selection.test.ts +0 -120
- package/src/plugins/ibkr/instance-selection.ts +0 -36
- package/src/plugins/ibkr/portfolio-performance.test.ts +0 -32
- package/src/plugins/ibkr/portfolio-performance.ts +0 -129
- package/src/plugins/ibkr/trade/badge.tsx +0 -28
- package/src/plugins/ibkr/trade/dialogs.tsx +0 -44
- package/src/plugins/ibkr/trade/preview-panel.tsx +0 -130
- package/src/plugins/ibkr/trade/tab/actions.tsx +0 -443
- package/src/plugins/ibkr/trade/tab/field-editors.tsx +0 -79
- package/src/plugins/ibkr/trade/tab/footer.ts +0 -53
- package/src/plugins/ibkr/trade/tab/header.tsx +0 -167
- package/src/plugins/ibkr/trade/tab/index.test.tsx +0 -178
- package/src/plugins/ibkr/trade/tab/index.tsx +0 -298
- package/src/plugins/ibkr/trade/tab/model.ts +0 -159
- package/src/plugins/ibkr/trade/tab/order-request.ts +0 -64
- package/src/plugins/ibkr/trade/tab/shortcuts.ts +0 -89
- package/src/plugins/ibkr/trade/tab/state-sync.ts +0 -86
- package/src/plugins/ibkr/trade/ticket-panel.tsx +0 -301
- package/src/plugins/ibkr/trade/utils.test.ts +0 -175
- package/src/plugins/ibkr/trade/utils.ts +0 -144
- package/src/plugins/ibkr/trading/pane-view.tsx +0 -237
- package/src/plugins/ibkr/trading/pane.tsx +0 -332
- package/src/plugins/ibkr/trading/state.test.ts +0 -109
- package/src/plugins/ibkr/trading/state.ts +0 -335
|
@@ -12,6 +12,7 @@ import type { ResultItem } from "../../list/model";
|
|
|
12
12
|
import {
|
|
13
13
|
buildTickerSearchCacheKey,
|
|
14
14
|
createQuickLookTickerCandidates,
|
|
15
|
+
formatInstrumentBadge,
|
|
15
16
|
} from "./results";
|
|
16
17
|
|
|
17
18
|
interface UseCommandBarTickerSearchActionsOptions {
|
|
@@ -47,13 +48,20 @@ export function useCommandBarTickerSearchActions({
|
|
|
47
48
|
|
|
48
49
|
const mapTickerSearchCandidateToResultItem = useCallback((candidate: TickerSearchCandidate): ResultItem => {
|
|
49
50
|
const detail = formatTickerSearchDetail(candidate);
|
|
50
|
-
|
|
51
|
+
// The class lives in the badge, so the trailing text carries only the
|
|
52
|
+
// venue rather than saying "Equity" twice on one row. An unclassified
|
|
53
|
+
// instrument has no class to show, so the badge column lifts its venue
|
|
54
|
+
// instead (a short exchange code qualifies on its own) and the trailing
|
|
55
|
+
// text goes quiet rather than repeating it.
|
|
56
|
+
const badge = formatInstrumentBadge(candidate);
|
|
57
|
+
const right = candidate.exchangeLabel || candidate.primaryExchangeLabel || candidate.right || undefined;
|
|
51
58
|
|
|
52
59
|
if (candidate.kind === "ticker" && candidate.ticker) {
|
|
53
60
|
return {
|
|
54
61
|
id: candidate.id,
|
|
55
62
|
label: candidate.label,
|
|
56
63
|
detail,
|
|
64
|
+
badge,
|
|
57
65
|
right,
|
|
58
66
|
category: candidate.category,
|
|
59
67
|
kind: "ticker",
|
|
@@ -72,6 +80,7 @@ export function useCommandBarTickerSearchActions({
|
|
|
72
80
|
id: candidate.id,
|
|
73
81
|
label: candidate.label,
|
|
74
82
|
detail,
|
|
83
|
+
badge,
|
|
75
84
|
right,
|
|
76
85
|
category: candidate.category,
|
|
77
86
|
kind: "search",
|
|
@@ -145,14 +154,6 @@ export function useCommandBarTickerSearchActions({
|
|
|
145
154
|
};
|
|
146
155
|
}
|
|
147
156
|
|
|
148
|
-
function formatTickerSearchRight(candidate: TickerSearchCandidate): string | undefined {
|
|
149
|
-
const assetClass = formatInstrumentClass(candidate.instrumentClass);
|
|
150
|
-
const exchange = candidate.exchangeLabel || candidate.primaryExchangeLabel || candidate.right || "";
|
|
151
|
-
if (!exchange) return assetClass;
|
|
152
|
-
if (assetClass === "Other") return exchange;
|
|
153
|
-
return `${assetClass} ${exchange}`;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
157
|
function formatTickerSearchDetail(candidate: TickerSearchCandidate): string {
|
|
157
158
|
const metadata = [
|
|
158
159
|
formatInstrumentClass(candidate.instrumentClass),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect, test } from "bun:test";
|
|
2
2
|
import type { ResultItem } from "../../list/model";
|
|
3
|
-
import { mergeTickerSearchResultItems } from "./results";
|
|
3
|
+
import { formatInstrumentBadge, mergePlainRootTickerResults, mergeTickerSearchResultItems } from "./results";
|
|
4
4
|
|
|
5
5
|
function resultItem(id: string, label: string, right: string, kind: ResultItem["kind"] = "ticker"): ResultItem {
|
|
6
6
|
return {
|
|
@@ -32,3 +32,56 @@ test("keeps completed ticker-search results authoritative over provisional rows"
|
|
|
32
32
|
const noResults = resultItem("no-results", "No matches for Apple", "", "info");
|
|
33
33
|
expect(mergeTickerSearchResultItems("Apple", [noResults], [])).toEqual([noResults]);
|
|
34
34
|
});
|
|
35
|
+
|
|
36
|
+
test("folds a plain query's symbol hits into one capped Instruments section behind the local rows", () => {
|
|
37
|
+
const pane: ResultItem = {
|
|
38
|
+
id: "pane:news",
|
|
39
|
+
label: "News",
|
|
40
|
+
detail: "",
|
|
41
|
+
category: "Panes",
|
|
42
|
+
kind: "action",
|
|
43
|
+
action: () => {},
|
|
44
|
+
};
|
|
45
|
+
const providerItems = [
|
|
46
|
+
resultItem("search:NVDA", "NVDA", "Equity NASDAQ", "search"),
|
|
47
|
+
// The saved row for the same symbol carries a different badge; one row per symbol.
|
|
48
|
+
resultItem("goto:NVDA", "NVDA", "NASDAQ"),
|
|
49
|
+
resultItem("search:NVDA.MX", "NVDA.MX", "Equity BMV", "search"),
|
|
50
|
+
resultItem("search:NVD.DE", "NVD.DE", "Equity XETRA", "search"),
|
|
51
|
+
resultItem("search:NVDL", "NVDL", "Fund NASDAQ", "search"),
|
|
52
|
+
resultItem("search:NVDS", "NVDS", "Fund NASDAQ", "search"),
|
|
53
|
+
resultItem("search:NVDX", "NVDX", "Fund NASDAQ", "search"),
|
|
54
|
+
resultItem("search-error", "Search failed", "", "info"),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const merged = mergePlainRootTickerResults("nvda", providerItems, [pane]);
|
|
58
|
+
|
|
59
|
+
expect(merged.map((item) => [item.id, item.category])).toEqual([
|
|
60
|
+
["search:NVDA", "Exact Match"],
|
|
61
|
+
["pane:news", "Panes"],
|
|
62
|
+
["search:NVDA.MX", "Instruments"],
|
|
63
|
+
["search:NVD.DE", "Instruments"],
|
|
64
|
+
["search:NVDL", "Instruments"],
|
|
65
|
+
["search:NVDS", "Instruments"],
|
|
66
|
+
]);
|
|
67
|
+
expect(merged.find((item) => item.id === "search:NVDA.MX")?.right).toBe("Equity BMV");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The class tag is what the eye sorts instruments by, so the mapping from a
|
|
72
|
+
* provider's type strings has to stay put: an exchange-traded fund is not a
|
|
73
|
+
* mutual fund, and an unclassified instrument gets no tag rather than a stand-in.
|
|
74
|
+
*/
|
|
75
|
+
test("names the instrument class for the badge column", () => {
|
|
76
|
+
const search = (type: string) => ({ providerId: "yahoo", symbol: "X", name: "X", exchange: "NYQ", type });
|
|
77
|
+
expect(formatInstrumentBadge({ instrumentClass: "equity" })).toBe("EQ");
|
|
78
|
+
expect(formatInstrumentBadge({ instrumentClass: "fund", result: search("ETF") })).toBe("ETF");
|
|
79
|
+
expect(formatInstrumentBadge({ instrumentClass: "fund", result: search("ETN") })).toBe("ETF");
|
|
80
|
+
expect(formatInstrumentBadge({ instrumentClass: "fund", result: search("MUTUALFUND") })).toBe("FUND");
|
|
81
|
+
expect(formatInstrumentBadge({
|
|
82
|
+
instrumentClass: "fund",
|
|
83
|
+
ticker: { metadata: { ticker: "VTI", assetCategory: "ETF" } } as never,
|
|
84
|
+
})).toBe("ETF");
|
|
85
|
+
expect(formatInstrumentBadge({ instrumentClass: "derivative" })).toBe("DERIV");
|
|
86
|
+
expect(formatInstrumentBadge({ instrumentClass: "other", result: search("INDEX") })).toBeUndefined();
|
|
87
|
+
});
|
|
@@ -19,6 +19,33 @@ export function createQuickLookTickerCandidates(tickers: Iterable<TickerRecord>)
|
|
|
19
19
|
return createLocalTickerSearchCandidates(tickers, new Map(), QUICK_LOOK_TICKER_SEARCH_OPTIONS);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** Provider type or saved asset category, whichever classified the candidate. */
|
|
23
|
+
function rawInstrumentType(candidate: Pick<TickerSearchCandidate, "result" | "ticker">): string {
|
|
24
|
+
return candidate.result?.brokerContract?.secType
|
|
25
|
+
|| candidate.result?.type
|
|
26
|
+
|| candidate.ticker?.metadata.assetCategory
|
|
27
|
+
|| "";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Class tag for the badge column. An unclassified instrument gets none: the
|
|
32
|
+
* row lifts its exchange code there instead when the code is short enough.
|
|
33
|
+
*/
|
|
34
|
+
export function formatInstrumentBadge(
|
|
35
|
+
candidate: Pick<TickerSearchCandidate, "instrumentClass" | "result" | "ticker">,
|
|
36
|
+
): string | undefined {
|
|
37
|
+
switch (candidate.instrumentClass) {
|
|
38
|
+
case "equity":
|
|
39
|
+
return "EQ";
|
|
40
|
+
case "fund":
|
|
41
|
+
return /\bET[FNP]\b/i.test(rawInstrumentType(candidate)) ? "ETF" : "FUND";
|
|
42
|
+
case "derivative":
|
|
43
|
+
return "DERIV";
|
|
44
|
+
case "other":
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
22
49
|
export function normalizeCommandTickerSearchText(value: string): string {
|
|
23
50
|
return value.trim().toUpperCase().replace(/[^A-Z0-9]+/g, "");
|
|
24
51
|
}
|
|
@@ -53,29 +80,43 @@ export function mergeTickerSearchResultItems(
|
|
|
53
80
|
: item);
|
|
54
81
|
}
|
|
55
82
|
|
|
83
|
+
export const ROOT_INSTRUMENTS_CATEGORY = "Instruments";
|
|
84
|
+
|
|
85
|
+
/** Enough to surface the listing the user means without burying the sections below. */
|
|
86
|
+
const ROOT_INSTRUMENTS_LIMIT = 5;
|
|
87
|
+
|
|
88
|
+
function isInstrumentItem(item: ResultItem): boolean {
|
|
89
|
+
return item.kind === "ticker" || item.kind === "search";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Fold symbol-search rows into a plain root query's list. An exact symbol hit
|
|
94
|
+
* is promoted ahead of everything; the rest collapse into one Instruments
|
|
95
|
+
* section with one row per symbol, since the listing split of the DES route
|
|
96
|
+
* is noise next to panes and commands. Info rows ("no matches", "search
|
|
97
|
+
* failed") are dropped: the instruments are an extra here, never the answer.
|
|
98
|
+
*/
|
|
56
99
|
export function mergePlainRootTickerResults(
|
|
57
100
|
query: string,
|
|
58
101
|
providerItems: ResultItem[],
|
|
59
102
|
rootItems: ResultItem[],
|
|
60
103
|
): ResultItem[] {
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
104
|
+
const seenSymbols = new Set<string>();
|
|
105
|
+
const instruments: ResultItem[] = [];
|
|
106
|
+
for (const item of providerItems) {
|
|
107
|
+
if (!isInstrumentItem(item)) continue;
|
|
108
|
+
const symbol = item.label.trim().toUpperCase();
|
|
109
|
+
if (seenSymbols.has(symbol)) continue;
|
|
110
|
+
seenSymbols.add(symbol);
|
|
111
|
+
instruments.push(item);
|
|
112
|
+
if (instruments.length >= ROOT_INSTRUMENTS_LIMIT) break;
|
|
113
|
+
}
|
|
114
|
+
if (instruments.length === 0) return rootItems;
|
|
72
115
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.forEach((item) => addItem(item, { skipInfo: true }));
|
|
80
|
-
return merged.length > 0 ? merged : rootItems;
|
|
116
|
+
const isExact = (item: ResultItem) => item.category === "Exact Match" || isExactTickerResultMatch(item, query);
|
|
117
|
+
return [
|
|
118
|
+
...instruments.filter(isExact).map((item) => ({ ...item, category: "Exact Match" })),
|
|
119
|
+
...rootItems,
|
|
120
|
+
...instruments.filter((item) => !isExact(item)).map((item) => ({ ...item, category: ROOT_INSTRUMENTS_CATEGORY })),
|
|
121
|
+
];
|
|
81
122
|
}
|
|
@@ -26,7 +26,7 @@ import type {
|
|
|
26
26
|
type CloseAll = (options?: { revertThemePreview?: boolean }) => void;
|
|
27
27
|
type Notify = (body: string, options?: { type?: "info" | "success" | "error" }) => void;
|
|
28
28
|
type OpenModeRoute = (
|
|
29
|
-
screen: "ticker-search" | "
|
|
29
|
+
screen: "ticker-search" | "layout",
|
|
30
30
|
initialQuery?: string,
|
|
31
31
|
payload?: Record<string, unknown>,
|
|
32
32
|
) => void;
|
|
@@ -80,15 +80,6 @@ export function useCommandBarRouteActions({
|
|
|
80
80
|
stateRef,
|
|
81
81
|
updateTopRoute,
|
|
82
82
|
}: UseCommandBarRouteActionsOptions) {
|
|
83
|
-
const buildPluginItems = useCallback((query: string): ResultItem[] => buildPluginToggleItems({
|
|
84
|
-
disabledPlugins: state.config.disabledPlugins || [],
|
|
85
|
-
dispatch,
|
|
86
|
-
getConfig: () => stateRef.current.config,
|
|
87
|
-
persistConfig,
|
|
88
|
-
pluginRegistry,
|
|
89
|
-
query,
|
|
90
|
-
}), [dispatch, persistConfig, pluginRegistry, state.config.disabledPlugins, stateRef]);
|
|
91
|
-
|
|
92
83
|
const buildWindowModeItems = useCallback((arg: string): ResultItem[] => buildWindowModeResultItems({
|
|
93
84
|
arg,
|
|
94
85
|
closeAll,
|
|
@@ -235,7 +226,6 @@ export function useCommandBarRouteActions({
|
|
|
235
226
|
activatePaneSettingField,
|
|
236
227
|
buildLayoutItems,
|
|
237
228
|
buildPaneSettingItems,
|
|
238
|
-
buildPluginItems,
|
|
239
229
|
buildWindowModeItems,
|
|
240
230
|
executeCollectionCommand,
|
|
241
231
|
openPaneSettingsRoute,
|
|
@@ -243,73 +233,3 @@ export function useCommandBarRouteActions({
|
|
|
243
233
|
};
|
|
244
234
|
}
|
|
245
235
|
|
|
246
|
-
function buildPluginToggleItems({
|
|
247
|
-
disabledPlugins,
|
|
248
|
-
dispatch,
|
|
249
|
-
getConfig,
|
|
250
|
-
persistConfig,
|
|
251
|
-
pluginRegistry,
|
|
252
|
-
query,
|
|
253
|
-
}: {
|
|
254
|
-
disabledPlugins: readonly string[];
|
|
255
|
-
dispatch: Dispatch<AppAction>;
|
|
256
|
-
getConfig: () => AppState["config"];
|
|
257
|
-
persistConfig: (nextConfig: AppState["config"]) => void;
|
|
258
|
-
pluginRegistry: PluginRegistry;
|
|
259
|
-
query: string;
|
|
260
|
-
}): ResultItem[] {
|
|
261
|
-
const normalizedQuery = query.trim().toLowerCase();
|
|
262
|
-
const pluginQuery = normalizedQuery === "plugin" || normalizedQuery === "plugins"
|
|
263
|
-
? ""
|
|
264
|
-
: normalizedQuery;
|
|
265
|
-
const toggleable = [...pluginRegistry.allPlugins.values()].filter((plugin) => plugin.toggleable);
|
|
266
|
-
const filtered = pluginQuery
|
|
267
|
-
? toggleable.filter((plugin) => (
|
|
268
|
-
[
|
|
269
|
-
plugin.name,
|
|
270
|
-
plugin.id,
|
|
271
|
-
plugin.description,
|
|
272
|
-
...pluginRegistry.getPluginPaneIds(plugin.id).flatMap((paneId) => [
|
|
273
|
-
paneId,
|
|
274
|
-
pluginRegistry.panes.get(paneId)?.name,
|
|
275
|
-
]),
|
|
276
|
-
...pluginRegistry.getPluginPaneTemplateIds(plugin.id).flatMap((templateId) => {
|
|
277
|
-
const template = pluginRegistry.paneTemplates.get(templateId);
|
|
278
|
-
return [
|
|
279
|
-
templateId,
|
|
280
|
-
template?.label,
|
|
281
|
-
template?.description,
|
|
282
|
-
...(template?.keywords ?? []),
|
|
283
|
-
];
|
|
284
|
-
}),
|
|
285
|
-
].some((term) => typeof term === "string" && term.toLowerCase().includes(pluginQuery))
|
|
286
|
-
))
|
|
287
|
-
: toggleable;
|
|
288
|
-
|
|
289
|
-
return filtered.map((plugin): ResultItem => {
|
|
290
|
-
const enabled = !disabledPlugins.includes(plugin.id);
|
|
291
|
-
const toggleAction = () => {
|
|
292
|
-
dispatch({ type: "TOGGLE_PLUGIN", pluginId: plugin.id });
|
|
293
|
-
const currentConfig = getConfig();
|
|
294
|
-
const nextDisabled = enabled
|
|
295
|
-
? [...disabledPlugins, plugin.id]
|
|
296
|
-
: disabledPlugins.filter((entry) => entry !== plugin.id);
|
|
297
|
-
if (enabled) {
|
|
298
|
-
for (const paneId of pluginRegistry.getPluginPaneIds(plugin.id)) {
|
|
299
|
-
pluginRegistry.hidePane(paneId);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
persistConfig({ ...currentConfig, disabledPlugins: nextDisabled });
|
|
303
|
-
};
|
|
304
|
-
return {
|
|
305
|
-
id: `plugin:${plugin.id}`,
|
|
306
|
-
label: plugin.name,
|
|
307
|
-
detail: plugin.description || "",
|
|
308
|
-
category: "Plugins",
|
|
309
|
-
kind: "plugin",
|
|
310
|
-
checked: enabled,
|
|
311
|
-
pluginToggle: toggleAction,
|
|
312
|
-
action: toggleAction,
|
|
313
|
-
};
|
|
314
|
-
});
|
|
315
|
-
}
|
|
@@ -8,7 +8,7 @@ interface UseCommandBarLaunchRequestOptions {
|
|
|
8
8
|
commandBarLaunchRequest: AppState["commandBarLaunchRequest"];
|
|
9
9
|
commandBarOpen: boolean;
|
|
10
10
|
openModeRoute: (
|
|
11
|
-
screen: "ticker-search" | "
|
|
11
|
+
screen: "ticker-search" | "layout",
|
|
12
12
|
initialQuery?: string,
|
|
13
13
|
payload?: Record<string, unknown>,
|
|
14
14
|
) => void;
|
|
@@ -2,6 +2,7 @@ import { useMemo } from "react";
|
|
|
2
2
|
import type { PluginRegistry } from "../../../plugins/registry";
|
|
3
3
|
import {
|
|
4
4
|
getEmptyState,
|
|
5
|
+
type CommandBarCategoryPriorities,
|
|
5
6
|
type CommandBarMode,
|
|
6
7
|
type CommandBarSectionOrder,
|
|
7
8
|
} from "../view-model";
|
|
@@ -33,13 +34,13 @@ interface BuildRouteListStateOptions {
|
|
|
33
34
|
query: string,
|
|
34
35
|
options?: { keepRouteOpen?: boolean },
|
|
35
36
|
) => ResultItem[];
|
|
36
|
-
buildPluginItems: (query: string) => ResultItem[];
|
|
37
37
|
currentRoute: CommandBarRoute | null;
|
|
38
38
|
orderedRootResults: ResultItem[];
|
|
39
39
|
pluginRegistry: Pick<PluginRegistry, "resolvePaneSettings">;
|
|
40
40
|
rootHoveredIdx: number | null;
|
|
41
41
|
rootModeKind: CommandBarMode;
|
|
42
42
|
rootQuery: string;
|
|
43
|
+
rootCategoryPriorities?: CommandBarCategoryPriorities;
|
|
43
44
|
rootSearching: boolean;
|
|
44
45
|
rootSectionOrder: CommandBarSectionOrder;
|
|
45
46
|
rootSelectedIdx: number;
|
|
@@ -53,12 +54,12 @@ function buildRouteListState(options: BuildRouteListStateOptions): ListScreenSta
|
|
|
53
54
|
adaptTickerSearchRouteResult,
|
|
54
55
|
buildLayoutItems,
|
|
55
56
|
buildPaneSettingItems,
|
|
56
|
-
buildPluginItems,
|
|
57
57
|
currentRoute,
|
|
58
58
|
orderedRootResults,
|
|
59
59
|
pluginRegistry,
|
|
60
60
|
rootHoveredIdx,
|
|
61
61
|
rootModeKind,
|
|
62
|
+
rootCategoryPriorities,
|
|
62
63
|
rootQuery,
|
|
63
64
|
rootSearching,
|
|
64
65
|
rootSectionOrder,
|
|
@@ -86,28 +87,12 @@ function buildRouteListState(options: BuildRouteListStateOptions): ListScreenSta
|
|
|
86
87
|
footerLeft: getScreenFooterLeft(null),
|
|
87
88
|
footerRight: getScreenFooterRight(null),
|
|
88
89
|
sectionOrder: rootSectionOrder,
|
|
90
|
+
categoryPriorities: rootCategoryPriorities,
|
|
89
91
|
};
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
if (currentRoute.kind === "mode") {
|
|
93
95
|
switch (currentRoute.screen) {
|
|
94
|
-
case "plugins": {
|
|
95
|
-
const results = buildPluginItems(currentRoute.query);
|
|
96
|
-
return {
|
|
97
|
-
kind: "mode",
|
|
98
|
-
title: "Manage Plugins",
|
|
99
|
-
subtitle: "Toggle optional plugins without leaving the command bar.",
|
|
100
|
-
query: currentRoute.query,
|
|
101
|
-
selectedIdx: currentRoute.selectedIdx,
|
|
102
|
-
hoveredIdx: currentRoute.hoveredIdx,
|
|
103
|
-
results: orderListResults(results),
|
|
104
|
-
searching: false,
|
|
105
|
-
emptyLabel: getEmptyState("plugins", currentRoute.query).label,
|
|
106
|
-
emptyDetail: getEmptyState("plugins", currentRoute.query).detail,
|
|
107
|
-
footerLeft: getScreenFooterLeft(currentRoute),
|
|
108
|
-
footerRight: getScreenFooterRight(currentRoute),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
96
|
case "layout": {
|
|
112
97
|
const results = buildLayoutItems(currentRoute.query);
|
|
113
98
|
return {
|
|
@@ -207,10 +192,10 @@ export function useRouteListState(options: BuildRouteListStateOptions): ListScre
|
|
|
207
192
|
adaptTickerSearchRouteResult,
|
|
208
193
|
buildLayoutItems,
|
|
209
194
|
buildPaneSettingItems,
|
|
210
|
-
buildPluginItems,
|
|
211
195
|
currentRoute,
|
|
212
196
|
orderedRootResults,
|
|
213
197
|
pluginRegistry,
|
|
198
|
+
rootCategoryPriorities,
|
|
214
199
|
rootHoveredIdx,
|
|
215
200
|
rootModeKind,
|
|
216
201
|
rootQuery,
|
|
@@ -226,10 +211,10 @@ export function useRouteListState(options: BuildRouteListStateOptions): ListScre
|
|
|
226
211
|
adaptTickerSearchRouteResult,
|
|
227
212
|
buildLayoutItems,
|
|
228
213
|
buildPaneSettingItems,
|
|
229
|
-
buildPluginItems,
|
|
230
214
|
currentRoute,
|
|
231
215
|
orderedRootResults,
|
|
232
216
|
pluginRegistry,
|
|
217
|
+
rootCategoryPriorities,
|
|
233
218
|
rootHoveredIdx,
|
|
234
219
|
rootModeKind,
|
|
235
220
|
rootQuery,
|
|
@@ -28,7 +28,7 @@ import type { OpenInlineConfirm } from "./routing/confirm";
|
|
|
28
28
|
import { activatePickerSelectionAction } from "./picker-activation";
|
|
29
29
|
|
|
30
30
|
type OpenModeRouteFn = (
|
|
31
|
-
screen: "ticker-search" | "
|
|
31
|
+
screen: "ticker-search" | "layout",
|
|
32
32
|
initialQuery?: string,
|
|
33
33
|
payload?: Record<string, unknown>,
|
|
34
34
|
) => void;
|
|
@@ -120,7 +120,8 @@ describe("CommandBar AI assist", () => {
|
|
|
120
120
|
query="new chat pane"
|
|
121
121
|
configurePluginRegistry={configureEarningsRegistry(created)}
|
|
122
122
|
/>,
|
|
123
|
-
|
|
123
|
+
// Wide enough for the answer's label and its title to share one row.
|
|
124
|
+
{ width: 120, height: 20 },
|
|
124
125
|
);
|
|
125
126
|
|
|
126
127
|
await testSetup.renderOnce();
|
|
@@ -131,12 +132,14 @@ describe("CommandBar AI assist", () => {
|
|
|
131
132
|
expect(sentCommandCount).toBeGreaterThan(0);
|
|
132
133
|
|
|
133
134
|
releaseResponse();
|
|
134
|
-
const answered = await waitForFrameToContain("
|
|
135
|
+
const answered = await waitForFrameToContain("#general · Open the general channel", ASSIST_WAIT_ATTEMPTS);
|
|
135
136
|
expect(answered).not.toContain("Thinking…");
|
|
136
137
|
expect(requests).toHaveLength(1);
|
|
137
|
-
// Above the local matches,
|
|
138
|
-
//
|
|
138
|
+
// Above the local matches, laid out like any other row with the prefix in
|
|
139
|
+
// the badge column, and holding the selection an untouched query never
|
|
140
|
+
// moved: plain Enter runs the AI's best guess.
|
|
139
141
|
expect(answered.indexOf("Ask AI")).toBeLessThan(answered.indexOf("Panes"));
|
|
142
|
+
expect(answered).toMatch(/CHAT\s+#general · Open the general channel/);
|
|
140
143
|
|
|
141
144
|
await emitKeypress(testSetup, { name: "return", sequence: "\r" });
|
|
142
145
|
expect(created).toEqual([{ templateId: "new-chat-pane", options: { arg: "#general" } }]);
|
|
@@ -162,7 +165,8 @@ describe("CommandBar AI assist", () => {
|
|
|
162
165
|
query="new chat pane"
|
|
163
166
|
configurePluginRegistry={configureEarningsRegistry(created)}
|
|
164
167
|
/>,
|
|
165
|
-
|
|
168
|
+
// Wide enough for the answers' labels and titles to share one row.
|
|
169
|
+
{ width: 120, height: 20 },
|
|
166
170
|
);
|
|
167
171
|
|
|
168
172
|
await testSetup.renderOnce();
|
|
@@ -170,9 +174,9 @@ describe("CommandBar AI assist", () => {
|
|
|
170
174
|
// Down lands on the local match while a single "Thinking…" row sits above.
|
|
171
175
|
await emitKeypress(testSetup, { name: "down" });
|
|
172
176
|
releaseResponse();
|
|
173
|
-
await waitForFrameToContain("
|
|
177
|
+
await waitForFrameToContain("#random · Open the random channel", ASSIST_WAIT_ATTEMPTS);
|
|
174
178
|
|
|
175
|
-
// Two answers replaced that one row, so the chosen row moved down by one
|
|
179
|
+
// Two answers replaced that one row, so the chosen row moved down by one;
|
|
176
180
|
// Enter still runs it rather than whatever now sits at its old index.
|
|
177
181
|
await emitKeypress(testSetup, { name: "return", sequence: "\r" });
|
|
178
182
|
expect(created).toEqual([{ templateId: "new-chat-pane", options: undefined }]);
|
|
@@ -196,7 +200,7 @@ describe("CommandBar AI assist", () => {
|
|
|
196
200
|
);
|
|
197
201
|
|
|
198
202
|
await testSetup.renderOnce();
|
|
199
|
-
await waitForFrameToContain("
|
|
203
|
+
await waitForFrameToContain("NVDA · Earnings Calendar", ASSIST_WAIT_ATTEMPTS);
|
|
200
204
|
|
|
201
205
|
await emitKeypress(testSetup, { name: "return", sequence: "\r" });
|
|
202
206
|
expect(created).toEqual([{ templateId: "earnings-calendar-pane", options: undefined }]);
|
|
@@ -275,8 +279,8 @@ describe("CommandBar AI assist", () => {
|
|
|
275
279
|
await testSetup.renderOnce();
|
|
276
280
|
expect(requests).toEqual([]);
|
|
277
281
|
|
|
278
|
-
// The offer
|
|
279
|
-
// local match the user was already looking at.
|
|
282
|
+
// The offer sits under the list and never takes the Enter that belongs to
|
|
283
|
+
// the local match the user was already looking at.
|
|
280
284
|
await emitKeypress(testSetup, { name: "return", sequence: "\r" });
|
|
281
285
|
expect(created).toEqual([{ templateId: "new-chat-pane", options: undefined }]);
|
|
282
286
|
});
|
|
@@ -82,7 +82,13 @@ export function useCommandBarEnvironment() {
|
|
|
82
82
|
}, []);
|
|
83
83
|
const { symbol: activeTickerSymbol, ticker: activeTickerData, financials: activeFinancials } = useFocusedTicker();
|
|
84
84
|
const { width: termWidth, height: termHeight } = useViewport();
|
|
85
|
-
const {
|
|
85
|
+
const {
|
|
86
|
+
nativePaneChrome: nativePaneChromeCapability,
|
|
87
|
+
cellWidthPx = 8,
|
|
88
|
+
cellHeightPx = 18,
|
|
89
|
+
nativeWindowChrome,
|
|
90
|
+
titleBarOverlay,
|
|
91
|
+
} = useUiCapabilities();
|
|
86
92
|
const nativePaneChrome = nativePaneChromeCapability === true;
|
|
87
93
|
const availableCommands = useMemo(
|
|
88
94
|
() => nativePaneChrome
|
|
@@ -111,6 +117,7 @@ export function useCommandBarEnvironment() {
|
|
|
111
117
|
getCommittedThemeId,
|
|
112
118
|
nativeListScrollRef,
|
|
113
119
|
nativePaneChrome,
|
|
120
|
+
nativeWindowChrome,
|
|
114
121
|
persistConfig,
|
|
115
122
|
skipTickerSearchDebounceRef,
|
|
116
123
|
state,
|