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,216 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { appendLiveQuotePoint } from "./chart-data";
|
|
3
|
+
import type { PricePoint, Quote } from "../types/financials";
|
|
4
|
+
|
|
5
|
+
function quoteFixture(overrides: Partial<Quote> = {}): Quote {
|
|
6
|
+
return {
|
|
7
|
+
symbol: "INTC",
|
|
8
|
+
price: 129,
|
|
9
|
+
currency: "USD",
|
|
10
|
+
change: 0,
|
|
11
|
+
changePercent: 0,
|
|
12
|
+
lastUpdated: Date.parse("2026-05-15T20:30:00Z"),
|
|
13
|
+
listingExchangeName: "NASDAQ",
|
|
14
|
+
marketState: "REGULAR",
|
|
15
|
+
...overrides,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("appendLiveQuotePoint", () => {
|
|
20
|
+
test("extends coarse chart histories with a fresh quote tail", () => {
|
|
21
|
+
const history: PricePoint[] = [
|
|
22
|
+
{ date: new Date("2026-05-04T00:00:00Z"), close: 56 },
|
|
23
|
+
{ date: new Date("2026-05-11T00:00:00Z"), close: 68 },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const extended = appendLiveQuotePoint(
|
|
27
|
+
history,
|
|
28
|
+
quoteFixture(),
|
|
29
|
+
{ now: Date.parse("2026-05-15T21:00:00Z") },
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(extended).toHaveLength(3);
|
|
33
|
+
expect(extended.at(-1)).toEqual({
|
|
34
|
+
date: new Date("2026-05-15T20:30:00Z"),
|
|
35
|
+
close: 129,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("merges a quote into the active OHLC bucket", () => {
|
|
40
|
+
const history: PricePoint[] = [
|
|
41
|
+
{
|
|
42
|
+
date: new Date("2026-05-15T20:25:00Z"),
|
|
43
|
+
open: 124,
|
|
44
|
+
high: 130,
|
|
45
|
+
low: 122,
|
|
46
|
+
close: 126,
|
|
47
|
+
volume: 1_000,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const extended = appendLiveQuotePoint(
|
|
52
|
+
history,
|
|
53
|
+
quoteFixture({ lastUpdated: Date.parse("2026-05-15T20:29:00Z") }),
|
|
54
|
+
{
|
|
55
|
+
now: Date.parse("2026-05-15T20:30:00Z"),
|
|
56
|
+
mode: "ohlc",
|
|
57
|
+
resolution: "5m",
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(extended).toHaveLength(1);
|
|
62
|
+
expect(extended[0]).toEqual({
|
|
63
|
+
date: new Date("2026-05-15T20:25:00Z"),
|
|
64
|
+
open: 124,
|
|
65
|
+
high: 130,
|
|
66
|
+
low: 122,
|
|
67
|
+
close: 129,
|
|
68
|
+
volume: 1_000,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("seeds a new OHLC bucket from the live price instead of prior-bar extremes", () => {
|
|
73
|
+
const history: PricePoint[] = [
|
|
74
|
+
{
|
|
75
|
+
date: new Date("2026-05-15T20:25:00Z"),
|
|
76
|
+
open: 124,
|
|
77
|
+
high: 180,
|
|
78
|
+
low: 80,
|
|
79
|
+
close: 126,
|
|
80
|
+
volume: 1_000,
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
const extended = appendLiveQuotePoint(
|
|
85
|
+
history,
|
|
86
|
+
quoteFixture({ lastUpdated: Date.parse("2026-05-15T20:30:00Z") }),
|
|
87
|
+
{
|
|
88
|
+
now: Date.parse("2026-05-15T20:31:00Z"),
|
|
89
|
+
mode: "ohlc",
|
|
90
|
+
resolution: "5m",
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
expect(extended).toHaveLength(2);
|
|
95
|
+
expect(extended[1]).toEqual({
|
|
96
|
+
date: new Date("2026-05-15T20:30:00Z"),
|
|
97
|
+
open: 129,
|
|
98
|
+
high: 129,
|
|
99
|
+
low: 129,
|
|
100
|
+
close: 129,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("treats calendar-month bars as variable-length buckets", () => {
|
|
105
|
+
const history: PricePoint[] = [{
|
|
106
|
+
date: new Date("2026-01-01T00:00:00Z"),
|
|
107
|
+
open: 120,
|
|
108
|
+
high: 140,
|
|
109
|
+
low: 110,
|
|
110
|
+
close: 125,
|
|
111
|
+
}];
|
|
112
|
+
|
|
113
|
+
const endOfJanuary = appendLiveQuotePoint(
|
|
114
|
+
history,
|
|
115
|
+
quoteFixture({ lastUpdated: Date.parse("2026-01-31T20:30:00Z") }),
|
|
116
|
+
{
|
|
117
|
+
now: Date.parse("2026-01-31T20:31:00Z"),
|
|
118
|
+
mode: "ohlc",
|
|
119
|
+
resolution: "1mo",
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
const startOfFebruary = appendLiveQuotePoint(
|
|
123
|
+
history,
|
|
124
|
+
quoteFixture({ lastUpdated: Date.parse("2026-02-01T20:30:00Z") }),
|
|
125
|
+
{
|
|
126
|
+
now: Date.parse("2026-02-01T20:31:00Z"),
|
|
127
|
+
mode: "ohlc",
|
|
128
|
+
resolution: "1mo",
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(endOfJanuary).toHaveLength(1);
|
|
133
|
+
expect(endOfJanuary[0]?.close).toBe(129);
|
|
134
|
+
expect(startOfFebruary).toHaveLength(2);
|
|
135
|
+
expect(startOfFebruary[1]).toMatchObject({
|
|
136
|
+
open: 129,
|
|
137
|
+
high: 129,
|
|
138
|
+
low: 129,
|
|
139
|
+
close: 129,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("uses the active extended-hours price for the live tail", () => {
|
|
144
|
+
const history: PricePoint[] = [
|
|
145
|
+
{ date: new Date("2026-05-15T19:30:00Z"), close: 128 },
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
const extended = appendLiveQuotePoint(
|
|
149
|
+
history,
|
|
150
|
+
quoteFixture({
|
|
151
|
+
marketState: "POST",
|
|
152
|
+
postMarketPrice: 131,
|
|
153
|
+
lastUpdated: Date.parse("2026-05-15T21:10:00Z"),
|
|
154
|
+
}),
|
|
155
|
+
{ now: Date.parse("2026-05-15T21:15:00Z") },
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
expect(extended.at(-1)?.close).toBe(131);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("does not bridge a missing intraday history window with one synthetic candle", () => {
|
|
162
|
+
const history: PricePoint[] = [
|
|
163
|
+
{ date: new Date("2026-07-22T14:49:00Z"), close: 347.73 },
|
|
164
|
+
{ date: new Date("2026-07-22T14:50:00Z"), close: 347.76 },
|
|
165
|
+
{ date: new Date("2026-07-22T14:51:00Z"), close: 347.68 },
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
const extended = appendLiveQuotePoint(
|
|
169
|
+
history,
|
|
170
|
+
quoteFixture({
|
|
171
|
+
symbol: "GOOG",
|
|
172
|
+
price: 346.27,
|
|
173
|
+
lastUpdated: Date.parse("2026-07-22T18:52:00Z"),
|
|
174
|
+
}),
|
|
175
|
+
Date.parse("2026-07-22T18:53:00Z"),
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
expect(extended).toBe(history);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("does not append a live quote tail with a likely unit mismatch", () => {
|
|
182
|
+
const history: PricePoint[] = [
|
|
183
|
+
{ date: new Date("2026-05-18T00:00:00Z"), close: 405 },
|
|
184
|
+
{ date: new Date("2026-05-22T00:00:00Z"), close: 379 },
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
const extended = appendLiveQuotePoint(
|
|
188
|
+
history,
|
|
189
|
+
quoteFixture({
|
|
190
|
+
symbol: "FTC",
|
|
191
|
+
currency: "GBP",
|
|
192
|
+
price: 3.79,
|
|
193
|
+
lastUpdated: Date.parse("2026-05-22T16:39:00Z"),
|
|
194
|
+
}),
|
|
195
|
+
{ now: Date.parse("2026-05-22T16:45:00Z") },
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
expect(extended).toBe(history);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test("does not append stale quotes from an older active session", () => {
|
|
202
|
+
const history: PricePoint[] = [
|
|
203
|
+
{ date: new Date("2026-05-11T00:00:00Z"), close: 68 },
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
const extended = appendLiveQuotePoint(
|
|
207
|
+
history,
|
|
208
|
+
quoteFixture({
|
|
209
|
+
lastUpdated: Date.parse("2026-05-08T20:00:00Z"),
|
|
210
|
+
}),
|
|
211
|
+
{ now: Date.parse("2026-05-15T15:00:00Z") },
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
expect(extended).toBe(history);
|
|
215
|
+
});
|
|
216
|
+
});
|
package/src/time-series/range.ts
CHANGED
|
@@ -7,3 +7,15 @@ export interface ChartDateWindow {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export const TIME_RANGES: TimeRange[] = ["1D", "1W", "1M", "3M", "6M", "1Y", "5Y", "ALL"];
|
|
10
|
+
export const CHART_RESOLUTIONS: ChartResolution[] = [
|
|
11
|
+
"auto",
|
|
12
|
+
"1m",
|
|
13
|
+
"5m",
|
|
14
|
+
"15m",
|
|
15
|
+
"30m",
|
|
16
|
+
"45m",
|
|
17
|
+
"1h",
|
|
18
|
+
"1d",
|
|
19
|
+
"1wk",
|
|
20
|
+
"1mo",
|
|
21
|
+
];
|
|
@@ -44,7 +44,7 @@ describe("chart-resolution", () => {
|
|
|
44
44
|
expect(sortChartResolutions(["1wk", "auto", "15m", "1d"])).toEqual(["auto", "15m", "1d", "1wk"]);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
test("picks
|
|
47
|
+
test("picks the supported resolution whose bar count sits nearest the target", () => {
|
|
48
48
|
const support = [
|
|
49
49
|
{ resolution: "1m", maxRange: "1D" },
|
|
50
50
|
{ resolution: "5m", maxRange: "1W" },
|
|
@@ -53,31 +53,30 @@ describe("chart-resolution", () => {
|
|
|
53
53
|
{ resolution: "1d", maxRange: "5Y" },
|
|
54
54
|
{ resolution: "1wk", maxRange: "ALL" },
|
|
55
55
|
] as const;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
expect(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
expect(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}, support, 100)).toBe("1m");
|
|
56
|
+
const pick = (start: string, end: string, current?: "5m" | "15m") => (
|
|
57
|
+
getBestSupportedResolutionForVisibleWindow(
|
|
58
|
+
{ start: new Date(start), end: new Date(end) },
|
|
59
|
+
support,
|
|
60
|
+
230,
|
|
61
|
+
current,
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(pick("2021-01-01T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("1wk");
|
|
66
|
+
expect(pick("2025-01-01T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("1d");
|
|
67
|
+
// Five months of daily bars beat 1h bars packed three to a pixel.
|
|
68
|
+
expect(pick("2025-08-01T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("1d");
|
|
69
|
+
expect(pick("2025-12-01T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("1h");
|
|
70
|
+
// Two weeks hold ten sessions: 15m bars, not the 780 5m bars of a
|
|
71
|
+
// calendar-day estimate.
|
|
72
|
+
expect(pick("2025-12-18T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("15m");
|
|
73
|
+
expect(pick("2025-12-29T00:00:00Z", "2026-01-01T00:00:00Z")).toBe("5m");
|
|
74
|
+
expect(pick("2026-01-01T00:00:00Z", "2026-01-02T00:00:00Z")).toBe("1m");
|
|
75
|
+
|
|
76
|
+
// A modest zoom keeps the resolution on screen; a large one still switches.
|
|
77
|
+
expect(pick("2025-12-26T09:36:00Z", "2026-01-01T00:00:00Z", "15m")).toBe("15m");
|
|
78
|
+
expect(pick("2025-12-29T00:00:00Z", "2026-01-01T00:00:00Z", "15m")).toBe("5m");
|
|
79
|
+
expect(pick("2025-12-15T00:00:00Z", "2026-01-01T00:00:00Z", "5m")).toBe("15m");
|
|
81
80
|
|
|
82
81
|
expect(CHART_RESOLUTION_STEP_MS["1h"]).toBe(60 * 60_000);
|
|
83
82
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChartResolution, TimeRange } from "./range";
|
|
2
|
-
import { TIME_RANGES } from "./range";
|
|
2
|
+
import { CHART_RESOLUTIONS, TIME_RANGES } from "./range";
|
|
3
3
|
import { isDateWindowWithinTimeRange } from "./date-window";
|
|
4
4
|
|
|
5
5
|
export type ManualChartResolution = Exclude<ChartResolution, "auto">;
|
|
@@ -9,20 +9,8 @@ export interface ChartResolutionSupport {
|
|
|
9
9
|
maxRange: TimeRange;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const TIME_RANGE_ORDER
|
|
13
|
-
|
|
14
|
-
const CHART_RESOLUTION_ORDER: ChartResolution[] = [
|
|
15
|
-
"auto",
|
|
16
|
-
"1m",
|
|
17
|
-
"5m",
|
|
18
|
-
"15m",
|
|
19
|
-
"30m",
|
|
20
|
-
"45m",
|
|
21
|
-
"1h",
|
|
22
|
-
"1d",
|
|
23
|
-
"1wk",
|
|
24
|
-
"1mo",
|
|
25
|
-
];
|
|
12
|
+
export const TIME_RANGE_ORDER = TIME_RANGES;
|
|
13
|
+
const CHART_RESOLUTION_ORDER = CHART_RESOLUTIONS;
|
|
26
14
|
|
|
27
15
|
const CHART_RESOLUTION_LABELS: Record<ChartResolution, string> = {
|
|
28
16
|
auto: "AUTO",
|
|
@@ -268,15 +256,42 @@ export function isRangePresetSupported(
|
|
|
268
256
|
return maxRange !== null && isTimeRangeAtOrBelow(range, maxRange);
|
|
269
257
|
}
|
|
270
258
|
|
|
259
|
+
const INTRADAY_TRADING_DAY_RATIO = 5 / 7;
|
|
260
|
+
/** Bars packed tighter than the target cost more than bars spread wider. */
|
|
261
|
+
const DENSE_SCORE_PENALTY = 1.5;
|
|
262
|
+
/** Score margin a candidate must win by before the active resolution changes. */
|
|
263
|
+
const RESOLUTION_SWITCH_HYSTERESIS = 0.35;
|
|
264
|
+
|
|
265
|
+
function estimateVisiblePointCount(resolution: ManualChartResolution, spanMs: number): number {
|
|
266
|
+
const calendarDays = Math.max(spanMs / CHART_RESOLUTION_STEP_MS["1d"], 1 / 24);
|
|
267
|
+
// Intraday bars only exist on trading days, so a multi-day window holds
|
|
268
|
+
// about five sessions a week. Anything up to a day is one session.
|
|
269
|
+
const days = isIntradayResolution(resolution) && calendarDays > 1
|
|
270
|
+
? Math.max(calendarDays * INTRADAY_TRADING_DAY_RATIO, 1)
|
|
271
|
+
: calendarDays;
|
|
272
|
+
return Math.max(days * CHART_RESOLUTION_POINTS_PER_DAY[resolution], 1);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function resolutionFitScore(estimatedPointCount: number, targetPointCount: number): number {
|
|
276
|
+
const ratio = estimatedPointCount / targetPointCount;
|
|
277
|
+
return ratio > 1 ? Math.log(ratio) * DENSE_SCORE_PENALTY : -Math.log(ratio);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Picks the supported resolution whose bar count sits closest to the target
|
|
282
|
+
* on a log scale, leaning toward fewer bars. A current resolution is kept
|
|
283
|
+
* until another candidate is clearly better, so a small zoom does not swap
|
|
284
|
+
* the whole data set.
|
|
285
|
+
*/
|
|
271
286
|
export function getBestSupportedResolutionForVisibleWindow(
|
|
272
287
|
window: { start: Date | null; end: Date | null } | null,
|
|
273
288
|
support: readonly ChartResolutionSupport[] | ReadonlyMap<ManualChartResolution, TimeRange>,
|
|
274
289
|
targetPointCount: number,
|
|
290
|
+
currentResolution?: ManualChartResolution | null,
|
|
275
291
|
): ManualChartResolution | null {
|
|
276
292
|
if (!window?.start || !window.end) return null;
|
|
277
293
|
|
|
278
294
|
const spanMs = Math.max(window.end.getTime() - window.start.getTime(), 0);
|
|
279
|
-
const dayCount = Math.max(spanMs / CHART_RESOLUTION_STEP_MS["1d"], 1 / 24);
|
|
280
295
|
const supportedResolutions = sortChartResolutions(
|
|
281
296
|
CHART_RESOLUTION_ORDER
|
|
282
297
|
.filter((resolution): resolution is ManualChartResolution => resolution !== "auto")
|
|
@@ -285,16 +300,20 @@ export function getBestSupportedResolutionForVisibleWindow(
|
|
|
285
300
|
return maxRange !== null && isDateWindowWithinTimeRange(window.start!, window.end!, maxRange);
|
|
286
301
|
}),
|
|
287
302
|
);
|
|
288
|
-
|
|
289
303
|
if (supportedResolutions.length === 0) return null;
|
|
290
304
|
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
const target = Math.max(targetPointCount, 1);
|
|
306
|
+
const scores = new Map(supportedResolutions.map((resolution) => [
|
|
307
|
+
resolution,
|
|
308
|
+
resolutionFitScore(estimateVisiblePointCount(resolution, spanMs), target),
|
|
309
|
+
] as const));
|
|
310
|
+
let best = supportedResolutions[0]!;
|
|
311
|
+
for (const resolution of supportedResolutions) {
|
|
312
|
+
if (scores.get(resolution)! <= scores.get(best)!) best = resolution;
|
|
297
313
|
}
|
|
298
|
-
|
|
299
|
-
|
|
314
|
+
if (currentResolution && scores.has(currentResolution)) {
|
|
315
|
+
const currentScore = scores.get(currentResolution)!;
|
|
316
|
+
if (currentScore <= scores.get(best)! + RESOLUTION_SWITCH_HYSTERESIS) return currentResolution;
|
|
317
|
+
}
|
|
318
|
+
return best;
|
|
300
319
|
}
|
|
@@ -98,6 +98,8 @@ export interface ChartResolveOptions {
|
|
|
98
98
|
requestViewport?: { start: Date; end: Date } | null;
|
|
99
99
|
/** Approximate number of horizontal observations the current surface can use. */
|
|
100
100
|
targetPointCount?: number;
|
|
101
|
+
/** Resolution currently on screen, kept through small Auto zooms. */
|
|
102
|
+
currentResolution?: ManualChartResolution | null;
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/** Raw source data retained while live quotes recompute the chart tail. */
|
|
@@ -290,6 +292,7 @@ function requestResolution(
|
|
|
290
292
|
{ start: new Date(runtimeBounds.start), end: new Date(runtimeBounds.end) },
|
|
291
293
|
sharedSupport,
|
|
292
294
|
options.targetPointCount ?? 120,
|
|
295
|
+
options.currentResolution,
|
|
293
296
|
)
|
|
294
297
|
: null;
|
|
295
298
|
const preferred = adaptive
|
|
@@ -388,6 +391,9 @@ export function seedChartResolutionResult(
|
|
|
388
391
|
loading: false,
|
|
389
392
|
errors: [],
|
|
390
393
|
warnings: [],
|
|
394
|
+
resolution: spec.viewport.resolution === "auto"
|
|
395
|
+
? getPresetResolution(spec.viewport.range)
|
|
396
|
+
: spec.viewport.resolution,
|
|
391
397
|
};
|
|
392
398
|
}
|
|
393
399
|
|
|
@@ -1224,5 +1230,6 @@ export async function resolveChartSpecData(
|
|
|
1224
1230
|
errors,
|
|
1225
1231
|
warnings: [...new Set([...priorityWarnings, ...warnings])],
|
|
1226
1232
|
viewport,
|
|
1233
|
+
resolution,
|
|
1227
1234
|
};
|
|
1228
1235
|
}
|
package/src/time-series/spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { CHART_RESOLUTIONS, TIME_RANGES, type ChartResolution, type TimeRange } from "./range";
|
|
2
2
|
import { getChartResolutionLabel } from "./resolution";
|
|
3
3
|
import {
|
|
4
4
|
canonicalTimeSeriesFieldId,
|
|
@@ -31,8 +31,8 @@ import {
|
|
|
31
31
|
isValidChartSeriesId,
|
|
32
32
|
} from "../capabilities/chart-series";
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
const RESOLUTIONS = new Set<ChartResolution>(
|
|
34
|
+
const RANGE_SET = new Set<TimeRange>(TIME_RANGES);
|
|
35
|
+
const RESOLUTIONS = new Set<ChartResolution>(CHART_RESOLUTIONS);
|
|
36
36
|
const PERIODS = new Set<SeriesPeriod>(["auto", "daily", "weekly", "monthly", "quarterly", "annual", "ttm"]);
|
|
37
37
|
const STYLES = new Set<SeriesStyle>(["line", "area", "step", "columns", "points", "candles", "ohlc", "hlc"]);
|
|
38
38
|
const ECONOMIC_STYLES = new Set<SeriesStyle>(["line", "area", "step", "columns", "points"]);
|
|
@@ -306,7 +306,7 @@ export function normalizeChartSpec(value: unknown, fallback: ChartSpec = DEFAULT
|
|
|
306
306
|
return {
|
|
307
307
|
version: CHART_SPEC_VERSION,
|
|
308
308
|
viewport: {
|
|
309
|
-
range:
|
|
309
|
+
range: RANGE_SET.has(viewport?.range as TimeRange)
|
|
310
310
|
? viewport!.range as TimeRange
|
|
311
311
|
: fallbackCopy.viewport.range,
|
|
312
312
|
resolution: RESOLUTIONS.has(viewport?.resolution as ChartResolution)
|
|
@@ -340,7 +340,7 @@ export function validateChartSpec(spec: ChartSpec): ChartSpecValidationResult {
|
|
|
340
340
|
if (spec.version !== CHART_SPEC_VERSION) {
|
|
341
341
|
errors.push(issue("version", "unsupported-version", `Unsupported chart spec version ${String(spec.version)}.`));
|
|
342
342
|
}
|
|
343
|
-
if (!
|
|
343
|
+
if (!RANGE_SET.has(spec.viewport.range)) errors.push(issue("viewport.range", "invalid-range", "Invalid date range."));
|
|
344
344
|
if (!RESOLUTIONS.has(spec.viewport.resolution)) {
|
|
345
345
|
errors.push(issue("viewport.resolution", "invalid-resolution", "Invalid chart resolution."));
|
|
346
346
|
}
|
package/src/time-series/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChartResolution, TimeRange } from "./range";
|
|
2
|
-
import type { ChartResolutionSupport } from "./resolution";
|
|
2
|
+
import type { ChartResolutionSupport, ManualChartResolution } from "./resolution";
|
|
3
3
|
import type { InstrumentRef } from "../market-data/request-types";
|
|
4
4
|
|
|
5
5
|
export const CHART_SPEC_VERSION = 2 as const;
|
|
@@ -175,4 +175,6 @@ export interface ChartResolutionResult {
|
|
|
175
175
|
warnings: string[];
|
|
176
176
|
/** Effective inclusive bounds used to clip the resolved chart data. */
|
|
177
177
|
viewport?: { start: Date; end: Date };
|
|
178
|
+
/** Bar resolution the loaded market history was fetched at. */
|
|
179
|
+
resolution?: ManualChartResolution;
|
|
178
180
|
}
|
|
@@ -35,6 +35,7 @@ export interface UseChartResolutionOptions {
|
|
|
35
35
|
autoViewport?: ChartResolveOptions["autoViewport"];
|
|
36
36
|
requestViewport?: ChartResolveOptions["requestViewport"];
|
|
37
37
|
targetPointCount?: number;
|
|
38
|
+
currentResolution?: ChartResolveOptions["currentResolution"];
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
const DEFAULT_QUOTE_POLL_INTERVAL_MS = 60_000;
|
|
@@ -146,10 +147,14 @@ export function useChartResolution(
|
|
|
146
147
|
? { start: new Date(requestViewportStart), end: new Date(requestViewportEnd) }
|
|
147
148
|
: null;
|
|
148
149
|
const adaptiveTargetPointCount = validAutoViewport ? options.targetPointCount : undefined;
|
|
150
|
+
// Read at resolve time only: hysteresis breaks ties when the viewport moves,
|
|
151
|
+
// and echoing the chosen resolution back must not trigger another resolve.
|
|
152
|
+
const currentResolution = validAutoViewport ? options.currentResolution ?? null : null;
|
|
149
153
|
const resolveOptions: ChartResolveOptions = {
|
|
150
154
|
autoViewport: validAutoViewport,
|
|
151
155
|
requestViewport: validRequestViewport,
|
|
152
156
|
targetPointCount: adaptiveTargetPointCount,
|
|
157
|
+
currentResolution,
|
|
153
158
|
};
|
|
154
159
|
const latestRequestRef = useRef({ spec, sources, options: resolveOptions });
|
|
155
160
|
latestRequestRef.current = { spec, sources, options: resolveOptions };
|
package/src/types/config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Portfolio, Watchlist } from "./ticker";
|
|
2
2
|
import type { LanguagePreference } from "../i18n/languages";
|
|
3
3
|
|
|
4
|
-
export const CURRENT_CONFIG_VERSION =
|
|
4
|
+
export const CURRENT_CONFIG_VERSION = 22;
|
|
5
5
|
|
|
6
6
|
type ChartRendererPreference = "auto" | "kitty" | "braille";
|
|
7
7
|
|
|
@@ -148,6 +148,13 @@ export interface AppConfig {
|
|
|
148
148
|
activeLayoutIndex: number;
|
|
149
149
|
brokerInstances: BrokerInstanceConfig[];
|
|
150
150
|
disabledPlugins: string[];
|
|
151
|
+
/**
|
|
152
|
+
* Plugins that used to ship inside Gloomberb and have since moved to their own
|
|
153
|
+
* repositories. Recorded once installed, so an upgrade restores them without
|
|
154
|
+
* re-installing on every launch, and so a user who removes one on purpose is
|
|
155
|
+
* not fought with.
|
|
156
|
+
*/
|
|
157
|
+
seededPlugins?: string[];
|
|
151
158
|
disabledSources: string[];
|
|
152
159
|
pluginConfig: Record<string, Record<string, unknown>>;
|
|
153
160
|
theme: string;
|
|
@@ -264,6 +271,71 @@ const DEFAULT_HOME_LAYOUT: LayoutConfig = {
|
|
|
264
271
|
detached: [],
|
|
265
272
|
};
|
|
266
273
|
|
|
274
|
+
/**
|
|
275
|
+
* One screen for "where are we": valuation and the economy in the wide slots,
|
|
276
|
+
* with the faster sentiment, volatility and credit reads beside them. These stay
|
|
277
|
+
* separate panes because each measures a different thing on a different horizon;
|
|
278
|
+
* the layout is what puts them on one screen.
|
|
279
|
+
*/
|
|
280
|
+
const DEFAULT_MACRO_LAYOUT: LayoutConfig = {
|
|
281
|
+
dockRoot: {
|
|
282
|
+
kind: "split",
|
|
283
|
+
axis: "vertical",
|
|
284
|
+
ratio: 0.54,
|
|
285
|
+
first: {
|
|
286
|
+
kind: "split",
|
|
287
|
+
axis: "horizontal",
|
|
288
|
+
ratio: 0.58,
|
|
289
|
+
first: { kind: "pane", instanceId: "market-valuation:macro" },
|
|
290
|
+
second: { kind: "pane", instanceId: "fear-greed:macro" },
|
|
291
|
+
},
|
|
292
|
+
second: {
|
|
293
|
+
kind: "split",
|
|
294
|
+
axis: "horizontal",
|
|
295
|
+
ratio: 0.58,
|
|
296
|
+
first: { kind: "pane", instanceId: "econ-statistics:macro" },
|
|
297
|
+
second: {
|
|
298
|
+
kind: "split",
|
|
299
|
+
axis: "vertical",
|
|
300
|
+
ratio: 0.5,
|
|
301
|
+
first: { kind: "pane", instanceId: "volatility-term-structure:macro" },
|
|
302
|
+
second: { kind: "pane", instanceId: "credit-conditions:macro" },
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
instances: [
|
|
307
|
+
{
|
|
308
|
+
instanceId: "market-valuation:macro",
|
|
309
|
+
paneId: "market-valuation",
|
|
310
|
+
binding: { kind: "none" },
|
|
311
|
+
settings: { indicator: "buffett", range: "25Y" },
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
instanceId: "econ-statistics:macro",
|
|
315
|
+
paneId: "econ-statistics",
|
|
316
|
+
binding: { kind: "none" },
|
|
317
|
+
settings: { stat: "cpi-yoy", range: "20Y" },
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
instanceId: "fear-greed:macro",
|
|
321
|
+
paneId: "fear-greed",
|
|
322
|
+
binding: { kind: "none" },
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
instanceId: "volatility-term-structure:macro",
|
|
326
|
+
paneId: "volatility-term-structure",
|
|
327
|
+
binding: { kind: "none" },
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
instanceId: "credit-conditions:macro",
|
|
331
|
+
paneId: "credit-conditions",
|
|
332
|
+
binding: { kind: "none" },
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
floating: [],
|
|
336
|
+
detached: [],
|
|
337
|
+
};
|
|
338
|
+
|
|
267
339
|
const DEFAULT_MONITOR_LAYOUT: LayoutConfig = {
|
|
268
340
|
dockRoot: {
|
|
269
341
|
kind: "split",
|
|
@@ -385,6 +457,14 @@ function getDockedPaneIdsFromNode(node: DockLayoutNode | null, result: string[]
|
|
|
385
457
|
return result;
|
|
386
458
|
}
|
|
387
459
|
|
|
460
|
+
export function getPlacedPaneInstanceIds(layout: LayoutConfig): string[] {
|
|
461
|
+
return [...new Set([
|
|
462
|
+
...getDockedPaneIdsFromNode(layout.dockRoot),
|
|
463
|
+
...layout.floating.map((entry) => entry.instanceId),
|
|
464
|
+
...(layout.detached ?? []).map((entry) => entry.instanceId),
|
|
465
|
+
])];
|
|
466
|
+
}
|
|
467
|
+
|
|
388
468
|
export function createPaneInstanceId(paneId: string): string {
|
|
389
469
|
nextPaneInstanceSeq += 1;
|
|
390
470
|
return `${paneId}:${Date.now().toString(36)}${nextPaneInstanceSeq.toString(36)}`;
|
|
@@ -488,8 +568,24 @@ export function removePaneInstances(layout: LayoutConfig, instanceIds: Iterable<
|
|
|
488
568
|
const removedIds = new Set(instanceIds);
|
|
489
569
|
if (removedIds.size === 0) return layout;
|
|
490
570
|
|
|
491
|
-
const
|
|
492
|
-
const validInstanceIds = new Set(
|
|
571
|
+
const retainedInstances = layout.instances.filter((instance) => !removedIds.has(instance.instanceId));
|
|
572
|
+
const validInstanceIds = new Set(retainedInstances.map((instance) => instance.instanceId));
|
|
573
|
+
const instances = retainedInstances
|
|
574
|
+
.map((instance) => {
|
|
575
|
+
const memory = clonePlacementMemory(instance.placementMemory);
|
|
576
|
+
if (!memory?.docked?.anchorInstanceId || validInstanceIds.has(memory.docked.anchorInstanceId)) {
|
|
577
|
+
return instance;
|
|
578
|
+
}
|
|
579
|
+
const docked = {
|
|
580
|
+
...memory.docked,
|
|
581
|
+
anchorInstanceId: undefined,
|
|
582
|
+
};
|
|
583
|
+
const nextDocked = docked.path || docked.position ? docked : undefined;
|
|
584
|
+
const placementMemory = nextDocked || memory.floating || memory.detached
|
|
585
|
+
? { ...memory, docked: nextDocked }
|
|
586
|
+
: undefined;
|
|
587
|
+
return { ...instance, placementMemory };
|
|
588
|
+
});
|
|
493
589
|
const dockRoot = normalizeDockNode(layout.dockRoot, validInstanceIds, new Set<string>());
|
|
494
590
|
const dockedPaneIds = new Set(getDockedPaneIdsFromNode(dockRoot));
|
|
495
591
|
const detached = layout.detached ?? [];
|
|
@@ -502,6 +598,28 @@ export function removePaneInstances(layout: LayoutConfig, instanceIds: Iterable<
|
|
|
502
598
|
};
|
|
503
599
|
}
|
|
504
600
|
|
|
601
|
+
export function removeUnreachablePaneInstances(layout: LayoutConfig): LayoutConfig {
|
|
602
|
+
const instancesById = new Map(layout.instances.map((instance) => [instance.instanceId, instance] as const));
|
|
603
|
+
const reachableIds = new Set(getPlacedPaneInstanceIds(layout));
|
|
604
|
+
const pendingIds = [...reachableIds];
|
|
605
|
+
|
|
606
|
+
for (let index = 0; index < pendingIds.length; index += 1) {
|
|
607
|
+
const instance = instancesById.get(pendingIds[index]!);
|
|
608
|
+
if (instance?.binding?.kind !== "follow") continue;
|
|
609
|
+
const sourceId = instance.binding.sourceInstanceId;
|
|
610
|
+
if (!instancesById.has(sourceId) || reachableIds.has(sourceId)) continue;
|
|
611
|
+
reachableIds.add(sourceId);
|
|
612
|
+
pendingIds.push(sourceId);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return removePaneInstances(
|
|
616
|
+
layout,
|
|
617
|
+
layout.instances
|
|
618
|
+
.filter((instance) => !reachableIds.has(instance.instanceId))
|
|
619
|
+
.map((instance) => instance.instanceId),
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
505
623
|
export function normalizePaneLayout(
|
|
506
624
|
layout: LayoutConfig,
|
|
507
625
|
options?: {
|
|
@@ -653,10 +771,12 @@ export function createDefaultConfig(dataDir: string): AppConfig {
|
|
|
653
771
|
layouts: [
|
|
654
772
|
{ name: "Home", layout: cloneLayout(layout), paneState: {} },
|
|
655
773
|
{ name: "Monitor", layout: cloneLayout(DEFAULT_MONITOR_LAYOUT), paneState: {} },
|
|
774
|
+
{ name: "Macro", layout: cloneLayout(DEFAULT_MACRO_LAYOUT), paneState: {} },
|
|
656
775
|
],
|
|
657
776
|
activeLayoutIndex: 0,
|
|
658
777
|
brokerInstances: [],
|
|
659
778
|
disabledPlugins: [],
|
|
779
|
+
seededPlugins: [],
|
|
660
780
|
disabledSources: [],
|
|
661
781
|
pluginConfig: {},
|
|
662
782
|
theme: "amber",
|