gloomberb 0.16.1 → 0.16.3
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 +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +26 -8
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +2 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +37 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +2 -0
- package/src/brokers/account-cache.ts +69 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +37 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +560 -136
- package/src/cli/commands/overview.ts +136 -48
- package/src/cli/commands/ticker.ts +220 -67
- package/src/cli/desktop-pane-shot.ts +37 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +27 -6
- package/src/cli/helpers.ts +4 -8
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index.ts +23 -8
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/options.ts +5 -1
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/capabilities.ts +5 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +87 -16
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +31 -22
- package/src/cli/pane-functions/headless.ts +201 -41
- package/src/cli/pane-functions/index.ts +24 -6
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +63 -9
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +11 -3
- package/src/cli/registry.ts +6 -3
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +53 -29
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/export.ts +6 -51
- package/src/components/data-table/view.tsx +32 -11
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +11 -11
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +12 -7
- package/src/components/layout/shell/drag/live.ts +122 -0
- package/src/components/layout/shell/drag/overlays.tsx +179 -35
- package/src/components/layout/shell/drag/runtime.ts +62 -50
- package/src/components/layout/shell/drag/slide.ts +10 -0
- package/src/components/layout/shell/index.tsx +37 -51
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
- package/src/components/layout/shell/native/surfaces.ts +30 -14
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +419 -168
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/metric-treemap/heat-surface.tsx +43 -16
- package/src/components/metric-treemap/heat-tiles.ts +18 -0
- package/src/components/metric-treemap/layout.ts +2 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/range-track.tsx +10 -3
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +7 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/data/config/store/normalize.ts +17 -1
- package/src/data/json-persistence.ts +17 -3
- package/src/data/json-storage.ts +2 -0
- package/src/data/memory-resource-store.ts +46 -0
- package/src/i18n/es.ts +19 -1
- package/src/i18n/ja.ts +19 -1
- package/src/i18n/ko.ts +19 -1
- package/src/i18n/zh-cn.ts +19 -1
- package/src/i18n/zh-tw.ts +19 -1
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +123 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +2 -0
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-client.ts +191 -66
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
- package/src/plugins/builtin/analytics/risk-model.ts +45 -17
- package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
- package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +2 -2
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +2 -2
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +161 -6
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +42 -16
- package/src/plugins/builtin/holders/report-header.ts +136 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
- package/src/plugins/builtin/market-movers/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +20 -3
- package/src/plugins/builtin/members/headless.ts +5 -3
- package/src/plugins/builtin/members/model.ts +10 -2
- package/src/plugins/builtin/members/pane.tsx +23 -6
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +48 -3
- package/src/plugins/builtin/pe-band/headless.ts +25 -7
- package/src/plugins/builtin/pe-band/model.ts +92 -16
- package/src/plugins/builtin/pe-band/pane.tsx +33 -16
- package/src/plugins/builtin/perps/client.ts +50 -3
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +249 -48
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/members-menu.tsx +260 -0
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/themes/pane.tsx +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +69 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
- package/src/plugins/builtin/world-venue-map/model.ts +23 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/loader.ts +13 -1
- package/src/plugins/registry/pane-settings.ts +1 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/data-table/row.tsx +2 -0
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +113 -17
- package/src/renderers/dom/host/drag-shield.ts +24 -0
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/live-frame.ts +54 -0
- package/src/renderers/dom/host/mouse.ts +8 -1
- package/src/renderers/dom/host/scroll-box.tsx +6 -5
- package/src/renderers/dom/host/tabs.tsx +3 -2
- package/src/renderers/dom/styles.css +16 -9
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -1
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
- package/src/renderers/electrobun/view/host/native.ts +0 -10
- package/src/renderers/electrobun/view/host/window-move.ts +28 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financial-routes.ts +2 -2
- package/src/sources/provider-router/financials.ts +76 -12
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/provider-router/primary.ts +2 -2
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/margin-account.ts +108 -0
- package/src/theme/heat-colors.ts +266 -84
- package/src/time-series/resolution.ts +15 -0
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +35 -3
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +20 -1
- package/src/types/ticker.ts +15 -0
- package/src/ui/host.tsx +26 -0
- package/src/ui/index.tsx +8 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/updater/index.ts +9 -11
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +19 -0
- package/src/utils/depositary-receipt.ts +70 -0
- package/src/utils/display-number.ts +63 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/fundamentals.ts +17 -1
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history-integrity.ts +19 -6
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { SecFilingItem } from "../types/data-provider";
|
|
2
|
+
import { ProviderMissError } from "./provider-errors";
|
|
3
|
+
|
|
4
|
+
/** Legal forms and grouping words, which say nothing about which company a name is. */
|
|
5
|
+
const COMPANY_NAME_FILLER = new Set([
|
|
6
|
+
"THE", "SA", "PLC", "LTD", "LIMITED", "CORP", "CORPORATION", "INC", "INCORPORATED", "NV", "AG", "SE",
|
|
7
|
+
"HOLDING", "HOLDINGS", "GROUP", "COMPANY", "CO",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The first word of a company name that tells it apart, in capitals without
|
|
12
|
+
* accents: "BANCO" for "Banco Santander, S.A.", "BP" for "BP p.l.c.". Null
|
|
13
|
+
* when the name is only legal forms.
|
|
14
|
+
*/
|
|
15
|
+
function companyNameToken(name: string | null | undefined): string | null {
|
|
16
|
+
const words = (name ?? "")
|
|
17
|
+
.normalize("NFKD")
|
|
18
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
19
|
+
.toUpperCase()
|
|
20
|
+
// An initialism (S.A., N.V., p.l.c.) is one word; any other dot separates two (Amazon.com).
|
|
21
|
+
.replace(/\b(?:[A-Z]\.){2,}/g, (initialism) => initialism.replaceAll(".", ""))
|
|
22
|
+
.replace(/['\u2019]/g, "")
|
|
23
|
+
.split(/[^A-Z0-9]+/);
|
|
24
|
+
return words.find((word) => word && !COMPANY_NAME_FILLER.has(word)) ?? null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether two names are clearly different companies. Names that cannot be
|
|
29
|
+
* compared count as the same, so only a plain conflict hides anything.
|
|
30
|
+
*/
|
|
31
|
+
export function areDifferentCompanies(left: string | null | undefined, right: string | null | undefined): boolean {
|
|
32
|
+
const leftToken = companyNameToken(left);
|
|
33
|
+
const rightToken = companyNameToken(right);
|
|
34
|
+
return !!leftToken && !!rightToken && leftToken !== rightToken;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface SecListing {
|
|
38
|
+
/** The bare symbol, such as SAN. */
|
|
39
|
+
symbol: string;
|
|
40
|
+
/** The listing's canonical venue, such as EPA. */
|
|
41
|
+
exchange: string;
|
|
42
|
+
/** The listing's company, from its own quote. */
|
|
43
|
+
name: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** "No SEC filings found for Sanofi (EPA). The SEC lists SAN as Banco Santander, S.A. (NYSE)." */
|
|
47
|
+
export function secRegistrantMismatchMessage(listing: SecListing, registrantName: string, registrantExchange?: string | null): string {
|
|
48
|
+
const registrant = registrantExchange ? `${registrantName} (${registrantExchange})` : registrantName;
|
|
49
|
+
return `No SEC filings found for ${listing.name} (${listing.exchange}). The SEC lists ${listing.symbol} as ${registrant}${registrant.endsWith(".") ? "" : "."}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The SEC knows the listing's symbol as another company: SAN on EPA is Sanofi, SAN at the SEC is Banco Santander. */
|
|
53
|
+
export class SecRegistrantMismatchError extends ProviderMissError {
|
|
54
|
+
constructor(readonly listing: SecListing, readonly registrantName: string) {
|
|
55
|
+
super(secRegistrantMismatchMessage(listing, registrantName));
|
|
56
|
+
this.name = "SecRegistrantMismatchError";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The company the filings were filed by. */
|
|
61
|
+
function registrantName(filings: readonly SecFilingItem[]): string | null {
|
|
62
|
+
return filings.map((filing) => filing.companyName?.trim()).find((name): name is string => !!name) ?? null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* A lookup for a listing outside the US can answer with the US registrant of
|
|
67
|
+
* the same symbol: a backend that predates venue-aware lookups ignores the
|
|
68
|
+
* venue. Those filings are another company's, so they are refused.
|
|
69
|
+
*/
|
|
70
|
+
export function assertSecRegistrantMatches(filings: readonly SecFilingItem[], listing: SecListing): void {
|
|
71
|
+
const registrant = registrantName(filings);
|
|
72
|
+
if (registrant && areDifferentCompanies(listing.name, registrant)) {
|
|
73
|
+
throw new SecRegistrantMismatchError(listing, registrant);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
import type { AppAction, AppState } from "../../../core/state/app/state";
|
|
45
45
|
import { scheduleConfigSave } from "../../config-save-scheduler";
|
|
46
46
|
import { LOW_PRIORITY_CONFIG_SAVE_DEBOUNCE_MS } from "../../persist-scheduler";
|
|
47
|
+
import { fireAndForget } from "../../../utils/fire-and-forget";
|
|
47
48
|
|
|
48
49
|
export {
|
|
49
50
|
appReducer,
|
|
@@ -565,10 +566,16 @@ export function AppProvider({
|
|
|
565
566
|
if (signature === lastMainSyncRef.current) return;
|
|
566
567
|
lastMainSyncRef.current = signature;
|
|
567
568
|
latestMainStateRevisionRef.current += 1;
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
569
|
+
// A snapshot that did not arrive must not count as sent. Forget it, unless
|
|
570
|
+
// a newer one has replaced it, so the next effect run sends it again. The
|
|
571
|
+
// two syncs below dedupe the same way.
|
|
572
|
+
fireAndForget(
|
|
573
|
+
desktopBridge.syncMainState({ ...snapshot, mainStateRevision: latestMainStateRevisionRef.current }),
|
|
574
|
+
"desktop.syncMainState",
|
|
575
|
+
() => {
|
|
576
|
+
if (lastMainSyncRef.current === signature) lastMainSyncRef.current = null;
|
|
577
|
+
},
|
|
578
|
+
);
|
|
572
579
|
}, [
|
|
573
580
|
buildDesktopSnapshot,
|
|
574
581
|
desktopBridge,
|
|
@@ -581,9 +588,12 @@ export function AppProvider({
|
|
|
581
588
|
|
|
582
589
|
useEffect(() => {
|
|
583
590
|
if (desktopBridge?.kind !== "main" || !desktopBridge.syncThemePreview) return;
|
|
584
|
-
|
|
585
|
-
lastThemePreviewSyncRef.current
|
|
586
|
-
|
|
591
|
+
const theme = state.themePreview;
|
|
592
|
+
if (lastThemePreviewSyncRef.current === theme) return;
|
|
593
|
+
lastThemePreviewSyncRef.current = theme;
|
|
594
|
+
fireAndForget(desktopBridge.syncThemePreview({ theme }), "desktop.setThemePreview", () => {
|
|
595
|
+
if (lastThemePreviewSyncRef.current === theme) lastThemePreviewSyncRef.current = undefined;
|
|
596
|
+
});
|
|
587
597
|
}, [desktopBridge, state.themePreview]);
|
|
588
598
|
|
|
589
599
|
useEffect(() => {
|
|
@@ -598,7 +608,13 @@ export function AppProvider({
|
|
|
598
608
|
const paneSignature = serializePaneState(state.paneState[desktopBridge.paneId]);
|
|
599
609
|
if (paneSignature === lastDetachedPaneSyncRef.current) return;
|
|
600
610
|
lastDetachedPaneSyncRef.current = paneSignature;
|
|
601
|
-
|
|
611
|
+
fireAndForget(
|
|
612
|
+
desktopBridge.replaceDetachedPaneState(desktopBridge.paneId, state.paneState[desktopBridge.paneId] ?? {}),
|
|
613
|
+
"desktop.replaceDetachedPaneState",
|
|
614
|
+
() => {
|
|
615
|
+
if (lastDetachedPaneSyncRef.current === paneSignature) lastDetachedPaneSyncRef.current = null;
|
|
616
|
+
},
|
|
617
|
+
);
|
|
602
618
|
}, [desktopBridge, serializePaneState, state.paneState]);
|
|
603
619
|
|
|
604
620
|
useLayoutEffect(() => {
|
|
@@ -106,21 +106,28 @@ export function useQuoteStreaming(
|
|
|
106
106
|
const paneInView = usePaneInView();
|
|
107
107
|
const coordinator = getSharedMarketDataCoordinator();
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.sort()
|
|
122
|
-
.
|
|
123
|
-
|
|
109
|
+
// Keyed on the array, not its contents: callers memoize their targets, and a
|
|
110
|
+
// portfolio re-renders on every data frame, where re-keying and sorting a
|
|
111
|
+
// thousand targets cost a few milliseconds each time.
|
|
112
|
+
const { coordinatorTargets, identityKey, subscriptionKey } = useMemo(() => {
|
|
113
|
+
const normalizedEntries = new Map<string, QuoteSubscriptionTarget>();
|
|
114
|
+
for (const target of targets) {
|
|
115
|
+
const resolved = normalizeQuoteStreamSubscriptionTarget(target);
|
|
116
|
+
if (!resolved) continue;
|
|
117
|
+
const normalized = paneInView ? resolved : downgradeOffscreenQuoteTarget(resolved);
|
|
118
|
+
const key = buildQuoteStreamSubscriptionKey(normalized);
|
|
119
|
+
normalizedEntries.set(key, normalized);
|
|
120
|
+
}
|
|
121
|
+
const sortedEntries = [...normalizedEntries.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
122
|
+
const normalizedTargets = sortedEntries.map(([, target]) => target);
|
|
123
|
+
return {
|
|
124
|
+
coordinatorTargets: toCoordinatorQuoteTargets(normalizedTargets),
|
|
125
|
+
identityKey: [...new Set(normalizedTargets.map(buildQuoteStreamSubscriptionIdentityKey))]
|
|
126
|
+
.sort()
|
|
127
|
+
.join("\u001f"),
|
|
128
|
+
subscriptionKey: sortedEntries.map(([key]) => key).join("|"),
|
|
129
|
+
};
|
|
130
|
+
}, [paneInView, targets]);
|
|
124
131
|
const latestSubscriptionRef = useRef({
|
|
125
132
|
identityKey,
|
|
126
133
|
subscriptionKey,
|
|
@@ -208,11 +215,16 @@ export function useQuoteUpdates(
|
|
|
208
215
|
): void {
|
|
209
216
|
const appActive = useAppVisible();
|
|
210
217
|
const coordinator = getSharedMarketDataCoordinator();
|
|
211
|
-
const normalizedTargets =
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
const { instrumentKey, normalizedTargets } = useMemo(() => {
|
|
219
|
+
const normalized = normalizeQuoteStreamSubscriptionTargets(targets);
|
|
220
|
+
return {
|
|
221
|
+
instrumentKey: normalized
|
|
222
|
+
.map((target) => buildQuoteKey(instrumentFromQuoteTarget(target)))
|
|
223
|
+
.sort()
|
|
224
|
+
.join("\u001f"),
|
|
225
|
+
normalizedTargets: normalized,
|
|
226
|
+
};
|
|
227
|
+
}, [targets]);
|
|
216
228
|
const instruments = useMemo(() => uniqueQuoteInstruments(normalizedTargets), [instrumentKey]);
|
|
217
229
|
|
|
218
230
|
useQuoteStreaming(targets, { enabled: liveStreaming });
|
|
@@ -270,12 +282,15 @@ export function useLiveQuoteEntries(
|
|
|
270
282
|
subscriptionStartedAt: number;
|
|
271
283
|
} {
|
|
272
284
|
const appActive = useAppVisible();
|
|
273
|
-
const normalizedTargets =
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
285
|
+
const { normalizedTargets, targetKey } = useMemo(() => {
|
|
286
|
+
const normalized = normalizeQuoteStreamSubscriptionTargets(targets);
|
|
287
|
+
return {
|
|
288
|
+
normalizedTargets: normalized,
|
|
289
|
+
targetKey: [...new Set(normalized.map((target) => buildQuoteStreamSubscriptionIdentityKey(target)))]
|
|
290
|
+
.sort()
|
|
291
|
+
.join("\u001f"),
|
|
292
|
+
};
|
|
293
|
+
}, [targets]);
|
|
279
294
|
const liveStreaming = options.liveStreaming !== false;
|
|
280
295
|
const freshnessKey = options.freshnessScopeKey ?? targetKey;
|
|
281
296
|
const subscriptionKey = `${appActive ? "active" : "inactive"}\u001f${liveStreaming ? "live" : "poll"}\u001f${freshnessKey}`;
|
|
@@ -5,9 +5,12 @@ import { useAppSelector, useOptionalPaneInstanceId } from "./app/context";
|
|
|
5
5
|
|
|
6
6
|
type ScrollDirection = "up" | "down";
|
|
7
7
|
|
|
8
|
+
/** A scroll position: rows (or cells), or device pixels where the host measures in them. */
|
|
9
|
+
type ScrollTarget = { cells: number } | { pixels: number };
|
|
10
|
+
|
|
8
11
|
interface PaneScrollAction {
|
|
9
12
|
direction: ScrollDirection;
|
|
10
|
-
resolveTarget(scrollBox: ScrollBoxRenderable):
|
|
13
|
+
resolveTarget(scrollBox: ScrollBoxRenderable): ScrollTarget | null;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
interface PaneScrollEntry {
|
|
@@ -57,17 +60,58 @@ function isVisibleScrollBox(scrollBox: ScrollBoxRenderable): boolean {
|
|
|
57
60
|
return !hasHiddenAncestor(scrollBox) && !hasCollapsedBounds(scrollBox);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
function
|
|
63
|
+
function maxScrollTop(scrollBox: ScrollBoxRenderable): number {
|
|
61
64
|
const viewportHeight = Math.max(0, scrollBox.viewport?.height ?? 0);
|
|
62
|
-
if (viewportHeight <= 0) return
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
if (viewportHeight <= 0) return 0;
|
|
66
|
+
return Math.max(0, scrollBox.scrollHeight - viewportHeight);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The desktop host rounds its viewport and content to whole rows, which can
|
|
71
|
+
* leave up to half a row of content past the last scrollable row. Where it
|
|
72
|
+
* also reports pixels, the ends are measured in them.
|
|
73
|
+
*/
|
|
74
|
+
function pixelRange(scrollBox: ScrollBoxRenderable): { top: number; max: number } | null {
|
|
75
|
+
const { scrollTopPx, scrollHeightPx, viewportPx } = scrollBox;
|
|
76
|
+
if (!scrollBox.scrollToPixels || typeof scrollTopPx !== "number" || typeof scrollHeightPx !== "number" || !viewportPx) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return { top: scrollTopPx, max: Math.max(0, scrollHeightPx - viewportPx.height) };
|
|
66
80
|
}
|
|
67
81
|
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
function topTarget(scrollBox: ScrollBoxRenderable): ScrollTarget | null {
|
|
83
|
+
if ((scrollBox.viewport?.height ?? 0) <= 0) return null;
|
|
84
|
+
const pixels = pixelRange(scrollBox);
|
|
85
|
+
if (pixels) return pixels.top >= 1 ? { pixels: 0 } : null;
|
|
86
|
+
return scrollBox.scrollTop > 0 ? { cells: 0 } : null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function bottomTarget(scrollBox: ScrollBoxRenderable): ScrollTarget | null {
|
|
90
|
+
const max = maxScrollTop(scrollBox);
|
|
91
|
+
// A body that overflows by less than a row is not worth capturing the keys for.
|
|
92
|
+
if (max <= 0) return null;
|
|
93
|
+
const pixels = pixelRange(scrollBox);
|
|
94
|
+
if (pixels) return pixels.max - pixels.top >= 1 ? { pixels: pixels.max } : null;
|
|
95
|
+
return max !== scrollBox.scrollTop ? { cells: max } : null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function scrollTargetByDelta(scrollBox: ScrollBoxRenderable, delta: number): ScrollTarget | null {
|
|
99
|
+
if ((scrollBox.viewport?.height ?? 0) <= 0) return null;
|
|
100
|
+
const wanted = scrollBox.scrollTop + delta;
|
|
101
|
+
if (delta < 0 && wanted <= 0) return topTarget(scrollBox);
|
|
102
|
+
if (delta > 0 && wanted >= maxScrollTop(scrollBox)) return bottomTarget(scrollBox);
|
|
103
|
+
return delta === 0 ? null : { cells: wanted };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function applyScrollTarget(scrollBox: ScrollBoxRenderable, target: ScrollTarget): void {
|
|
107
|
+
if ("pixels" in target) {
|
|
108
|
+
scrollBox.scrollToPixels?.(target.pixels);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
scrollBox.scrollTo(target.cells);
|
|
112
|
+
if (scrollBox.scrollTop !== target.cells) {
|
|
113
|
+
scrollBox.scrollTop = target.cells;
|
|
114
|
+
}
|
|
71
115
|
}
|
|
72
116
|
|
|
73
117
|
/**
|
|
@@ -76,7 +120,7 @@ function scrollTargetByDelta(scrollBox: ScrollBoxRenderable, delta: number): num
|
|
|
76
120
|
*/
|
|
77
121
|
export function scrollByLines(scrollBox: ScrollBoxRenderable, delta: number): void {
|
|
78
122
|
const target = scrollTargetByDelta(scrollBox, delta);
|
|
79
|
-
if (target
|
|
123
|
+
if (target) applyScrollTarget(scrollBox, target);
|
|
80
124
|
}
|
|
81
125
|
|
|
82
126
|
function arrowScrollLines(scrollBox: ScrollBoxRenderable): number {
|
|
@@ -117,20 +161,9 @@ function resolveKeyScrollAction(event: PaneScrollKeyEvent): PaneScrollAction | n
|
|
|
117
161
|
),
|
|
118
162
|
};
|
|
119
163
|
case "home":
|
|
120
|
-
return {
|
|
121
|
-
direction: "up",
|
|
122
|
-
resolveTarget: (scrollBox) => (
|
|
123
|
-
scrollBox.scrollTop > 0 ? 0 : null
|
|
124
|
-
),
|
|
125
|
-
};
|
|
164
|
+
return { direction: "up", resolveTarget: topTarget };
|
|
126
165
|
case "end":
|
|
127
|
-
return {
|
|
128
|
-
direction: "down",
|
|
129
|
-
resolveTarget: (scrollBox) => {
|
|
130
|
-
const target = clampScrollTop(scrollBox, Number.MAX_SAFE_INTEGER);
|
|
131
|
-
return target == null || target === scrollBox.scrollTop ? null : target;
|
|
132
|
-
},
|
|
133
|
-
};
|
|
166
|
+
return { direction: "down", resolveTarget: bottomTarget };
|
|
134
167
|
default:
|
|
135
168
|
return null;
|
|
136
169
|
}
|
|
@@ -145,12 +178,12 @@ function getEntryScore(entry: PaneScrollEntry, scrollBox: ScrollBoxRenderable):
|
|
|
145
178
|
function findScrollableEntry(paneId: string, action: PaneScrollAction): {
|
|
146
179
|
entry: PaneScrollEntry;
|
|
147
180
|
scrollBox: ScrollBoxRenderable;
|
|
148
|
-
target:
|
|
181
|
+
target: ScrollTarget;
|
|
149
182
|
} | null {
|
|
150
183
|
const entries = paneScrollBoxes.get(paneId);
|
|
151
184
|
if (!entries) return null;
|
|
152
185
|
|
|
153
|
-
let best: { entry: PaneScrollEntry; scrollBox: ScrollBoxRenderable; target:
|
|
186
|
+
let best: { entry: PaneScrollEntry; scrollBox: ScrollBoxRenderable; target: ScrollTarget; score: number } | null = null;
|
|
154
187
|
for (const entry of entries.values()) {
|
|
155
188
|
const scrollBox = entry.ref.current;
|
|
156
189
|
if (!scrollBox) continue;
|
|
@@ -176,17 +209,16 @@ function scrollPaneByKey(paneId: string, event: PaneScrollKeyEvent): boolean {
|
|
|
176
209
|
const match = findScrollableEntry(paneId, action);
|
|
177
210
|
if (!match) return false;
|
|
178
211
|
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
212
|
+
const { scrollBox } = match;
|
|
213
|
+
const position = () => scrollBox.scrollTopPx ?? scrollBox.scrollTop;
|
|
214
|
+
const previousTop = scrollBox.scrollTop;
|
|
215
|
+
const previousPosition = position();
|
|
216
|
+
applyScrollTarget(scrollBox, match.target);
|
|
184
217
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return delta > 0;
|
|
218
|
+
if (position() === previousPosition) return false;
|
|
219
|
+
const delta = Math.max(1, Math.abs(scrollBox.scrollTop - previousTop));
|
|
220
|
+
match.entry.onScrollActivity?.({ scroll: { direction: action.direction, delta } });
|
|
221
|
+
return true;
|
|
190
222
|
}
|
|
191
223
|
|
|
192
224
|
export function useForwardedScrollBoxRef<T>(
|
|
@@ -102,6 +102,10 @@ function sanitizePortfolio(portfolio: Portfolio): Portfolio {
|
|
|
102
102
|
currency: portfolio.currency,
|
|
103
103
|
brokerId: portfolio.brokerId,
|
|
104
104
|
lastSyncedAt: portfolio.lastSyncedAt,
|
|
105
|
+
// Cash and targets are the user's own entries: a pulled portfolio without
|
|
106
|
+
// them would erase them on this device.
|
|
107
|
+
...(portfolio.cash ? { cash: { ...portfolio.cash } } : {}),
|
|
108
|
+
...(portfolio.targetWeights ? { targetWeights: { ...portfolio.targetWeights } } : {}),
|
|
105
109
|
};
|
|
106
110
|
}
|
|
107
111
|
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type CrashReportsPayload,
|
|
7
7
|
} from "../api-client";
|
|
8
8
|
import type { TelemetryConfig } from "../types/config";
|
|
9
|
+
import { isSleepRpcTimeout } from "../utils/rpc-timeout-error";
|
|
9
10
|
import { VERSION } from "../version";
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -172,10 +173,12 @@ function toReportError(error: unknown, context: CrashReportContext): PendingErro
|
|
|
172
173
|
/**
|
|
173
174
|
* Queues one error. Safe to call from any error handler: it never throws,
|
|
174
175
|
* never awaits, and drops the error when reporting is off, already seen this
|
|
175
|
-
* session, or over the session cap.
|
|
176
|
+
* session, or over the session cap. A desktop request timeout that fired
|
|
177
|
+
* after the machine slept is not an error at all and is dropped too.
|
|
176
178
|
*/
|
|
177
179
|
export function reportCrash(error: unknown, context: CrashReportContext): void {
|
|
178
180
|
try {
|
|
181
|
+
if (isSleepRpcTimeout(error)) return;
|
|
179
182
|
if (host && !host.isEnabled()) return;
|
|
180
183
|
if (accepted >= MAX_ERRORS_PER_SESSION) return;
|
|
181
184
|
const entry = toReportError(error, context);
|
|
@@ -8,7 +8,8 @@ export interface PrintedCliResult {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* A command context whose `initMarketData`
|
|
11
|
+
* A command context whose `initMarketData` and `initConfigData` resolve to `market` (config, store, dataProvider, ...),
|
|
12
|
+
* with an empty ticker store unless `market` brings one.
|
|
12
13
|
* `fail` throws, every printResult call is kept in `printed`, and `closeCount` reports how many
|
|
13
14
|
* times the command closed its persistence.
|
|
14
15
|
*/
|
|
@@ -18,9 +19,16 @@ export function createTestCliContext(
|
|
|
18
19
|
): { context: CliCommandContext; printed: PrintedCliResult[]; closeCount: () => number } {
|
|
19
20
|
const printed: PrintedCliResult[] = [];
|
|
20
21
|
let closed = 0;
|
|
22
|
+
const init = async () => ({
|
|
23
|
+
persistence: { close: () => { closed += 1; } },
|
|
24
|
+
// Commands look up the saved listing of every symbol they are given.
|
|
25
|
+
store: { loadTicker: async () => null, loadAllTickers: async () => [] },
|
|
26
|
+
...market,
|
|
27
|
+
});
|
|
21
28
|
const context = {
|
|
22
29
|
cliOptions: { ...DEFAULT_CLI_OPTIONS, ...cliOptions },
|
|
23
|
-
initMarketData:
|
|
30
|
+
initMarketData: init,
|
|
31
|
+
initConfigData: init,
|
|
24
32
|
printResult: (result: CliResult<any>, options?: CliResultRenderOptions<any, any>) => { printed.push({ result, options }); },
|
|
25
33
|
fail: (message: string): never => { throw new Error(message); },
|
|
26
34
|
} as unknown as CliCommandContext;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Quote, TickerFinancials } from "../types/financials";
|
|
2
|
+
import type { Portfolio, TickerRecord } from "../types/ticker";
|
|
3
|
+
import type { BrokerAccount } from "../types/trading";
|
|
4
|
+
import { createTestTicker } from "./ticker";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An invented margin account: 1.0M of equity carrying 1.6M of positions, the
|
|
8
|
+
* difference borrowed in three currencies. It holds a US stock, a listing
|
|
9
|
+
* quoted in euros and an option, which no quote prices, so it stays at its
|
|
10
|
+
* broker mark. Every figure is made up.
|
|
11
|
+
*/
|
|
12
|
+
export const MARGIN_PORTFOLIO: Portfolio = {
|
|
13
|
+
id: "broker:margin-test:M1",
|
|
14
|
+
name: "Margin test",
|
|
15
|
+
currency: "USD",
|
|
16
|
+
brokerId: "test",
|
|
17
|
+
brokerInstanceId: "margin-test",
|
|
18
|
+
brokerAccountId: "M1",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Dollars per unit of each currency. */
|
|
22
|
+
export const MARGIN_EXCHANGE_RATES = new Map([["USD", 1], ["EUR", 1.2], ["JPY", 0.008]]);
|
|
23
|
+
|
|
24
|
+
const OPTION = "CCC 280121C00050000";
|
|
25
|
+
|
|
26
|
+
function holding(symbol: string, details: {
|
|
27
|
+
exchange: string;
|
|
28
|
+
currency: string;
|
|
29
|
+
shares: number;
|
|
30
|
+
mark: number;
|
|
31
|
+
multiplier?: number;
|
|
32
|
+
assetCategory?: string;
|
|
33
|
+
}): TickerRecord {
|
|
34
|
+
return createTestTicker(symbol, symbol, {
|
|
35
|
+
exchange: details.exchange,
|
|
36
|
+
currency: details.currency,
|
|
37
|
+
assetCategory: details.assetCategory,
|
|
38
|
+
portfolios: [MARGIN_PORTFOLIO.id],
|
|
39
|
+
positions: [{
|
|
40
|
+
portfolio: MARGIN_PORTFOLIO.id,
|
|
41
|
+
shares: details.shares,
|
|
42
|
+
avgCost: details.mark,
|
|
43
|
+
markPrice: details.mark,
|
|
44
|
+
marketValue: details.shares * details.mark * (details.multiplier ?? 1),
|
|
45
|
+
unrealizedPnl: 0,
|
|
46
|
+
multiplier: details.multiplier,
|
|
47
|
+
currency: details.currency,
|
|
48
|
+
side: "long",
|
|
49
|
+
broker: "test",
|
|
50
|
+
brokerInstanceId: "margin-test",
|
|
51
|
+
brokerAccountId: "M1",
|
|
52
|
+
}],
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const MARGIN_TICKERS: TickerRecord[] = [
|
|
57
|
+
holding("AAA", { exchange: "NASDAQ", currency: "USD", shares: 4_000, mark: 200 }),
|
|
58
|
+
holding("BBB", { exchange: "XETRA", currency: "EUR", shares: 5_000, mark: 100 }),
|
|
59
|
+
holding(OPTION, { exchange: "", currency: "USD", shares: 20, mark: 100, multiplier: 100, assetCategory: "OPT" }),
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
export function createMarginAccount(overrides: Partial<BrokerAccount> = {}): BrokerAccount {
|
|
63
|
+
return {
|
|
64
|
+
accountId: "M1",
|
|
65
|
+
name: "Margin test",
|
|
66
|
+
currency: "USD",
|
|
67
|
+
source: "cloud",
|
|
68
|
+
updatedAt: Date.now() - 60_000,
|
|
69
|
+
netLiquidation: 1_000_000,
|
|
70
|
+
grossPositionValue: 1_600_000,
|
|
71
|
+
totalCashValue: -600_000,
|
|
72
|
+
cashBalances: [
|
|
73
|
+
{ currency: "EUR", quantity: -250_000, baseValue: -300_000, baseCurrency: "USD" },
|
|
74
|
+
{ currency: "JPY", quantity: -25_000_000, baseValue: -200_000, baseCurrency: "USD" },
|
|
75
|
+
{ currency: "USD", quantity: -100_000, baseValue: -100_000, baseCurrency: "USD" },
|
|
76
|
+
],
|
|
77
|
+
...overrides,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function liveQuote(symbol: string, price: number, previousClose: number, currency: string, exchange: string): TickerFinancials {
|
|
82
|
+
const quote: Quote = {
|
|
83
|
+
symbol,
|
|
84
|
+
price,
|
|
85
|
+
change: price - previousClose,
|
|
86
|
+
changePercent: (price / previousClose - 1) * 100,
|
|
87
|
+
previousClose,
|
|
88
|
+
currency,
|
|
89
|
+
lastUpdated: Date.now() - 1_000,
|
|
90
|
+
listingExchangeName: exchange,
|
|
91
|
+
marketState: "REGULAR",
|
|
92
|
+
dataSource: "live",
|
|
93
|
+
};
|
|
94
|
+
return { annualStatements: [], quarterlyStatements: [], priceHistory: [], quote };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Real-time quotes for the stock and the euro listing, the stock `move`
|
|
99
|
+
* dollars above its mark. With `option`, the option is quoted at its mark too,
|
|
100
|
+
* so every position has a live price.
|
|
101
|
+
*/
|
|
102
|
+
export function marginQuotes({ move = 0, option = false }: { move?: number; option?: boolean } = {}): Map<string, TickerFinancials> {
|
|
103
|
+
return new Map([
|
|
104
|
+
["AAA", liveQuote("AAA", 200 + move, 200, "USD", "NASDAQ")],
|
|
105
|
+
["BBB", liveQuote("BBB", 100, 100, "EUR", "XETRA")],
|
|
106
|
+
...(option ? [[OPTION, liveQuote(OPTION, 100, 100, "USD", "CBOE")] as const] : []),
|
|
107
|
+
]);
|
|
108
|
+
}
|