gloomberb 0.16.2 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +34 -16
- package/src/api-client/index.ts +12 -0
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +88 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +31 -0
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +57 -1
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/app/global-shortcuts.ts +11 -1
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +18 -1
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +70 -0
- package/src/brokers/account-cache.ts +45 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +23 -9
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +29 -0
- package/src/cli/commands/crypto-hints.ts +12 -4
- package/src/cli/commands/market.ts +524 -148
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +422 -0
- package/src/cli/commands/overview.ts +223 -42
- package/src/cli/commands/search.ts +29 -8
- package/src/cli/commands/system.ts +99 -19
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +200 -73
- package/src/cli/desktop-pane-shot.ts +100 -16
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +7 -4
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/help.ts +40 -7
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index-roots.ts +51 -0
- package/src/cli/index.ts +21 -13
- package/src/cli/listing-arg.ts +211 -3
- package/src/cli/not-a-ticker.ts +37 -0
- package/src/cli/options.ts +55 -7
- package/src/cli/pane-functions/capabilities.ts +13 -2
- package/src/cli/pane-functions/catalog.ts +13 -2
- package/src/cli/pane-functions/data.ts +36 -5
- package/src/cli/pane-functions/dom.ts +89 -28
- package/src/cli/pane-functions/freshness.ts +205 -26
- package/src/cli/pane-functions/function-help.ts +71 -24
- package/src/cli/pane-functions/headless.ts +168 -35
- package/src/cli/pane-functions/index.ts +12 -2
- package/src/cli/pane-functions/market-session.ts +133 -0
- package/src/cli/pane-functions/options.ts +15 -4
- package/src/cli/pane-functions/report-notices.ts +63 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +32 -8
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +109 -23
- package/src/cli/registry.ts +8 -4
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +63 -16
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/components/chart/composite/composite-chart.tsx +43 -4
- package/src/components/chart/composite/legend.tsx +39 -6
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/data-table/export.ts +6 -51
- package/src/components/data-table/view.tsx +31 -10
- package/src/components/layout/floating-pane.tsx +6 -2
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +46 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/header.tsx +2 -1
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +16 -7
- package/src/components/layout/shell/drag/live.ts +193 -0
- package/src/components/layout/shell/drag/overlays.tsx +179 -35
- package/src/components/layout/shell/drag/runtime.ts +62 -50
- package/src/components/layout/shell/drag/slide.ts +10 -0
- package/src/components/layout/shell/index.tsx +84 -57
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +28 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
- package/src/components/layout/shell/native/surfaces.ts +30 -14
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +461 -180
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +9 -5
- package/src/components/metric-treemap/heat-surface.tsx +27 -8
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-wizard.tsx +49 -40
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +6 -2
- package/src/components/ui/button.tsx +10 -0
- package/src/components/ui/data-table/index.tsx +38 -0
- package/src/components/ui/data-table/types.ts +8 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/icon.tsx +11 -2
- package/src/components/ui/index.ts +1 -1
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +37 -3
- package/src/data/json-persistence.ts +17 -3
- package/src/data/json-storage.ts +2 -0
- package/src/data/memory-resource-store.ts +46 -0
- package/src/i18n/es.ts +14 -1
- package/src/i18n/ja.ts +14 -1
- package/src/i18n/ko.ts +14 -1
- package/src/i18n/zh-cn.ts +14 -1
- package/src/i18n/zh-tw.ts +14 -1
- package/src/layout/desks.ts +1 -2
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/market-data/market/freshness.ts +156 -11
- package/src/market-data/market/status.ts +40 -0
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/quotes/contributions.ts +19 -2
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/metadata.ts +16 -0
- package/src/market-data/quotes/screener-live-quotes.ts +56 -5
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -4
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/analytics/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
- package/src/plugins/builtin/analytics/risk-model.ts +37 -8
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
- package/src/plugins/builtin/attention/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +48 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +112 -4
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
- package/src/plugins/builtin/cloud/askg/model.ts +129 -70
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
- package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +360 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/starter-symbols.ts +8 -0
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +666 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +234 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/upgrade-dialog.tsx +26 -2
- package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
- package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/pane.tsx +1 -1
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +107 -64
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/index.tsx +68 -22
- package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/headless.ts +9 -3
- package/src/plugins/builtin/gpu/model.ts +14 -5
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +32 -6
- package/src/plugins/builtin/holders/pane.tsx +25 -13
- package/src/plugins/builtin/holders/report-header.ts +46 -5
- package/src/plugins/builtin/insider/index.tsx +4 -4
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +12 -2
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +22 -10
- package/src/plugins/builtin/iv-history/index.tsx +3 -3
- package/src/plugins/builtin/iv-history/model.ts +61 -13
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +121 -45
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +24 -0
- package/src/plugins/builtin/macro-day/headless.ts +11 -8
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +11 -6
- package/src/plugins/builtin/macro-day/pane.tsx +12 -8
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +94 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +8 -1
- package/src/plugins/builtin/market-movers/model.ts +71 -17
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/members/pane.tsx +10 -0
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +161 -12
- package/src/plugins/builtin/options-positioning/headless.ts +4 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +73 -17
- package/src/plugins/builtin/options-scenario/headless.ts +71 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +284 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/equity-row.tsx +8 -5
- package/src/plugins/builtin/perps/model.ts +16 -5
- package/src/plugins/builtin/perps/pane.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +344 -32
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +87 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +3 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +18 -9
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
- package/src/plugins/builtin/portfolio-list/cli/render.ts +89 -18
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
- package/src/plugins/builtin/portfolio-list/headless.ts +40 -7
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +7 -4
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +22 -4
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
- package/src/plugins/builtin/realized-vol/headless.ts +3 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +7 -3
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/pane.tsx +1 -1
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/shared/command-tab.ts +51 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +260 -0
- package/src/plugins/builtin/shared/report-freshness.ts +50 -2
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/index.tsx +19 -4
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +1 -10
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/themes/pane.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +63 -25
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -4
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
- package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +197 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +124 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +2 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +18 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/index.ts +6 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +27 -14
- package/src/plugins/builtin/world-venue-map/layers.ts +68 -10
- package/src/plugins/builtin/world-venue-map/map.tsx +198 -62
- package/src/plugins/builtin/world-venue-map/model.ts +16 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +3 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +16 -10
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +127 -63
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +84 -24
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +5 -0
- package/src/remote/controller.ts +3 -53
- package/src/remote/matching.ts +69 -0
- package/src/remote/schema.ts +1 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/host/box.tsx +113 -17
- package/src/renderers/dom/host/drag-shield.ts +35 -0
- package/src/renderers/dom/host/live-frame.ts +62 -0
- package/src/renderers/dom/host/mouse.ts +8 -1
- package/src/renderers/dom/host/scroll-box.tsx +6 -5
- package/src/renderers/dom/host/tabs.tsx +3 -2
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +26 -5
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +15 -1
- package/src/renderers/electrobun/shared/protocol.ts +12 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
- package/src/renderers/electrobun/view/host/native.ts +0 -10
- package/src/renderers/electrobun/view/host/window-move.ts +28 -0
- package/src/renderers/electrobun/view/main.tsx +4 -1
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +19 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +20 -21
- package/src/sources/listing-symbols.ts +11 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +8 -4
- package/src/sources/provider-router/financial-routes.ts +13 -7
- package/src/sources/provider-router/financials.ts +106 -16
- package/src/sources/provider-router/history.ts +27 -11
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +24 -6
- package/src/sources/sec-edgar.ts +68 -8
- package/src/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/margin-account.ts +108 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/search/index.ts +22 -2
- package/src/tickers/search/ranking.ts +45 -1
- package/src/tickers/search/types.ts +3 -1
- package/src/time-series/resolution.ts +15 -0
- package/src/time-series/resolve.ts +1 -14
- package/src/types/config.ts +61 -1
- package/src/types/financials.ts +32 -3
- package/src/types/headless.ts +11 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +49 -3
- package/src/ui/host.tsx +16 -0
- package/src/ui/index.tsx +10 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/utils/cli-output.ts +14 -1
- package/src/utils/currency-units.ts +8 -3
- package/src/utils/depositary-receipt.ts +54 -10
- package/src/utils/display-number.ts +63 -0
- package/src/utils/exchanges.ts +13 -0
- package/src/utils/format.ts +2 -1
- package/src/utils/fundamentals.ts +17 -1
- package/src/utils/fx-market-hours.ts +34 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history-integrity.ts +19 -6
- package/src/utils/price-history.ts +39 -6
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +159 -30
- package/src/utils/sec.ts +38 -34
- package/src/utils/throttled-fetch.ts +51 -22
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
getDockedPaneIds,
|
|
5
5
|
removePane,
|
|
6
6
|
} from "../../../layout/pane-manager";
|
|
7
|
+
import { paneMoveBackTarget, paneNewLayoutBlock } from "../../../layout/pane-layout-move";
|
|
8
|
+
import { resolveTickerForPane } from "../../../state/app/context";
|
|
7
9
|
import { findPaneInstance } from "../../../types/config";
|
|
10
|
+
import { tf } from "../../../i18n";
|
|
8
11
|
import type { ResultItem } from "../list/model";
|
|
9
12
|
import type { LayoutItemsContext } from "./types";
|
|
10
13
|
import { WINDOW_MODE_COMMAND_OPTIONS } from "./window-mode";
|
|
@@ -20,6 +23,7 @@ export function buildFocusedPaneLayoutItems({
|
|
|
20
23
|
persistLayoutChange,
|
|
21
24
|
pluginRegistry,
|
|
22
25
|
pushRoute,
|
|
26
|
+
state,
|
|
23
27
|
}: LayoutItemsContext): ResultItem[] {
|
|
24
28
|
const focusedPane = focusedPaneId ? findPaneInstance(currentLayout, focusedPaneId) : null;
|
|
25
29
|
const focusedPaneDef = focusedPane ? pluginRegistry.panes.get(focusedPane.paneId) : null;
|
|
@@ -37,6 +41,12 @@ export function buildFocusedPaneLayoutItems({
|
|
|
37
41
|
|
|
38
42
|
const dockedPaneIds = getDockedPaneIds(currentLayout);
|
|
39
43
|
const focusedFloating = currentLayout.floating.find((entry) => entry.instanceId === focusedPane.instanceId);
|
|
44
|
+
const newLayoutBlock = paneNewLayoutBlock(
|
|
45
|
+
currentLayout,
|
|
46
|
+
focusedPane.instanceId,
|
|
47
|
+
(instanceId) => resolveTickerForPane(state, instanceId),
|
|
48
|
+
);
|
|
49
|
+
const moveBack = paneMoveBackTarget(state.config, focusedPane.instanceId);
|
|
40
50
|
|
|
41
51
|
return [
|
|
42
52
|
{
|
|
@@ -65,6 +75,34 @@ export function buildFocusedPaneLayoutItems({
|
|
|
65
75
|
pluginRegistry.togglePaneFullscreen(focusedPane.instanceId);
|
|
66
76
|
},
|
|
67
77
|
},
|
|
78
|
+
{
|
|
79
|
+
id: "layout-move-to-new-layout",
|
|
80
|
+
label: "Move to New Layout",
|
|
81
|
+
detail: newLayoutBlock === "only-pane"
|
|
82
|
+
? "Already the only pane in this layout"
|
|
83
|
+
: "Give the focused pane a layout of its own that it fills",
|
|
84
|
+
searchText: "own layout tab fullscreen",
|
|
85
|
+
category: "Focused Pane",
|
|
86
|
+
kind: "action",
|
|
87
|
+
disabled: newLayoutBlock === "only-pane" || newLayoutBlock === "detached",
|
|
88
|
+
action: () => {
|
|
89
|
+
closeAll({ revertThemePreview: false });
|
|
90
|
+
pluginRegistry.movePaneToNewLayout(focusedPane.instanceId);
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
...(moveBack ? [{
|
|
94
|
+
id: "layout-move-back",
|
|
95
|
+
label: tf("Move Back to {layout}", { layout: moveBack.name }),
|
|
96
|
+
detail: moveBack.original
|
|
97
|
+
? "Return the focused pane to the layout it came from"
|
|
98
|
+
: "The layout it came from is gone, so it docks in this one instead",
|
|
99
|
+
category: "Focused Pane",
|
|
100
|
+
kind: "action" as const,
|
|
101
|
+
action: () => {
|
|
102
|
+
closeAll({ revertThemePreview: false });
|
|
103
|
+
pluginRegistry.movePaneBack(focusedPane.instanceId);
|
|
104
|
+
},
|
|
105
|
+
}] : []),
|
|
68
106
|
...WINDOW_MODE_COMMAND_OPTIONS.map((option) => ({
|
|
69
107
|
id: `layout-window-mode:${option.mode}`,
|
|
70
108
|
label: option.label,
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type SharedWorkflowDeps,
|
|
30
30
|
} from "../workflow/ops";
|
|
31
31
|
import type { PluginRegistry } from "../../../plugins/registry";
|
|
32
|
+
import { PluginOffError, notifyPluginOff } from "../../../plugins/plugin-off";
|
|
32
33
|
import { shouldOpenPaneTemplateConfig } from "./workflow-route";
|
|
33
34
|
|
|
34
35
|
type CloseAllFn = (options?: { revertThemePreview?: boolean }) => void;
|
|
@@ -107,6 +108,10 @@ export function useCommandBarPaneTemplateActions({
|
|
|
107
108
|
await pluginRegistry.createPaneFromTemplateAsync(template.id, createOptions);
|
|
108
109
|
closeAll({ revertThemePreview: false });
|
|
109
110
|
} catch (error) {
|
|
111
|
+
if (error instanceof PluginOffError) {
|
|
112
|
+
notifyPluginOff(pluginRegistry, error, () => { void openPaneTemplateDirect(template, createOptions); });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
110
115
|
const displayLabel = getPaneTemplateDisplayLabel(template);
|
|
111
116
|
notify(
|
|
112
117
|
error instanceof Error ? error.message : `Could not create ${displayLabel.toLowerCase()}.`,
|
|
@@ -147,6 +147,8 @@ export function createRootCommandItemBuilder({
|
|
|
147
147
|
return command.description;
|
|
148
148
|
case "toggle-value-flashing":
|
|
149
149
|
return state.config.valueFlashingEnabled ? "Currently on" : "Currently off";
|
|
150
|
+
case "toggle-presentation-mode":
|
|
151
|
+
return state.config.presentationMode ? "Currently on" : "Currently off";
|
|
150
152
|
case "toggle-crash-reports":
|
|
151
153
|
return state.config.telemetry?.crashReports === false ? "Currently off" : "Currently on";
|
|
152
154
|
case "toggle-usage-counts":
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import type { DisabledPluginOwner, PluginRegistry } from "../../../../plugins/registry";
|
|
3
|
+
import { getPaneTemplateDisplayLabel, paneTemplateShortcutPrefixes } from "../../pane-templates/items";
|
|
4
|
+
import type { ResultItem } from "../../list/model";
|
|
5
|
+
import { PLUGIN_INSTALL_CATEGORY } from "../../view-model";
|
|
6
|
+
|
|
7
|
+
/** A typed code whose function belongs to a plugin that is switched off. */
|
|
8
|
+
interface PluginTurnOnOffer {
|
|
9
|
+
owner: DisabledPluginOwner;
|
|
10
|
+
code: string;
|
|
11
|
+
/** The function's name, as its row reads when the plugin is on. */
|
|
12
|
+
label: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type TurnOnRegistry = Pick<
|
|
16
|
+
PluginRegistry,
|
|
17
|
+
"allPlugins" | "commands" | "getCommandPluginId" | "getDisabledPaneTemplateOwner" | "paneTemplates"
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Matches the code alone or as the first word, case-insensitively, against
|
|
22
|
+
* the functions of switched-off plugins. Only plugins the user can switch
|
|
23
|
+
* back on are offered.
|
|
24
|
+
*/
|
|
25
|
+
function matchPluginTurnOnOffer({
|
|
26
|
+
query,
|
|
27
|
+
pluginRegistry,
|
|
28
|
+
disabledPlugins,
|
|
29
|
+
}: {
|
|
30
|
+
query: string;
|
|
31
|
+
pluginRegistry: TurnOnRegistry;
|
|
32
|
+
disabledPlugins: readonly string[];
|
|
33
|
+
}): PluginTurnOnOffer | null {
|
|
34
|
+
const code = (query.trim().split(/\s+/, 1)[0] ?? "").toUpperCase();
|
|
35
|
+
if (!code || disabledPlugins.length === 0) return null;
|
|
36
|
+
const canTurnOn = (owner: DisabledPluginOwner | null): owner is DisabledPluginOwner => (
|
|
37
|
+
!!owner && pluginRegistry.allPlugins.get(owner.id)?.toggleable === true
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
for (const template of pluginRegistry.paneTemplates.values()) {
|
|
41
|
+
if (!paneTemplateShortcutPrefixes(template).some((prefix) => prefix.trim().toUpperCase() === code)) continue;
|
|
42
|
+
const owner = pluginRegistry.getDisabledPaneTemplateOwner(template.id, disabledPlugins);
|
|
43
|
+
if (canTurnOn(owner)) return { owner, code, label: getPaneTemplateDisplayLabel(template) };
|
|
44
|
+
}
|
|
45
|
+
for (const [commandId, command] of pluginRegistry.commands) {
|
|
46
|
+
if (command.shortcut?.trim().toUpperCase() !== code) continue;
|
|
47
|
+
const pluginId = pluginRegistry.getCommandPluginId(commandId);
|
|
48
|
+
const plugin = pluginId ? pluginRegistry.allPlugins.get(pluginId) : undefined;
|
|
49
|
+
const owner = plugin && disabledPlugins.includes(plugin.id) ? { id: plugin.id, name: plugin.name } : null;
|
|
50
|
+
if (canTurnOn(owner)) return { owner, code, label: command.label };
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The row for a code whose plugin is off, or null. Enter turns the plugin on,
|
|
57
|
+
* then runs the typed text again, argument and all, as if just entered.
|
|
58
|
+
* `enabled` is false whenever something else claimed the query.
|
|
59
|
+
*/
|
|
60
|
+
export function useRootPluginTurnOnItem({
|
|
61
|
+
enabled,
|
|
62
|
+
query,
|
|
63
|
+
pluginRegistry,
|
|
64
|
+
disabledPlugins,
|
|
65
|
+
rerunQuery,
|
|
66
|
+
}: {
|
|
67
|
+
enabled: boolean;
|
|
68
|
+
query: string;
|
|
69
|
+
pluginRegistry: PluginRegistry;
|
|
70
|
+
disabledPlugins: readonly string[];
|
|
71
|
+
rerunQuery: (query: string) => void;
|
|
72
|
+
}): ResultItem | null {
|
|
73
|
+
return useMemo(() => {
|
|
74
|
+
const offer = enabled ? matchPluginTurnOnOffer({ query, pluginRegistry, disabledPlugins }) : null;
|
|
75
|
+
if (!offer) return null;
|
|
76
|
+
const actionLine = `Turn on ${offer.owner.name}`;
|
|
77
|
+
return {
|
|
78
|
+
id: `plugin-turn-on:${offer.owner.id}:${offer.code}`,
|
|
79
|
+
label: offer.label,
|
|
80
|
+
detail: actionLine,
|
|
81
|
+
category: PLUGIN_INSTALL_CATEGORY,
|
|
82
|
+
kind: "action",
|
|
83
|
+
right: offer.code,
|
|
84
|
+
searchText: [offer.code, offer.label, offer.owner.name].join(" "),
|
|
85
|
+
lines: [{ segments: [{ text: actionLine, emphasis: "match" }] }],
|
|
86
|
+
action: () => {
|
|
87
|
+
pluginRegistry.setPluginEnabled(offer.owner.id, true);
|
|
88
|
+
rerunQuery(query);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}, [disabledPlugins, enabled, pluginRegistry, query, rerunQuery]);
|
|
92
|
+
}
|
|
@@ -86,6 +86,12 @@ export interface RootResultModelOptions {
|
|
|
86
86
|
* user is aiming at, and only ever adds to what the bar already resolved.
|
|
87
87
|
*/
|
|
88
88
|
providerResultItems?: ResultItem[];
|
|
89
|
+
/**
|
|
90
|
+
* Rows from providers that answer from memory, built with the keystroke. The
|
|
91
|
+
* empty bar shows them under Suggested; typed text ranks them as one block
|
|
92
|
+
* among the local matches, at the place of their best row.
|
|
93
|
+
*/
|
|
94
|
+
providerMatchItems?: ResultItem[];
|
|
89
95
|
runDirectCommand: (command: Command, arg: string) => void;
|
|
90
96
|
runSecurityDescriptionShortcut: (query?: string) => void | Promise<void>;
|
|
91
97
|
state: AppState;
|
|
@@ -134,6 +140,32 @@ function buildBindKeyItem(
|
|
|
134
140
|
};
|
|
135
141
|
}
|
|
136
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Ranks a provider's in-memory rows with the local matches without reordering
|
|
145
|
+
* them: the provider decided which rows answer and in what order, so the block
|
|
146
|
+
* moves as one to where its best row would rank. A block none of whose rows
|
|
147
|
+
* the bar's own matching finds still shows, after the local matches.
|
|
148
|
+
*/
|
|
149
|
+
function rankMatchBlock(
|
|
150
|
+
localItems: ResultItem[],
|
|
151
|
+
blockItems: ResultItem[],
|
|
152
|
+
query: string,
|
|
153
|
+
): ResultItem[] {
|
|
154
|
+
if (blockItems.length === 0) {
|
|
155
|
+
return fuzzyFilter(localItems, query, rootItemSearchText, (item) => item.label);
|
|
156
|
+
}
|
|
157
|
+
const block = new Set(blockItems);
|
|
158
|
+
const ranked = fuzzyFilter([...localItems, ...blockItems], query, rootItemSearchText, (item) => item.label);
|
|
159
|
+
const firstBlockIndex = ranked.findIndex((item) => block.has(item));
|
|
160
|
+
const local = ranked.filter((item) => !block.has(item));
|
|
161
|
+
if (firstBlockIndex < 0) return [...local, ...blockItems];
|
|
162
|
+
return [...local.slice(0, firstBlockIndex), ...blockItems, ...local.slice(firstBlockIndex)];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function rootItemSearchText(item: ResultItem): string {
|
|
166
|
+
return `${item.label} ${item.searchText || ""} ${item.detail} ${item.right || ""}`;
|
|
167
|
+
}
|
|
168
|
+
|
|
137
169
|
/** Kept short: the empty bar is still a browse list of everything below. */
|
|
138
170
|
const MAX_RECENT_TICKER_ROWS = 4;
|
|
139
171
|
const MAX_RECENT_PANE_ROWS = 4;
|
|
@@ -211,6 +243,7 @@ export function buildRootResultModel(options: RootResultModelOptions): RootResul
|
|
|
211
243
|
rootQuery,
|
|
212
244
|
rootShortcutIntent,
|
|
213
245
|
providerResultItems = [],
|
|
246
|
+
providerMatchItems = [],
|
|
214
247
|
runDirectCommand,
|
|
215
248
|
runSecurityDescriptionShortcut,
|
|
216
249
|
state,
|
|
@@ -316,6 +349,7 @@ export function buildRootResultModel(options: RootResultModelOptions): RootResul
|
|
|
316
349
|
recentTickers: state.recentTickers ?? [],
|
|
317
350
|
}));
|
|
318
351
|
}
|
|
352
|
+
items.push(...providerMatchItems);
|
|
319
353
|
items.push(...paneShortcutItems());
|
|
320
354
|
for (const command of availableCommands) {
|
|
321
355
|
const item = commandToItem(command);
|
|
@@ -336,13 +370,7 @@ export function buildRootResultModel(options: RootResultModelOptions): RootResul
|
|
|
336
370
|
...tickerActionItems(),
|
|
337
371
|
...pluginCommandItems(),
|
|
338
372
|
];
|
|
339
|
-
|
|
340
|
-
allItems,
|
|
341
|
-
rootQuery,
|
|
342
|
-
(item) => `${item.label} ${item.searchText || ""} ${item.detail} ${item.right || ""}`,
|
|
343
|
-
(item) => item.label,
|
|
344
|
-
);
|
|
345
|
-
items.push(...matchedItems);
|
|
373
|
+
items.push(...rankMatchBlock(allItems, providerMatchItems, rootQuery));
|
|
346
374
|
}
|
|
347
375
|
|
|
348
376
|
const shortcutClaimedQuery = rootShortcutIntent.kind !== "none";
|
|
@@ -356,10 +384,12 @@ export function buildRootResultModel(options: RootResultModelOptions): RootResul
|
|
|
356
384
|
items.push(buildBindKeyItem(rootShortcutIntent, bindKey));
|
|
357
385
|
}
|
|
358
386
|
// A resolved prefix means the user is speaking the command language, so
|
|
359
|
-
//
|
|
360
|
-
|
|
361
|
-
|
|
387
|
+
// only providers that asked to answer after that code add rows, below the
|
|
388
|
+
// code's own.
|
|
389
|
+
if (shortcutClaimedQuery) {
|
|
390
|
+
items.push(...providerMatchItems);
|
|
362
391
|
}
|
|
392
|
+
items.push(...providerResultItems);
|
|
363
393
|
|
|
364
394
|
// Built from the local matches, then placed above them: the AI turns the
|
|
365
395
|
// typed sentence into commands, so its answer leads the list. Its Thinking
|
|
@@ -14,6 +14,7 @@ import { normalizeCommandTickerSearchText } from "../ticker-search/results";
|
|
|
14
14
|
import { useTickerSearchRouteResults } from "../ticker-search/route";
|
|
15
15
|
import { buildRootResultModel, type RootResultModel } from "./results";
|
|
16
16
|
import { useRootProviderSearch } from "./provider-search";
|
|
17
|
+
import { isProviderResultItem } from "./search-providers";
|
|
17
18
|
import { buildRootShortcutFeedback } from "./shortcut-feedback";
|
|
18
19
|
import type { ShortcutIntent } from "./shortcuts";
|
|
19
20
|
import { clampIndex } from "../../../../utils/math";
|
|
@@ -66,6 +67,7 @@ interface UseCommandBarRootRuntimeOptions {
|
|
|
66
67
|
pluginCommandResultItems(command: CommandDef, shortcutArg: string): ResultItem[];
|
|
67
68
|
pluginInstallItem?: ResultItem | null;
|
|
68
69
|
providerResultItems?: ResultItem[];
|
|
70
|
+
providerMatchItems?: ResultItem[];
|
|
69
71
|
providerCategoryPriorities?: CommandBarCategoryPriorities;
|
|
70
72
|
providerSearching?: boolean;
|
|
71
73
|
readTickerSearchCache(
|
|
@@ -123,6 +125,7 @@ export function useCommandBarRootRuntime({
|
|
|
123
125
|
pluginCommandResultItems,
|
|
124
126
|
pluginInstallItem = null,
|
|
125
127
|
providerResultItems = [],
|
|
128
|
+
providerMatchItems = [],
|
|
126
129
|
providerCategoryPriorities,
|
|
127
130
|
providerSearching = false,
|
|
128
131
|
readTickerSearchCache,
|
|
@@ -202,6 +205,7 @@ export function useCommandBarRootRuntime({
|
|
|
202
205
|
rootQuery,
|
|
203
206
|
rootShortcutIntent,
|
|
204
207
|
providerResultItems,
|
|
208
|
+
providerMatchItems,
|
|
205
209
|
runDirectCommand,
|
|
206
210
|
runSecurityDescriptionShortcut,
|
|
207
211
|
state,
|
|
@@ -234,6 +238,7 @@ export function useCommandBarRootRuntime({
|
|
|
234
238
|
rootQuery,
|
|
235
239
|
rootShortcutIntent,
|
|
236
240
|
providerResultItems,
|
|
241
|
+
providerMatchItems,
|
|
237
242
|
runDirectCommand,
|
|
238
243
|
runSecurityDescriptionShortcut,
|
|
239
244
|
state,
|
|
@@ -261,10 +266,13 @@ export function useCommandBarRootRuntime({
|
|
|
261
266
|
const normalizedQuery = normalizeCommandTickerSearchText(symbolQuery);
|
|
262
267
|
// The install row for "TV" is labelled TV, but it leads on purpose and
|
|
263
268
|
// must not keep Grupo Televisa out of the list.
|
|
269
|
+
// A plugin's row never stands in for the symbol: a DM with @spy must not
|
|
270
|
+
// keep SPY out of the list.
|
|
264
271
|
const hasExactLocalRow = rootResultModel.items.some((item) => (
|
|
265
272
|
item !== pluginInstallItem
|
|
266
273
|
&& item.kind !== "ticker"
|
|
267
274
|
&& item.kind !== "search"
|
|
275
|
+
&& !isProviderResultItem(item)
|
|
268
276
|
&& normalizeCommandTickerSearchText(item.label) === normalizedQuery
|
|
269
277
|
));
|
|
270
278
|
return hasExactLocalRow ? null : symbolQuery;
|
|
@@ -9,6 +9,29 @@ import type { ResultItem } from "../../list/model";
|
|
|
9
9
|
|
|
10
10
|
const DEFAULT_MIN_QUERY_LENGTH = 3;
|
|
11
11
|
const DEFAULT_DEBOUNCE_MS = 300;
|
|
12
|
+
const PROVIDER_ROW_PREFIX = "search-provider:";
|
|
13
|
+
|
|
14
|
+
/** A row a plugin search provider contributed, as opposed to one the bar resolved itself. */
|
|
15
|
+
export function isProviderResultItem(item: Pick<ResultItem, "id">): boolean {
|
|
16
|
+
return item.id.startsWith(PROVIDER_ROW_PREFIX);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether a provider answers the text in the bar: free text, or text a code
|
|
21
|
+
* claimed that the provider asked to keep hearing.
|
|
22
|
+
*/
|
|
23
|
+
function answersQuery(provider: CommandBarSearchProvider, claimedShortcut: string | null): boolean {
|
|
24
|
+
if (!claimedShortcut) return true;
|
|
25
|
+
return provider.shortcuts?.some((code) => code.trim().toUpperCase() === claimedShortcut) ?? false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function meetsMinQueryLength(provider: CommandBarSearchProvider, trimmedQuery: string): boolean {
|
|
29
|
+
return trimmedQuery.length >= (provider.minQueryLength ?? DEFAULT_MIN_QUERY_LENGTH);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sortByPriority(providers: readonly CommandBarSearchProvider[]): CommandBarSearchProvider[] {
|
|
33
|
+
return [...providers].sort((left, right) => (left.priority ?? 0) - (right.priority ?? 0));
|
|
34
|
+
}
|
|
12
35
|
|
|
13
36
|
export function getAvailableCommandBarSearchProviders(
|
|
14
37
|
pluginRegistry: Pick<PluginRegistry, "commandBarSearchProviders" | "getCommandBarSearchProviderPluginId">,
|
|
@@ -31,15 +54,16 @@ export function toProviderResultItem(
|
|
|
31
54
|
onExecuted: () => void,
|
|
32
55
|
): ResultItem {
|
|
33
56
|
return {
|
|
34
|
-
id:
|
|
57
|
+
id: `${PROVIDER_ROW_PREFIX}${provider.id}:${result.id}`,
|
|
35
58
|
label: result.label,
|
|
36
59
|
detail: result.detail ?? "",
|
|
37
60
|
category: result.category ?? provider.category,
|
|
38
61
|
kind: "action",
|
|
39
62
|
lines: result.lines,
|
|
40
63
|
badge: result.badge,
|
|
64
|
+
name: result.name,
|
|
41
65
|
right: result.right,
|
|
42
|
-
searchText: [result.label, result.detail ?? "", ...(result.keywords ?? [])].join(" "),
|
|
66
|
+
searchText: [result.label, result.detail ?? "", result.name ?? "", ...(result.keywords ?? [])].join(" "),
|
|
43
67
|
disabled: result.disabled,
|
|
44
68
|
action: async () => {
|
|
45
69
|
if (result.disabled) return;
|
|
@@ -58,26 +82,73 @@ interface ProviderResults {
|
|
|
58
82
|
interface UseCommandBarSearchProvidersOptions {
|
|
59
83
|
providers: readonly CommandBarSearchProvider[];
|
|
60
84
|
query: string;
|
|
61
|
-
/** False while a route is open or
|
|
85
|
+
/** False while a route is open or the venue list owns the query. */
|
|
62
86
|
enabled: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The code that claimed the query (`CHAT`), upper case, or null for free
|
|
89
|
+
* text. Only providers that list it among their `shortcuts` still answer.
|
|
90
|
+
*/
|
|
91
|
+
claimedShortcut?: string | null;
|
|
63
92
|
context: CommandBarSearchContext;
|
|
64
93
|
onExecuted: () => void;
|
|
65
94
|
}
|
|
66
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Rows from providers that answer from memory (`match`), worked out as the bar
|
|
98
|
+
* renders so they land with the keystroke instead of a frame behind it. A
|
|
99
|
+
* provider that throws contributes nothing.
|
|
100
|
+
*/
|
|
101
|
+
function useProviderMatchItems({
|
|
102
|
+
providers,
|
|
103
|
+
query,
|
|
104
|
+
enabled,
|
|
105
|
+
claimedShortcut,
|
|
106
|
+
context,
|
|
107
|
+
onExecutedRef,
|
|
108
|
+
}: {
|
|
109
|
+
providers: readonly CommandBarSearchProvider[];
|
|
110
|
+
query: string;
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
claimedShortcut: string | null;
|
|
113
|
+
context: CommandBarSearchContext;
|
|
114
|
+
onExecutedRef: { current: () => void };
|
|
115
|
+
}): ResultItem[] {
|
|
116
|
+
return useMemo(() => {
|
|
117
|
+
if (!enabled) return [];
|
|
118
|
+
const trimmed = query.trim();
|
|
119
|
+
return sortByPriority(providers).flatMap((provider) => {
|
|
120
|
+
if (!provider.match || !answersQuery(provider, claimedShortcut) || !meetsMinQueryLength(provider, trimmed)) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
let results: CommandBarResultDef[];
|
|
124
|
+
try {
|
|
125
|
+
results = provider.match(trimmed, context);
|
|
126
|
+
} catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
return results.map((result) => toProviderResultItem(provider, result, () => onExecutedRef.current()));
|
|
130
|
+
});
|
|
131
|
+
}, [claimedShortcut, context, enabled, onExecutedRef, providers, query]);
|
|
132
|
+
}
|
|
133
|
+
|
|
67
134
|
/**
|
|
68
135
|
* Runs plugin search providers for the root list. Each provider debounces and
|
|
69
136
|
* aborts on its own, answers are memoized for the life of the bar, and rows are
|
|
70
137
|
* only ever added to the static list: a provider that fails, hangs, or answers
|
|
71
138
|
* late leaves what the command bar already resolved exactly as it was.
|
|
139
|
+
* Providers that answer from memory skip all of that and come back as
|
|
140
|
+
* `providerMatchItems`, for the bar to rank with its own matches.
|
|
72
141
|
*/
|
|
73
142
|
export function useCommandBarSearchProviders({
|
|
74
143
|
providers,
|
|
75
144
|
query,
|
|
76
145
|
enabled,
|
|
146
|
+
claimedShortcut = null,
|
|
77
147
|
context,
|
|
78
148
|
onExecuted,
|
|
79
149
|
}: UseCommandBarSearchProvidersOptions): {
|
|
80
150
|
providerResultItems: ResultItem[];
|
|
151
|
+
providerMatchItems: ResultItem[];
|
|
81
152
|
providerSearching: boolean;
|
|
82
153
|
} {
|
|
83
154
|
const [resultsByProvider, setResultsByProvider] = useState<Record<string, ProviderResults>>({});
|
|
@@ -136,8 +207,12 @@ export function useCommandBarSearchProviders({
|
|
|
136
207
|
}
|
|
137
208
|
|
|
138
209
|
for (const provider of providers) {
|
|
139
|
-
|
|
140
|
-
|
|
210
|
+
if (
|
|
211
|
+
!enabled
|
|
212
|
+
|| provider.match
|
|
213
|
+
|| !answersQuery(provider, claimedShortcut)
|
|
214
|
+
|| !meetsMinQueryLength(provider, trimmed)
|
|
215
|
+
) {
|
|
141
216
|
cancel(provider.id);
|
|
142
217
|
setLoading(provider.id, false);
|
|
143
218
|
continue;
|
|
@@ -179,7 +254,7 @@ export function useCommandBarSearchProviders({
|
|
|
179
254
|
})();
|
|
180
255
|
}, provider.debounceMs ?? DEFAULT_DEBOUNCE_MS));
|
|
181
256
|
}
|
|
182
|
-
}, [enabled, providers, query]);
|
|
257
|
+
}, [claimedShortcut, enabled, providers, query]);
|
|
183
258
|
|
|
184
259
|
useEffect(() => () => {
|
|
185
260
|
for (const timer of timersRef.current.values()) clearTimeout(timer);
|
|
@@ -191,15 +266,23 @@ export function useCommandBarSearchProviders({
|
|
|
191
266
|
const providerResultItems = useMemo(() => {
|
|
192
267
|
const trimmed = query.trim();
|
|
193
268
|
if (!enabled) return [];
|
|
194
|
-
return
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
269
|
+
return sortByPriority(providers).flatMap((provider) => {
|
|
270
|
+
if (provider.match || !answersQuery(provider, claimedShortcut)) return [];
|
|
271
|
+
const results = resultsByProvider[provider.id];
|
|
272
|
+
return results?.query === trimmed ? results.items : [];
|
|
273
|
+
});
|
|
274
|
+
}, [claimedShortcut, enabled, providers, query, resultsByProvider]);
|
|
275
|
+
|
|
276
|
+
const providerMatchItems = useProviderMatchItems({
|
|
277
|
+
providers,
|
|
278
|
+
query,
|
|
279
|
+
enabled,
|
|
280
|
+
claimedShortcut,
|
|
281
|
+
context,
|
|
282
|
+
onExecutedRef,
|
|
283
|
+
});
|
|
201
284
|
|
|
202
285
|
const providerSearching = enabled && providers.some((provider) => loadingProviderIds.includes(provider.id));
|
|
203
286
|
|
|
204
|
-
return { providerResultItems, providerSearching };
|
|
287
|
+
return { providerResultItems, providerMatchItems, providerSearching };
|
|
205
288
|
}
|
|
@@ -23,6 +23,7 @@ import { useAppStateRef } from "../../../state/app/context";
|
|
|
23
23
|
import { listingChoiceQuery } from "../../../tickers/search";
|
|
24
24
|
import { parseRootShortcutIntent } from "../routes/root/shortcuts";
|
|
25
25
|
import { useRootPluginInstallItem } from "../routes/root/plugin-install";
|
|
26
|
+
import { useRootPluginTurnOnItem } from "../routes/root/plugin-turn-on";
|
|
26
27
|
import { useCommandBarThemePreview } from "../theme-preview";
|
|
27
28
|
import { matchThemeOptions } from "../theme-picker";
|
|
28
29
|
import { CommandBarPanel } from "../panel";
|
|
@@ -243,6 +244,15 @@ export function CommandBar({
|
|
|
243
244
|
dispatch({ type: "SET_COMMAND_BAR", open: true, query, launch: { kind: "run-query", query } });
|
|
244
245
|
}, [dispatch]);
|
|
245
246
|
const closeBar = useCallback(() => closeAfterRun({ revertThemePreview: false }), [closeAfterRun]);
|
|
247
|
+
// A code whose plugin is switched off offers to turn it on. The install row
|
|
248
|
+
// never offers a code the app has, so the two never compete.
|
|
249
|
+
const pluginTurnOnItem = useRootPluginTurnOnItem({
|
|
250
|
+
enabled: !currentRoute && rootShortcutIntent.kind === "none",
|
|
251
|
+
query: rootQuery,
|
|
252
|
+
pluginRegistry,
|
|
253
|
+
disabledPlugins: state.config.disabledPlugins,
|
|
254
|
+
rerunQuery,
|
|
255
|
+
});
|
|
246
256
|
const pluginInstallItem = useRootPluginInstallItem({
|
|
247
257
|
enabled: !currentRoute && rootShortcutIntent.kind === "none",
|
|
248
258
|
query: rootQuery,
|
|
@@ -374,12 +384,15 @@ export function CommandBar({
|
|
|
374
384
|
const closeAfterProviderResult = useCallback(() => {
|
|
375
385
|
closeAfterRun({ revertThemePreview: false });
|
|
376
386
|
}, [closeAfterRun]);
|
|
377
|
-
const { providerResultItems, providerSearching } = useCommandBarSearchProviders({
|
|
387
|
+
const { providerResultItems, providerMatchItems, providerSearching } = useCommandBarSearchProviders({
|
|
378
388
|
providers: searchProviders,
|
|
379
389
|
query: rootQuery,
|
|
390
|
+
// A colon is the venue list.
|
|
391
|
+
enabled: !currentRoute && !listingChoice,
|
|
380
392
|
// A resolved prefix means the user is running a command, so free-text
|
|
381
|
-
// providers neither ask the network nor add rows
|
|
382
|
-
|
|
393
|
+
// providers neither ask the network nor add rows, unless they asked to
|
|
394
|
+
// answer after that code.
|
|
395
|
+
claimedShortcut: rootShortcutIntent.kind === "none" ? null : rootShortcutIntent.prefix,
|
|
383
396
|
context: searchProviderContext,
|
|
384
397
|
onExecuted: closeAfterProviderResult,
|
|
385
398
|
});
|
|
@@ -426,8 +439,9 @@ export function CommandBar({
|
|
|
426
439
|
paneShortcutItems,
|
|
427
440
|
pluginCommandItems,
|
|
428
441
|
pluginCommandResultItems,
|
|
429
|
-
pluginInstallItem,
|
|
442
|
+
pluginInstallItem: pluginTurnOnItem ?? pluginInstallItem,
|
|
430
443
|
providerResultItems,
|
|
444
|
+
providerMatchItems,
|
|
431
445
|
providerCategoryPriorities,
|
|
432
446
|
providerSearching,
|
|
433
447
|
readTickerSearchCache,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { t } from "../../i18n";
|
|
12
12
|
import { getThemeIds, isDarkTheme, themes as themeRegistry } from "../../theme/themes";
|
|
13
13
|
import { Box, Text, TextAttributes } from "../../ui";
|
|
14
|
-
import { truncateToDisplayWidth } from "../../utils/format";
|
|
14
|
+
import { displayWidth, truncateToDisplayWidth } from "../../utils/format";
|
|
15
15
|
import { ListView, type ListViewItem } from "../ui";
|
|
16
16
|
import type { ListRowState } from "../ui/list-view";
|
|
17
17
|
import type { ListJump } from "./list/model";
|
|
@@ -28,6 +28,8 @@ const THEME_PREVIEW_DEBOUNCE_MS = 120;
|
|
|
28
28
|
const DARK_THEME_GLYPH = "☾";
|
|
29
29
|
/** The glyph plus the space that keeps names on one left edge, dark or light. */
|
|
30
30
|
const GLYPH_GUTTER_WIDTH = 2;
|
|
31
|
+
/** Between a name and its config id. */
|
|
32
|
+
const ID_GAP = 2;
|
|
31
33
|
|
|
32
34
|
export interface ThemeOption {
|
|
33
35
|
id: string;
|
|
@@ -38,6 +40,32 @@ export interface ThemeOption {
|
|
|
38
40
|
const THEME_OPTIONS: ThemeOption[] = getThemeIds()
|
|
39
41
|
.map((id) => ({ id, name: themeRegistry[id]!.name, dark: isDarkTheme(id) }))
|
|
40
42
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
43
|
+
/** Ids line up in one column after the longest name. */
|
|
44
|
+
const LONGEST_THEME_NAME = Math.max(...THEME_OPTIONS.map((theme) => displayWidth(theme.name)));
|
|
45
|
+
const CURRENT_LABEL = "current";
|
|
46
|
+
|
|
47
|
+
interface ThemeRowLayout {
|
|
48
|
+
name: number;
|
|
49
|
+
/** Zero when the id has no room. */
|
|
50
|
+
id: number;
|
|
51
|
+
showCurrent: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A row's name, then the id `config set theme` and the docs use, in one
|
|
56
|
+
* column after the longest name. The id is copied, so it never shows cut:
|
|
57
|
+
* the current row gives up its "current" tag first (its name is bold), then
|
|
58
|
+
* the id goes, before any of a name does.
|
|
59
|
+
*/
|
|
60
|
+
function themeRowLayout(width: number, id: string, current: boolean): ThemeRowLayout {
|
|
61
|
+
const name = Math.min(LONGEST_THEME_NAME, width);
|
|
62
|
+
const idWidth = displayWidth(id);
|
|
63
|
+
const room = width - name - ID_GAP;
|
|
64
|
+
const currentWidth = displayWidth(CURRENT_LABEL) + 1;
|
|
65
|
+
if (current && room - currentWidth >= idWidth) return { name, id: idWidth, showCurrent: true };
|
|
66
|
+
if (room >= idWidth) return { name, id: idWidth, showCurrent: false };
|
|
67
|
+
return { name, id: 0, showCurrent: current && width - name >= currentWidth };
|
|
68
|
+
}
|
|
41
69
|
|
|
42
70
|
/**
|
|
43
71
|
* Shared with the panel layout, which sizes the sheet to whatever this returns
|
|
@@ -227,10 +255,12 @@ export const ThemePicker = memo(forwardRef<ThemePickerHandle, ThemePickerProps>(
|
|
|
227
255
|
onCommitRef.current(selected.id);
|
|
228
256
|
}, [cancelPreview]);
|
|
229
257
|
|
|
230
|
-
|
|
258
|
+
// The whole row past the glyph: the name, the id and, on the current row, its tag.
|
|
259
|
+
const rowWidth = Math.max(1, labelWidth - GLYPH_GUTTER_WIDTH + trailingWidth);
|
|
231
260
|
const renderRow = useCallback((item: ListViewItem, state: ListRowState) => {
|
|
232
|
-
const
|
|
233
|
-
const
|
|
261
|
+
const layout = themeRowLayout(rowWidth, item.id, item.current === true);
|
|
262
|
+
const label = truncateToDisplayWidth(item.label, layout.name);
|
|
263
|
+
const subtle = state.selected ? palette.selectedText : palette.subtle;
|
|
234
264
|
return (
|
|
235
265
|
<Box
|
|
236
266
|
flexDirection="row"
|
|
@@ -241,11 +271,11 @@ export const ThemePicker = memo(forwardRef<ThemePickerHandle, ThemePickerProps>(
|
|
|
241
271
|
style={nativePaneChrome ? { borderRadius: 6 } : undefined}
|
|
242
272
|
>
|
|
243
273
|
<Box width={GLYPH_GUTTER_WIDTH}>
|
|
244
|
-
<Text fg={
|
|
274
|
+
<Text fg={subtle}>
|
|
245
275
|
{isDarkTheme(item.id) ? DARK_THEME_GLYPH : ""}
|
|
246
276
|
</Text>
|
|
247
277
|
</Box>
|
|
248
|
-
<Box width={
|
|
278
|
+
<Box width={layout.name}>
|
|
249
279
|
<Text
|
|
250
280
|
fg={state.selected ? palette.selectedText : palette.text}
|
|
251
281
|
attributes={item.current ? TextAttributes.BOLD : undefined}
|
|
@@ -253,19 +283,24 @@ export const ThemePicker = memo(forwardRef<ThemePickerHandle, ThemePickerProps>(
|
|
|
253
283
|
{label}
|
|
254
284
|
</Text>
|
|
255
285
|
</Box>
|
|
256
|
-
|
|
257
|
-
<
|
|
258
|
-
{
|
|
259
|
-
</
|
|
260
|
-
|
|
286
|
+
{layout.id > 0 ? (
|
|
287
|
+
<Box width={ID_GAP + layout.id} paddingLeft={ID_GAP}>
|
|
288
|
+
<Text fg={subtle}>{item.id}</Text>
|
|
289
|
+
</Box>
|
|
290
|
+
) : null}
|
|
291
|
+
<Box flexGrow={1} />
|
|
292
|
+
{layout.showCurrent ? (
|
|
293
|
+
<Box width={displayWidth(CURRENT_LABEL) + 1} flexShrink={0}>
|
|
294
|
+
<Text fg={subtle}>{CURRENT_LABEL}</Text>
|
|
295
|
+
</Box>
|
|
296
|
+
) : null}
|
|
261
297
|
</Box>
|
|
262
298
|
);
|
|
263
299
|
}, [
|
|
264
300
|
contentPadding,
|
|
265
|
-
nameWidth,
|
|
266
301
|
nativePaneChrome,
|
|
267
302
|
palette,
|
|
268
|
-
|
|
303
|
+
rowWidth,
|
|
269
304
|
]);
|
|
270
305
|
|
|
271
306
|
return (
|