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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { priceColor } from "../../theme/colors";
|
|
3
|
+
import { useThemeColors } from "../../theme/theme-context";
|
|
4
|
+
import { useAppActive } from "../../state/app/activity";
|
|
5
|
+
import { useAppSelector } from "../../state/app/context";
|
|
6
|
+
import { selectBaseCurrency } from "../../state/selectors-ui";
|
|
7
|
+
import { getSharedMarketDataCoordinator } from "../../market-data/coordinator";
|
|
8
|
+
import { t } from "../../i18n";
|
|
9
|
+
import { useQuoteEntry, useResolvedEntryValue } from "../../market-data/hooks";
|
|
10
|
+
import { formatPercentRaw } from "../../utils/format";
|
|
11
|
+
import { formatMarketPrice } from "../../market-data/market/format";
|
|
12
|
+
import { getActiveQuoteDisplay, marketStateColor, marketStateCountdown, marketStateLabel } from "../../market-data/market/status";
|
|
13
|
+
|
|
14
|
+
const SPY_REFRESH_MS = 5 * 60_000; // 5 min
|
|
15
|
+
|
|
16
|
+
export interface MarketSummary {
|
|
17
|
+
baseCurrency: string;
|
|
18
|
+
marketColor: string;
|
|
19
|
+
/** Market state with its countdown, when the state has one. */
|
|
20
|
+
marketLabel: string;
|
|
21
|
+
/** Market state alone, for a header too narrow for the countdown. */
|
|
22
|
+
marketLabelShort: string;
|
|
23
|
+
spyColor: string;
|
|
24
|
+
spyText: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface MarketSummaryFit {
|
|
28
|
+
showBaseCurrency: boolean;
|
|
29
|
+
showCountdown: boolean;
|
|
30
|
+
showState: boolean;
|
|
31
|
+
showSpy: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Picks which parts of the cluster survive at a given width, ordered by how
|
|
36
|
+
* much each can still change: SPY first, then the market-state label, then the
|
|
37
|
+
* base currency, then the countdown suffix that widens the label. A narrowing
|
|
38
|
+
* header therefore sheds the countdown, then the currency, then the state, and
|
|
39
|
+
* keeps SPY longest. `countdownWidth` is what the suffix adds to the label.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveMarketSummaryFit(options: {
|
|
42
|
+
available: number;
|
|
43
|
+
baseCurrencyWidth: number;
|
|
44
|
+
countdownWidth: number;
|
|
45
|
+
spyWidth: number;
|
|
46
|
+
stateWidth: number;
|
|
47
|
+
}): MarketSummaryFit {
|
|
48
|
+
let remaining = options.available;
|
|
49
|
+
const take = (width: number): boolean => {
|
|
50
|
+
if (width <= 0 || width > remaining) return false;
|
|
51
|
+
remaining -= width;
|
|
52
|
+
return true;
|
|
53
|
+
};
|
|
54
|
+
const showSpy = take(options.spyWidth);
|
|
55
|
+
const showState = take(options.stateWidth);
|
|
56
|
+
const showBaseCurrency = take(options.baseCurrencyWidth);
|
|
57
|
+
const showCountdown = showState && take(options.countdownWidth);
|
|
58
|
+
return { showBaseCurrency, showCountdown, showState, showSpy };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function useMarketSummary(): MarketSummary {
|
|
62
|
+
const colors = useThemeColors();
|
|
63
|
+
const appActive = useAppActive();
|
|
64
|
+
const baseCurrency = useAppSelector(selectBaseCurrency);
|
|
65
|
+
const spyQuoteEntry = useQuoteEntry("SPY", null);
|
|
66
|
+
const spyQuote = useResolvedEntryValue(spyQuoteEntry);
|
|
67
|
+
const mktState = spyQuote?.marketState;
|
|
68
|
+
const [now, setNow] = useState(Date.now());
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!appActive || (mktState !== "PRE" && mktState !== "REGULAR")) return;
|
|
72
|
+
setNow(Date.now());
|
|
73
|
+
const id = setInterval(() => setNow(Date.now()), 1_000);
|
|
74
|
+
return () => clearInterval(id);
|
|
75
|
+
}, [appActive, mktState]);
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (!appActive) return;
|
|
79
|
+
const coordinator = getSharedMarketDataCoordinator();
|
|
80
|
+
if (!coordinator) return;
|
|
81
|
+
const fetchSpy = async () => {
|
|
82
|
+
await coordinator.loadQuote({ symbol: "SPY" }).catch(() => {});
|
|
83
|
+
};
|
|
84
|
+
fetchSpy();
|
|
85
|
+
const id = setInterval(fetchSpy, SPY_REFRESH_MS);
|
|
86
|
+
return () => { clearInterval(id); };
|
|
87
|
+
}, [appActive]);
|
|
88
|
+
|
|
89
|
+
const activeSpyQuote = getActiveQuoteDisplay(spyQuote);
|
|
90
|
+
const spyColor = activeSpyQuote ? priceColor(activeSpyQuote.change, colors) : colors.textDim;
|
|
91
|
+
const spyText = activeSpyQuote
|
|
92
|
+
? `SPY ${formatMarketPrice(activeSpyQuote.price, { assetCategory: "ETF" })} ${formatPercentRaw(activeSpyQuote.changePercent)}`
|
|
93
|
+
: "SPY —";
|
|
94
|
+
|
|
95
|
+
const mktCountdown = mktState ? marketStateCountdown(mktState, now) : null;
|
|
96
|
+
const marketLabelShort = mktState ? t(marketStateLabel(mktState)) : "";
|
|
97
|
+
const marketLabel = marketLabelShort && mktCountdown
|
|
98
|
+
? `${marketLabelShort} · ${mktCountdown}`
|
|
99
|
+
: marketLabelShort;
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
baseCurrency,
|
|
103
|
+
marketColor: mktState ? marketStateColor(mktState, colors) : colors.textDim,
|
|
104
|
+
marketLabel,
|
|
105
|
+
marketLabelShort,
|
|
106
|
+
spyColor,
|
|
107
|
+
spyText,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -1,8 +1,103 @@
|
|
|
1
|
-
import { TITLEBAR_OVERLAY_HEIGHT_PX } from "../titlebar-overlay";
|
|
1
|
+
import { TITLEBAR_OVERLAY_HEIGHT_PX, getTitlebarLeadingInset } from "../titlebar-overlay";
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_HEADER_HEIGHT = 1;
|
|
4
4
|
|
|
5
|
+
const HEADER_PROMPT_MIN_WIDTH = 10;
|
|
6
|
+
/** Columns the header keeps free right of the prompt for the update status. */
|
|
7
|
+
const HEADER_PROMPT_UPDATE_COLUMNS = 14;
|
|
8
|
+
/**
|
|
9
|
+
* Width the prompt holds before the market cluster is offered anything. Above
|
|
10
|
+
* the command surface minimum so a mid-size window does not hand the cluster a
|
|
11
|
+
* whole tier and leave the sheet sitting on its floor.
|
|
12
|
+
*/
|
|
13
|
+
const HEADER_PROMPT_COMFORT_WIDTH = 48;
|
|
14
|
+
/** Narrowest command surface, by host: a document snippet still reads here. */
|
|
15
|
+
const COMMAND_SURFACE_MIN_WIDTH = { native: 46, terminal: 42 };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The market cluster's reserve at the header's right edge, widest first. Each
|
|
19
|
+
* step is the worst case for what it shows, so a ticking countdown or a longer
|
|
20
|
+
* state label can never push the cluster past its columns:
|
|
21
|
+
*
|
|
22
|
+
* 42 PRE-MKT · 5h 30m SPY 1,234.56 -10.60% USD
|
|
23
|
+
* 31 the state label and SPY
|
|
24
|
+
* 21 SPY alone
|
|
25
|
+
*
|
|
26
|
+
* Steps rather than a share of the window: a reserve of, say, 18 columns is
|
|
27
|
+
* too narrow for anything and would waste all 18. There is deliberately no
|
|
28
|
+
* step for "everything but the countdown", which would cost the sheet eleven
|
|
29
|
+
* columns to add the base currency, the one value here that barely moves.
|
|
30
|
+
*/
|
|
31
|
+
const HEADER_MARKET_TIERS = [42, 31, 21] as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Update status is transient, so on a narrow header it gives most of its
|
|
35
|
+
* reserve back rather than shortening the placeholder that has to sell the
|
|
36
|
+
* command bar to a first-time user.
|
|
37
|
+
*/
|
|
38
|
+
function headerPromptUpdateColumns(termWidth: number): number {
|
|
39
|
+
return Math.min(HEADER_PROMPT_UPDATE_COLUMNS, Math.max(4, Math.floor(termWidth * 0.12)));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Columns the market cluster gets, from the terminal width alone: a reserve
|
|
44
|
+
* that tracked the quote would resize the prompt every time SPY ticked.
|
|
45
|
+
*/
|
|
46
|
+
function headerMarketColumns(termWidth: number, left: number, updateColumns: number): number {
|
|
47
|
+
const spare = termWidth - left - updateColumns - HEADER_PROMPT_COMFORT_WIDTH;
|
|
48
|
+
return HEADER_MARKET_TIERS.find((tier) => tier <= spare) ?? 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
5
51
|
export function resolveAppHeaderHeightCells(options: { titleBarOverlay?: boolean; cellHeightPx?: number }): number {
|
|
6
52
|
if (!options.titleBarOverlay || !options.cellHeightPx || options.cellHeightPx <= 0) return DEFAULT_HEADER_HEIGHT;
|
|
7
53
|
return TITLEBAR_OVERLAY_HEIGHT_PX / options.cellHeightPx;
|
|
8
54
|
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Width shared by the header prompt and the command sheet that drops out of
|
|
58
|
+
* it, so the sheet reads as the prompt expanding downward. A fraction of the
|
|
59
|
+
* window so the update status and the Help pill keep their place, capped where
|
|
60
|
+
* a document snippet still has room but a label does not run past where the
|
|
61
|
+
* eye goes.
|
|
62
|
+
*/
|
|
63
|
+
export function resolveCommandSurfaceWidth(options: { termWidth: number; nativePaneChrome?: boolean }): number {
|
|
64
|
+
const { termWidth } = options;
|
|
65
|
+
return options.nativePaneChrome
|
|
66
|
+
? Math.max(COMMAND_SURFACE_MIN_WIDTH.native, Math.min(104, termWidth - 10, Math.floor(termWidth * 0.64)))
|
|
67
|
+
: Math.max(COMMAND_SURFACE_MIN_WIDTH.terminal, Math.min(96, termWidth - 8, Math.floor(termWidth * 0.68)));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface HeaderPromptGeometry {
|
|
71
|
+
/** Column the prompt starts at. */
|
|
72
|
+
left: number;
|
|
73
|
+
width: number;
|
|
74
|
+
/** Columns held at the header's right edge for the market cluster. */
|
|
75
|
+
marketColumns: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Geometry of the always-visible command prompt in the header. While the
|
|
80
|
+
* command bar is open the same prompt hosts its input, so the geometry never
|
|
81
|
+
* changes underneath the user.
|
|
82
|
+
*/
|
|
83
|
+
export function resolveHeaderPromptGeometry(options: {
|
|
84
|
+
termWidth: number;
|
|
85
|
+
nativePaneChrome?: boolean;
|
|
86
|
+
nativeWindowChrome?: boolean;
|
|
87
|
+
titleBarOverlay?: boolean;
|
|
88
|
+
}): HeaderPromptGeometry {
|
|
89
|
+
const { nativePaneChrome, termWidth, titleBarOverlay } = options;
|
|
90
|
+
const nativeWindowChrome = options.nativeWindowChrome ?? titleBarOverlay;
|
|
91
|
+
const leadingInset = titleBarOverlay && nativeWindowChrome ? getTitlebarLeadingInset() : 0;
|
|
92
|
+
const left = leadingInset + 1;
|
|
93
|
+
const updateColumns = headerPromptUpdateColumns(termWidth);
|
|
94
|
+
const marketColumns = headerMarketColumns(termWidth, left, updateColumns);
|
|
95
|
+
const width = Math.max(
|
|
96
|
+
HEADER_PROMPT_MIN_WIDTH,
|
|
97
|
+
Math.min(
|
|
98
|
+
resolveCommandSurfaceWidth({ nativePaneChrome, termWidth }),
|
|
99
|
+
termWidth - left - updateColumns - marketColumns,
|
|
100
|
+
),
|
|
101
|
+
);
|
|
102
|
+
return { left, width, marketColumns };
|
|
103
|
+
}
|
|
@@ -30,9 +30,10 @@ import {
|
|
|
30
30
|
selectStatusBarVisible,
|
|
31
31
|
} from "../../../state/selectors-ui";
|
|
32
32
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
33
|
+
import { tf } from "../../../i18n";
|
|
33
34
|
import { getPaneDisplayTitle } from "../pane/title";
|
|
34
35
|
import type { PaneHeaderQuickSetting } from "../pane/header";
|
|
35
|
-
import { getShortcutDisplayMode } from "../../../utils/shortcut-labels";
|
|
36
|
+
import { formatCommandBarShortcut, getShortcutDisplayMode } from "../../../utils/shortcut-labels";
|
|
36
37
|
import {
|
|
37
38
|
actionMenuWidth,
|
|
38
39
|
menuForPane,
|
|
@@ -257,10 +258,13 @@ export function Shell({
|
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
const {
|
|
261
|
+
canExportPaneCsv,
|
|
260
262
|
closeAllFloatingPanes,
|
|
261
263
|
closeFocusedPane,
|
|
262
264
|
copyFocusedPaneScreenshot,
|
|
263
265
|
copyPaneScreenshot,
|
|
266
|
+
exportFocusedPaneCsv,
|
|
267
|
+
exportPaneCsv,
|
|
264
268
|
gridlockVisiblePanes,
|
|
265
269
|
handleFloatingClose,
|
|
266
270
|
openFocusedPaneSettings,
|
|
@@ -474,6 +478,7 @@ export function Shell({
|
|
|
474
478
|
closeAllFloatingPanes,
|
|
475
479
|
closeFocusedPane,
|
|
476
480
|
copyFocusedPaneScreenshot,
|
|
481
|
+
exportFocusedPaneCsv,
|
|
477
482
|
focusedPaneId,
|
|
478
483
|
gridlockVisiblePanes,
|
|
479
484
|
hasActiveDrag,
|
|
@@ -526,6 +531,7 @@ export function Shell({
|
|
|
526
531
|
state: titleState,
|
|
527
532
|
persistLayout,
|
|
528
533
|
}),
|
|
534
|
+
canExportPaneCsv(paneId) ? exportPaneCsv : undefined,
|
|
529
535
|
);
|
|
530
536
|
void showContextMenu(context, items, event).then((shown) => {
|
|
531
537
|
if (shown) return;
|
|
@@ -549,7 +555,7 @@ export function Shell({
|
|
|
549
555
|
items: fallbackItems,
|
|
550
556
|
});
|
|
551
557
|
});
|
|
552
|
-
}, [contentHeight, copyPaneScreenshot, desktopWindowBridge, focusPane, getPaneTitle, nativePaneChrome, openPaneSettings, paneMap, paneState, persistLayout, pluginRegistry, publicSharing, rendererHost.copyPngImage, sharePane, shortcutDisplayMode, showContextMenu, titleState, visibleLayout, width]);
|
|
558
|
+
}, [canExportPaneCsv, contentHeight, copyPaneScreenshot, desktopWindowBridge, exportPaneCsv, focusPane, getPaneTitle, nativePaneChrome, openPaneSettings, paneMap, paneState, persistLayout, pluginRegistry, publicSharing, rendererHost.copyPngImage, sharePane, shortcutDisplayMode, showContextMenu, titleState, visibleLayout, width]);
|
|
553
559
|
|
|
554
560
|
const {
|
|
555
561
|
handleFloatingCloseMouseDown,
|
|
@@ -632,7 +638,9 @@ export function Shell({
|
|
|
632
638
|
<Box flexDirection="column" alignItems="center">
|
|
633
639
|
<AsciiText text="Gloomberb" font="wordmark" color={colors.textMuted} />
|
|
634
640
|
<Box height={1} />
|
|
635
|
-
<Text fg={colors.textDim}>
|
|
641
|
+
<Text fg={colors.textDim}>
|
|
642
|
+
{tf("{shortcut} to get started.", { shortcut: formatCommandBarShortcut(shortcutDisplayMode) })}
|
|
643
|
+
</Text>
|
|
636
644
|
</Box>
|
|
637
645
|
</Box>
|
|
638
646
|
|
|
@@ -34,6 +34,7 @@ export function menuForPane(
|
|
|
34
34
|
copyPaneScreenshot?: (paneId: string) => void | Promise<void>,
|
|
35
35
|
sharePane?: () => void | Promise<void>,
|
|
36
36
|
linkItems: ContextMenuItem[] = [],
|
|
37
|
+
exportPaneCsv?: (paneId: string) => void | Promise<void>,
|
|
37
38
|
): ContextMenuItem[] {
|
|
38
39
|
const baseActions: ContextMenuItem[] = [];
|
|
39
40
|
if (pluginRegistry.hasPaneSettings(pane.instance.instanceId)) {
|
|
@@ -60,6 +61,14 @@ export function menuForPane(
|
|
|
60
61
|
onSelect: () => copyPaneScreenshot(pane.instance.instanceId),
|
|
61
62
|
});
|
|
62
63
|
}
|
|
64
|
+
if (exportPaneCsv) {
|
|
65
|
+
baseActions.push({
|
|
66
|
+
id: "export-csv",
|
|
67
|
+
label: "Export CSV",
|
|
68
|
+
accelerator: PANE_MANAGEMENT_ACCELERATORS.exportCsv,
|
|
69
|
+
onSelect: () => exportPaneCsv(pane.instance.instanceId),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
63
72
|
|
|
64
73
|
if (pane.floating) {
|
|
65
74
|
baseActions.push({
|
|
@@ -13,6 +13,10 @@ import type { PluginRegistry } from "../../../../plugins/registry";
|
|
|
13
13
|
import type { LayoutConfig } from "../../../../types/config";
|
|
14
14
|
import type { RendererHost } from "../../../../ui";
|
|
15
15
|
import { capturePaneScreenshotPngBase64 } from "../../../../utils/dom-screenshot";
|
|
16
|
+
import {
|
|
17
|
+
exportPaneTableCsv,
|
|
18
|
+
hasPaneTableExporter,
|
|
19
|
+
} from "../../../../state/pane-table-export-registry";
|
|
16
20
|
|
|
17
21
|
function removedFocusRestoreOptions(
|
|
18
22
|
layout: LayoutConfig,
|
|
@@ -75,6 +79,28 @@ export function useShellPaneActions({
|
|
|
75
79
|
}
|
|
76
80
|
}, [closePaneMenu, pluginRegistry, rendererHost]);
|
|
77
81
|
|
|
82
|
+
const canExportPaneCsv = useCallback((paneId: string) => {
|
|
83
|
+
const pane = paneMap.get(paneId);
|
|
84
|
+
return pane?.def.tableExport === true && hasPaneTableExporter(paneId);
|
|
85
|
+
}, [paneMap]);
|
|
86
|
+
|
|
87
|
+
const exportPaneCsv = useCallback(async (paneId: string) => {
|
|
88
|
+
closePaneMenu();
|
|
89
|
+
const pane = paneMap.get(paneId);
|
|
90
|
+
if (!pane) return;
|
|
91
|
+
await exportPaneTableCsv(
|
|
92
|
+
paneId,
|
|
93
|
+
pane.instance.title ?? pane.def.name,
|
|
94
|
+
pluginRegistry.notify,
|
|
95
|
+
);
|
|
96
|
+
}, [closePaneMenu, paneMap, pluginRegistry]);
|
|
97
|
+
|
|
98
|
+
const exportFocusedPaneCsv = useCallback(() => {
|
|
99
|
+
if (!focusedPaneId || !canExportPaneCsv(focusedPaneId)) return false;
|
|
100
|
+
void exportPaneCsv(focusedPaneId);
|
|
101
|
+
return true;
|
|
102
|
+
}, [canExportPaneCsv, exportPaneCsv, focusedPaneId]);
|
|
103
|
+
|
|
78
104
|
const closeFocusedPane = useCallback(() => {
|
|
79
105
|
if (!focusedPaneId || !isPaneInLayout(visibleLayout, focusedPaneId)) return false;
|
|
80
106
|
const nextLayout = removePane(visibleLayout, focusedPaneId);
|
|
@@ -132,10 +158,13 @@ export function useShellPaneActions({
|
|
|
132
158
|
}, [focusedPaneId, persistLayout, previousFocusedPaneId, visibleLayout]);
|
|
133
159
|
|
|
134
160
|
return {
|
|
161
|
+
canExportPaneCsv,
|
|
135
162
|
closeAllFloatingPanes,
|
|
136
163
|
closeFocusedPane,
|
|
137
164
|
copyFocusedPaneScreenshot,
|
|
138
165
|
copyPaneScreenshot,
|
|
166
|
+
exportFocusedPaneCsv,
|
|
167
|
+
exportPaneCsv,
|
|
139
168
|
gridlockVisiblePanes,
|
|
140
169
|
handleFloatingClose,
|
|
141
170
|
openFocusedPaneSettings,
|
|
@@ -16,6 +16,7 @@ interface ShellPaneManagementShortcutOptions {
|
|
|
16
16
|
closeAllFloatingPanes(): boolean;
|
|
17
17
|
closeFocusedPane(): boolean;
|
|
18
18
|
copyFocusedPaneScreenshot(): boolean;
|
|
19
|
+
exportFocusedPaneCsv(): boolean;
|
|
19
20
|
focusedPaneId: string | null;
|
|
20
21
|
gridlockVisiblePanes(): boolean;
|
|
21
22
|
hasActiveDrag(): boolean;
|
|
@@ -35,6 +36,7 @@ export function useShellPaneManagementShortcuts({
|
|
|
35
36
|
closeAllFloatingPanes,
|
|
36
37
|
closeFocusedPane,
|
|
37
38
|
copyFocusedPaneScreenshot,
|
|
39
|
+
exportFocusedPaneCsv,
|
|
38
40
|
focusedPaneId,
|
|
39
41
|
gridlockVisiblePanes,
|
|
40
42
|
hasActiveDrag,
|
|
@@ -121,6 +123,9 @@ export function useShellPaneManagementShortcuts({
|
|
|
121
123
|
case "copy-screenshot":
|
|
122
124
|
handled = copyFocusedPaneScreenshot();
|
|
123
125
|
break;
|
|
126
|
+
case "export-csv":
|
|
127
|
+
handled = exportFocusedPaneCsv();
|
|
128
|
+
break;
|
|
124
129
|
case "share":
|
|
125
130
|
handled = shareFocusedPane();
|
|
126
131
|
break;
|
|
@@ -6,6 +6,7 @@ export const PANE_MANAGEMENT_ACCELERATORS = {
|
|
|
6
6
|
toggleFloating: "CmdOrCtrl+Shift+D",
|
|
7
7
|
popOut: "CmdOrCtrl+Shift+O",
|
|
8
8
|
copyScreenshot: "CmdOrCtrl+Shift+C",
|
|
9
|
+
exportCsv: "CmdOrCtrl+Shift+E",
|
|
9
10
|
share: "CmdOrCtrl+Shift+S",
|
|
10
11
|
close: "CmdOrCtrl+W",
|
|
11
12
|
closeAllFloating: "CmdOrCtrl+Alt+W",
|
|
@@ -21,6 +22,7 @@ export type PaneManagementShortcut =
|
|
|
21
22
|
| "toggle-floating"
|
|
22
23
|
| "pop-out"
|
|
23
24
|
| "copy-screenshot"
|
|
25
|
+
| "export-csv"
|
|
24
26
|
| "share"
|
|
25
27
|
| "close"
|
|
26
28
|
| "close-all-floating"
|
|
@@ -41,6 +43,7 @@ export function resolvePaneManagementShortcut(
|
|
|
41
43
|
if (!shifted && name === ",") return "settings";
|
|
42
44
|
if (!shifted || event.alt) return null;
|
|
43
45
|
if (name === "c") return "copy-screenshot";
|
|
46
|
+
if (name === "e") return "export-csv";
|
|
44
47
|
if (name === "s") return "share";
|
|
45
48
|
if (name === "d") return "toggle-floating";
|
|
46
49
|
if (name === "f") return "toggle-fullscreen";
|
|
@@ -4,6 +4,7 @@ import { AppContext, createInitialState } from "../../state/app/context";
|
|
|
4
4
|
import { cloneLayout, createDefaultConfig, createPaneInstance, type LayoutConfig } from "../../types/config";
|
|
5
5
|
import type { AppNotificationRequest } from "../../types/plugin";
|
|
6
6
|
import { StatusBar } from "./status-bar";
|
|
7
|
+
import { VERSION } from "../../version";
|
|
7
8
|
import { getDockedPaneIds } from "../../plugins/pane-manager";
|
|
8
9
|
import { setSharedRegistryForTests } from "../../plugins/registry";
|
|
9
10
|
import { act, useEffect, useState } from "react";
|
|
@@ -51,18 +52,18 @@ describe("StatusBar", () => {
|
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
test("opens the
|
|
55
|
+
test("opens the current version changelog from the version chip", async () => {
|
|
55
56
|
const config = createDefaultConfig("/tmp/gloomberb-test");
|
|
56
57
|
config.layouts = [{ name: "Home", layout: cloneLayout(config.layout) }];
|
|
57
58
|
const state = {
|
|
58
59
|
...createInitialState(config),
|
|
59
60
|
statusBarVisible: true,
|
|
60
61
|
};
|
|
61
|
-
|
|
62
|
+
let openedVersion = "";
|
|
62
63
|
|
|
63
64
|
testSetup = await testRender(
|
|
64
|
-
<AppContext value={{ state, dispatch: (
|
|
65
|
-
<StatusBar />
|
|
65
|
+
<AppContext value={{ state, dispatch: () => {} }}>
|
|
66
|
+
<StatusBar onOpenChangelog={(version) => { openedVersion = version; }} />
|
|
66
67
|
</AppContext>,
|
|
67
68
|
{ width: 120, height: 1 },
|
|
68
69
|
);
|
|
@@ -70,13 +71,13 @@ describe("StatusBar", () => {
|
|
|
70
71
|
await testSetup.renderOnce();
|
|
71
72
|
|
|
72
73
|
const frame = testSetup.captureCharFrame();
|
|
73
|
-
const
|
|
74
|
-
expect(
|
|
74
|
+
const versionX = frame.split("\n")[0]?.indexOf(`v${VERSION}`) ?? -1;
|
|
75
|
+
expect(versionX).toBeGreaterThanOrEqual(0);
|
|
75
76
|
|
|
76
|
-
await testSetup.mockMouse.click(
|
|
77
|
+
await testSetup.mockMouse.click(versionX + 1, 0);
|
|
77
78
|
await testSetup.renderOnce();
|
|
78
79
|
|
|
79
|
-
expect(
|
|
80
|
+
expect(openedVersion).toBe(VERSION);
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
test("shows a transient focus layout tab without replacing saved layouts", async () => {
|