gloomberb 0.16.1 → 0.16.2
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 +24 -0
- package/src/cli/commands/command-utils.ts +8 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +414 -106
- package/src/cli/commands/overview.ts +77 -32
- package/src/cli/commands/ticker.ts +101 -43
- package/src/cli/desktop-pane-shot.ts +34 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +1 -0
- package/src/cli/helpers.ts +4 -8
- package/src/cli/index.ts +12 -2
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/pane-functions/access-gate.ts +42 -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 +20 -2
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +27 -20
- package/src/cli/pane-functions/headless.ts +39 -11
- package/src/cli/pane-functions/index.ts +15 -4
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +35 -7
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +7 -3
- package/src/cli/result.ts +41 -27
- 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/view.tsx +29 -10
- 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/menu.ts +2 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +14 -3
- 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/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 +78 -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/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/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 +1 -1
- 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/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 +1 -1
- 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/headless.ts +139 -5
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +20 -3
- package/src/plugins/builtin/holders/report-header.ts +95 -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/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 +13 -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 +248 -47
- package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -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 +230 -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 +98 -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 +47 -13
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -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 +11 -3
- 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/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/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/social-mentions/headless.ts +1 -0
- 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/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -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 +157 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -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 +447 -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 +67 -4
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
- package/src/plugins/builtin/world-venue-map/model.ts +7 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -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 +28 -43
- 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/dom/build-assets.ts +81 -3
- 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/input.tsx +14 -3
- package/src/renderers/dom/styles.css +6 -7
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -0
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +27 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financials.ts +8 -7
- package/src/sources/provider-router/history.ts +15 -10
- 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/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/theme/heat-colors.ts +266 -84
- 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 +3 -0
- 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 +14 -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 +14 -0
- package/src/utils/depositary-receipt.ts +26 -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/price-earnings.ts +70 -3
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from "fs/promises";
|
|
2
|
-
import { join, relative } from "path";
|
|
2
|
+
import { dirname, join, relative, resolve } from "path";
|
|
3
|
+
import type { BunPlugin } from "bun";
|
|
3
4
|
import { TITLEBAR_OVERLAY_HEIGHT_PX } from "../../components/layout/titlebar-overlay";
|
|
4
5
|
|
|
5
6
|
/** Imports whose path ends with the first entry resolve to the second, relative to the view directory. */
|
|
@@ -27,6 +28,13 @@ interface ViewBundleOptions {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const ELECTROBUN_VIEW_DIR = join(process.cwd(), "src", "renderers", "electrobun", "view");
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Where the world map finds its land data, relative to the map's
|
|
34
|
+
* `basemap.ts`. Only view bundles define it, so the terminal binary, which
|
|
35
|
+
* never draws that map, leaves the data out.
|
|
36
|
+
*/
|
|
37
|
+
export const WORLD_MAP_DATA_SPECIFIER = "./natural-earth/index.chunk.js";
|
|
30
38
|
const DOM_RENDERER_DIR = join(process.cwd(), "src", "renderers", "dom");
|
|
31
39
|
|
|
32
40
|
export function electrobunViewPath(...parts: string[]): string {
|
|
@@ -50,6 +58,7 @@ export async function buildViewBundle({
|
|
|
50
58
|
failureMessage,
|
|
51
59
|
missingEntryMessage,
|
|
52
60
|
}: ViewBundleOptions): Promise<{ script: string; stylesheet: string | null }> {
|
|
61
|
+
const chunks = new Map<string, string>();
|
|
53
62
|
const result = await Bun.build({
|
|
54
63
|
entrypoints: [entrypoint],
|
|
55
64
|
outdir,
|
|
@@ -58,8 +67,15 @@ export async function buildViewBundle({
|
|
|
58
67
|
splitting: false,
|
|
59
68
|
sourcemap,
|
|
60
69
|
minify: true,
|
|
61
|
-
define: {
|
|
62
|
-
|
|
70
|
+
define: {
|
|
71
|
+
"process.env.NODE_ENV": "\"production\"",
|
|
72
|
+
__GLOOM_WORLD_MAP_DATA__: JSON.stringify(WORLD_MAP_DATA_SPECIFIER),
|
|
73
|
+
...define,
|
|
74
|
+
},
|
|
75
|
+
plugins: [
|
|
76
|
+
lazyChunkPlugin(outdir, outdir, chunks),
|
|
77
|
+
...(aliasRules.length > 0 ? [electrobunViewAliasPlugin(aliasRules)] : []),
|
|
78
|
+
],
|
|
63
79
|
});
|
|
64
80
|
|
|
65
81
|
if (!result.success) {
|
|
@@ -69,6 +85,7 @@ export async function buildViewBundle({
|
|
|
69
85
|
|
|
70
86
|
const script = result.outputs.find((output) => output.kind === "entry-point" && output.path.endsWith(".js"));
|
|
71
87
|
if (!script) throw new Error(missingEntryMessage);
|
|
88
|
+
await buildLazyChunks(outdir, chunks, failureMessage);
|
|
72
89
|
|
|
73
90
|
const stylesheet = result.outputs.find((output) => output.path.endsWith(".css"))?.path ?? null;
|
|
74
91
|
if (stylesheet) await writeFile(stylesheet, withTitlebarOverlayHeight(await readFile(stylesheet, "utf8")));
|
|
@@ -122,6 +139,67 @@ ${bootstrapScript}
|
|
|
122
139
|
`;
|
|
123
140
|
}
|
|
124
141
|
|
|
142
|
+
/**
|
|
143
|
+
* The view bundle is one file (no splitting), so a module reached through
|
|
144
|
+
* `import()` would land in it. A module named `*.chunk.ts` and imported as
|
|
145
|
+
* `import("./path/name.chunk.js")` instead ships as its own file at that path
|
|
146
|
+
* next to the importing bundle, fetched the first time it is asked for: large
|
|
147
|
+
* data only some panes draw, such as the world map's coastlines. The terminal
|
|
148
|
+
* and the tests run the source, where the same `import()` loads the module.
|
|
149
|
+
*/
|
|
150
|
+
function lazyChunkPlugin(rootOutdir: string, emitDir: string, chunks: Map<string, string>): BunPlugin {
|
|
151
|
+
return {
|
|
152
|
+
name: "lazy-chunks",
|
|
153
|
+
setup(build) {
|
|
154
|
+
build.onResolve({ filter: /\.chunk(\.js|\.ts)?$/ }, (args) => {
|
|
155
|
+
if (args.kind.startsWith("entry-point") || /[\\/]node_modules[\\/]/.test(args.importer)) return undefined;
|
|
156
|
+
if (args.kind !== "dynamic-import") {
|
|
157
|
+
throw new Error(`${args.path} is a lazy chunk; load it with import() (from ${args.importer})`);
|
|
158
|
+
}
|
|
159
|
+
if (!args.path.startsWith("./") || !args.path.endsWith(".chunk.js")) {
|
|
160
|
+
throw new Error(`Lazy chunk ${args.path} must be imported as "./<path>.chunk.js" (from ${args.importer})`);
|
|
161
|
+
}
|
|
162
|
+
const source = resolve(dirname(args.importer), args.path.replace(/\.js$/, ".ts"));
|
|
163
|
+
const output = resolve(emitDir, args.path);
|
|
164
|
+
if (relative(rootOutdir, output).startsWith("..")) throw new Error(`Lazy chunk ${args.path} would land outside ${rootOutdir}`);
|
|
165
|
+
const existing = chunks.get(output);
|
|
166
|
+
if (existing && existing !== source) throw new Error(`Two lazy chunks emit ${output}: ${existing} and ${source}`);
|
|
167
|
+
chunks.set(output, source);
|
|
168
|
+
return { path: args.path, external: true };
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Builds each lazy chunk on its own, and the chunks those load in turn. */
|
|
175
|
+
async function buildLazyChunks(rootOutdir: string, chunks: Map<string, string>, failureMessage: string): Promise<void> {
|
|
176
|
+
const built = new Set<string>();
|
|
177
|
+
let pending = [...chunks.entries()];
|
|
178
|
+
while (pending.length) {
|
|
179
|
+
const nested = new Map<string, string>();
|
|
180
|
+
for (const [output, source] of pending) {
|
|
181
|
+
if (built.has(output)) continue;
|
|
182
|
+
built.add(output);
|
|
183
|
+
const result = await Bun.build({
|
|
184
|
+
entrypoints: [source],
|
|
185
|
+
outdir: dirname(output),
|
|
186
|
+
naming: relative(dirname(output), output),
|
|
187
|
+
target: "browser",
|
|
188
|
+
format: "esm",
|
|
189
|
+
splitting: false,
|
|
190
|
+
sourcemap: "none",
|
|
191
|
+
minify: true,
|
|
192
|
+
plugins: [lazyChunkPlugin(rootOutdir, dirname(output), nested)],
|
|
193
|
+
});
|
|
194
|
+
if (!result.success) {
|
|
195
|
+
const details = result.logs.map((log) => log.message).filter(Boolean).join("\n");
|
|
196
|
+
throw new Error(`${failureMessage}: lazy chunk ${source}\n${details}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
pending = [...nested.entries()];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
125
203
|
function electrobunViewAliasPlugin(aliasRules: AliasRule[]) {
|
|
126
204
|
return {
|
|
127
205
|
name: "electrobun-view-aliases",
|
|
@@ -353,6 +353,8 @@ function WebDataTableRowInner<
|
|
|
353
353
|
<div
|
|
354
354
|
key={column.id}
|
|
355
355
|
data-gloom-role="data-table-cell"
|
|
356
|
+
// The instant behind a shortened time ("Wed 11:27"), so a rendered-view report can print it whole.
|
|
357
|
+
data-gloom-cell-instant={cell.value instanceof Date && Number.isFinite(cell.value.getTime()) ? cell.value.toISOString() : undefined}
|
|
356
358
|
style={{
|
|
357
359
|
minWidth: 0,
|
|
358
360
|
position: freezeFirstColumn && columnIndex === 0 ? "sticky" : undefined,
|
|
@@ -345,8 +345,10 @@ export function WebTextField({
|
|
|
345
345
|
focusedBackgroundColor={plain ? "transparent" : resolvedBackgroundColor}
|
|
346
346
|
cursorColor={colors.textBright}
|
|
347
347
|
style={{
|
|
348
|
-
|
|
349
|
-
|
|
348
|
+
// A framed field keeps its text one cell off the frame; a plain one
|
|
349
|
+
// sits flush in the row or band that holds it.
|
|
350
|
+
paddingLeft: plain ? 0 : "var(--cell-w)",
|
|
351
|
+
paddingRight: plain ? 0 : "var(--cell-w)",
|
|
350
352
|
borderRadius: plain ? 0 : CONTROL_RADIUS,
|
|
351
353
|
// The field is taller than a cell, so the input takes the inner
|
|
352
354
|
// height and centers its text on the box's own line.
|
|
@@ -581,8 +583,10 @@ export function WebDialogFrame({
|
|
|
581
583
|
</Box>
|
|
582
584
|
{children}
|
|
583
585
|
{footer && (
|
|
586
|
+
// Sized by its line, not one cell: a cell-high box with this padding
|
|
587
|
+
// left the key line hanging out of its bottom.
|
|
584
588
|
<Box
|
|
585
|
-
|
|
589
|
+
flexShrink={0}
|
|
586
590
|
style={{
|
|
587
591
|
borderTop: `1px solid ${panelBorder(colors)}`,
|
|
588
592
|
paddingTop: 8,
|
|
@@ -5,6 +5,7 @@ import { TextAttributes } from "../../../ui";
|
|
|
5
5
|
import type { ListRowState, ListViewItem, ListViewProps } from "../../../components/ui/list-view";
|
|
6
6
|
import { blendHex, hoverBg, type ThemeColors } from "../../../theme/colors";
|
|
7
7
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
8
|
+
import { WEB_CELL_HEIGHT } from "../../../theme/font-scale";
|
|
8
9
|
import { isInsideDialogSurface } from "../host/focus-scope";
|
|
9
10
|
import { isEditableKeyboardTarget } from "../key-event";
|
|
10
11
|
import {
|
|
@@ -58,6 +59,10 @@ function DefaultDesktopRow({
|
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
const FRAMED_LIST_PADDING_PX = 4;
|
|
63
|
+
/** What a framed list adds above and below its rows: padding and a 1px border on each side. */
|
|
64
|
+
const FRAMED_LIST_CHROME_PX = 2 * (FRAMED_LIST_PADDING_PX + 1);
|
|
65
|
+
|
|
61
66
|
function listRowStyle(selected: boolean, disabled: boolean, colors: ThemeColors): CSSProperties {
|
|
62
67
|
return {
|
|
63
68
|
borderRadius: CONTROL_RADIUS,
|
|
@@ -109,6 +114,16 @@ export function WebListView({
|
|
|
109
114
|
const tabStopIndex = selectedIndex >= 0 && items[selectedIndex] && !items[selectedIndex].disabled
|
|
110
115
|
? selectedIndex : items.findIndex((item) => !item.disabled);
|
|
111
116
|
const effectiveSurface = surface ?? (scrollable ? "framed" : "plain");
|
|
117
|
+
// `height` counts terminal rows. A list that is not meant to scroll takes
|
|
118
|
+
// only the rows it has, up to that many; one with more rows than that
|
|
119
|
+
// scrolls inside the height instead of drawing over whatever follows it.
|
|
120
|
+
const rowsHeight = items.length === 0 ? 1 : items.length * rowHeight + (items.length - 1) * rowGap;
|
|
121
|
+
const overflowsHeight = !scrollable && height != null && rowsHeight > height;
|
|
122
|
+
const scrolls = scrollable || overflowsHeight;
|
|
123
|
+
// The frame's padding and border sit outside the rows it was asked to hold.
|
|
124
|
+
const scrollHeight = overflowsHeight
|
|
125
|
+
? `${height * WEB_CELL_HEIGHT + (effectiveSurface === "plain" ? 0 : FRAMED_LIST_CHROME_PX)}px`
|
|
126
|
+
: height;
|
|
112
127
|
const frameStyle = effectiveSurface === "plain"
|
|
113
128
|
? {
|
|
114
129
|
border: "none",
|
|
@@ -119,12 +134,12 @@ export function WebListView({
|
|
|
119
134
|
: {
|
|
120
135
|
border: `1px solid ${panelBorder(colors)}`,
|
|
121
136
|
borderRadius: CONTROL_RADIUS,
|
|
122
|
-
padding:
|
|
137
|
+
padding: FRAMED_LIST_PADDING_PX,
|
|
123
138
|
backgroundColor: subtlePanelFill(colors),
|
|
124
139
|
};
|
|
125
140
|
|
|
126
141
|
useEffect(() => {
|
|
127
|
-
if (!
|
|
142
|
+
if (!scrolls || !autoScrollToIndex || activeScrollIndex < 0) return;
|
|
128
143
|
const scrollBox = scrollRef.current;
|
|
129
144
|
if (!scrollBox) return;
|
|
130
145
|
const safeIndex = Math.min(activeScrollIndex, items.length - 1);
|
|
@@ -136,16 +151,16 @@ export function WebListView({
|
|
|
136
151
|
} else if (rowBottom > scrollBox.scrollTop + viewportHeight) {
|
|
137
152
|
scrollBox.scrollTo(rowBottom - viewportHeight);
|
|
138
153
|
}
|
|
139
|
-
}, [activeScrollIndex, autoScrollToIndex, items.length, rowHeight, rowStride,
|
|
154
|
+
}, [activeScrollIndex, autoScrollToIndex, items.length, rowHeight, rowStride, scrolls]);
|
|
140
155
|
|
|
141
156
|
useEffect(() => {
|
|
142
|
-
if (!
|
|
157
|
+
if (!scrolls) return;
|
|
143
158
|
const scrollBox = scrollRef.current;
|
|
144
159
|
if (!scrollBox) return;
|
|
145
160
|
if (scrollBox.verticalScrollBar) {
|
|
146
161
|
scrollBox.verticalScrollBar.visible = items.length * rowStride - rowGap > (scrollBox.viewport?.height ?? 0);
|
|
147
162
|
}
|
|
148
|
-
}, [items.length, height, flexGrow, rowGap, rowStride,
|
|
163
|
+
}, [items.length, height, flexGrow, rowGap, rowStride, scrolls]);
|
|
149
164
|
|
|
150
165
|
// The dialog or pane around the list moves its cursor (j/k, Home/End). A row
|
|
151
166
|
// Tab or a press left focused follows it, or Space and Enter would act on the
|
|
@@ -156,8 +171,8 @@ export function WebListView({
|
|
|
156
171
|
const active = document.activeElement;
|
|
157
172
|
if (!list || !active || !list.contains(active) || isEditableKeyboardTarget(active)) return;
|
|
158
173
|
const row = list.querySelectorAll<HTMLElement>('[role="option"]')[selectedIndex];
|
|
159
|
-
if (row && !row.contains(active)) row.focus({ preventScroll:
|
|
160
|
-
}, [listDomId,
|
|
174
|
+
if (row && !row.contains(active)) row.focus({ preventScroll: scrolls });
|
|
175
|
+
}, [listDomId, scrolls, selectedIndex]);
|
|
161
176
|
|
|
162
177
|
const rows = items.length === 0
|
|
163
178
|
? (
|
|
@@ -233,11 +248,21 @@ export function WebListView({
|
|
|
233
248
|
});
|
|
234
249
|
|
|
235
250
|
return (
|
|
236
|
-
<Box
|
|
237
|
-
{
|
|
251
|
+
<Box
|
|
252
|
+
id={listDomId}
|
|
253
|
+
flexDirection="column"
|
|
254
|
+
height={scrollable ? height : undefined}
|
|
255
|
+
// A list sized by its container gives up height to it, and scrolls.
|
|
256
|
+
minHeight={scrollable && height == null ? 0 : undefined}
|
|
257
|
+
flexGrow={flexGrow}
|
|
258
|
+
gap={1}
|
|
259
|
+
role="listbox"
|
|
260
|
+
aria-label={remoteLabel}
|
|
261
|
+
>
|
|
262
|
+
{scrolls ? (
|
|
238
263
|
<ScrollBox
|
|
239
264
|
ref={scrollRef}
|
|
240
|
-
height={
|
|
265
|
+
height={scrollHeight}
|
|
241
266
|
flexGrow={flexGrow}
|
|
242
267
|
scrollY
|
|
243
268
|
focusable={false}
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
-
import type { HostPopoverProps } from "../../../ui";
|
|
5
|
+
import type { BoxRenderable, HostPopoverProps } from "../../../ui";
|
|
6
6
|
import { blendHex } from "../../../theme/colors";
|
|
7
|
+
import { WEB_CELL_HEIGHT, WEB_CELL_WIDTH } from "../../../theme/font-scale";
|
|
7
8
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
8
9
|
|
|
9
10
|
const VIEWPORT_MARGIN = 10;
|
|
11
|
+
/** How far a popover kept inside its pane stays off the pane's edge. */
|
|
12
|
+
const PANE_MARGIN = 4;
|
|
10
13
|
const POPOVER_GAP = 6;
|
|
14
|
+
const PANE_SELECTOR = '[data-gloom-role="pane-window"], [data-gloom-role="detached-pane-window"]';
|
|
11
15
|
/** `.gloom-popover` in styles.css: above dialogs and toasts. */
|
|
12
16
|
const POPOVER_Z_INDEX = 10_001;
|
|
13
17
|
|
|
@@ -21,6 +25,51 @@ function cssSize(value: number | string | undefined): number | string | undefine
|
|
|
21
25
|
return typeof value === "number" ? `${value}px` : value;
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
interface Edges {
|
|
29
|
+
left: number;
|
|
30
|
+
top: number;
|
|
31
|
+
right: number;
|
|
32
|
+
bottom: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Where an anchor element is now, in viewport pixels. Null once it is gone
|
|
37
|
+
* from the page (a removed message), so the popover falls back to its trigger.
|
|
38
|
+
*/
|
|
39
|
+
function anchorEdges(anchor: BoxRenderable): Edges | null {
|
|
40
|
+
const rect = anchor.getBoundingClientRect?.();
|
|
41
|
+
if (rect) {
|
|
42
|
+
if (rect.width === 0 && rect.height === 0) return null;
|
|
43
|
+
return { left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height };
|
|
44
|
+
}
|
|
45
|
+
const bounds = anchor.absoluteBounds;
|
|
46
|
+
if (!bounds) return null;
|
|
47
|
+
return {
|
|
48
|
+
left: bounds.x * WEB_CELL_WIDTH,
|
|
49
|
+
top: bounds.y * WEB_CELL_HEIGHT,
|
|
50
|
+
right: (bounds.x + bounds.width) * WEB_CELL_WIDTH,
|
|
51
|
+
bottom: (bounds.y + bounds.height) * WEB_CELL_HEIGHT,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The area a popover must stay in: the window, and for `pane` the pane that holds its trigger too. */
|
|
56
|
+
function placementEdges(wrapper: Element | null, boundary: HostPopoverProps["boundary"]): Edges {
|
|
57
|
+
const viewport = {
|
|
58
|
+
left: VIEWPORT_MARGIN,
|
|
59
|
+
top: VIEWPORT_MARGIN,
|
|
60
|
+
right: window.innerWidth - VIEWPORT_MARGIN,
|
|
61
|
+
bottom: window.innerHeight - VIEWPORT_MARGIN,
|
|
62
|
+
};
|
|
63
|
+
const pane = boundary === "pane" ? wrapper?.closest(PANE_SELECTOR)?.getBoundingClientRect() : null;
|
|
64
|
+
if (!pane) return viewport;
|
|
65
|
+
return {
|
|
66
|
+
left: Math.max(viewport.left, pane.left + PANE_MARGIN),
|
|
67
|
+
top: Math.max(viewport.top, pane.top + PANE_MARGIN),
|
|
68
|
+
right: Math.min(viewport.right, pane.right - PANE_MARGIN),
|
|
69
|
+
bottom: Math.min(viewport.bottom, pane.bottom - PANE_MARGIN),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
24
73
|
/**
|
|
25
74
|
* The popover is portalled to <body>, so its z-index only competes in the root
|
|
26
75
|
* stacking context. A trigger inside a surface stacked above the popover layer
|
|
@@ -45,6 +94,10 @@ export function WebPopover({
|
|
|
45
94
|
trigger,
|
|
46
95
|
children,
|
|
47
96
|
anchorPoint,
|
|
97
|
+
anchor,
|
|
98
|
+
boundary = "viewport",
|
|
99
|
+
onPointerEnter,
|
|
100
|
+
onPointerLeave,
|
|
48
101
|
placement = "bottom-start",
|
|
49
102
|
minWidth = 280,
|
|
50
103
|
maxWidth = "min(420px, calc(100vw - 20px))",
|
|
@@ -59,18 +112,19 @@ export function WebPopover({
|
|
|
59
112
|
const [zIndex, setZIndex] = useState<number | undefined>(undefined);
|
|
60
113
|
|
|
61
114
|
const updatePosition = useCallback(() => {
|
|
62
|
-
const
|
|
115
|
+
const wrapper = anchorRef.current;
|
|
63
116
|
const popover = popoverRef.current;
|
|
64
|
-
if (!
|
|
117
|
+
if (!wrapper || !popover) return;
|
|
65
118
|
|
|
66
119
|
const popoverRect = popover.getBoundingClientRect();
|
|
67
|
-
const triggerRect =
|
|
120
|
+
const triggerRect = wrapper.getBoundingClientRect();
|
|
121
|
+
const elementEdges = anchor ? anchorEdges(anchor) : null;
|
|
68
122
|
// Keyboard-driven popovers can intentionally omit a visible trigger. In
|
|
69
123
|
// that case the anchor wrapper still inherits a line-height, so its DOM
|
|
70
124
|
// rect is not truly empty even though there is nothing useful to anchor to.
|
|
71
125
|
// Center these unanchored menus; explicit pointer/footer coordinates still
|
|
72
126
|
// take precedence below.
|
|
73
|
-
if (!anchorPoint && (trigger == null || (triggerRect.width === 0 && triggerRect.height === 0))) {
|
|
127
|
+
if (!elementEdges && !anchorPoint && (trigger == null || (triggerRect.width === 0 && triggerRect.height === 0))) {
|
|
74
128
|
setPosition({
|
|
75
129
|
left: Math.max(
|
|
76
130
|
VIEWPORT_MARGIN,
|
|
@@ -90,28 +144,26 @@ export function WebPopover({
|
|
|
90
144
|
});
|
|
91
145
|
return;
|
|
92
146
|
}
|
|
93
|
-
const anchorRect = anchorPoint
|
|
147
|
+
const anchorRect = elementEdges ?? (anchorPoint
|
|
94
148
|
? {
|
|
95
149
|
left: anchorPoint.x,
|
|
96
150
|
right: anchorPoint.x,
|
|
97
151
|
top: anchorPoint.y,
|
|
98
152
|
bottom: anchorPoint.y,
|
|
99
153
|
}
|
|
100
|
-
: triggerRect;
|
|
154
|
+
: triggerRect);
|
|
155
|
+
const edges = placementEdges(wrapper, boundary);
|
|
101
156
|
const preferredLeft = placement === "bottom-end"
|
|
102
157
|
? anchorRect.right - popoverRect.width
|
|
103
158
|
: anchorRect.left;
|
|
104
|
-
const left = Math.max(
|
|
105
|
-
VIEWPORT_MARGIN,
|
|
106
|
-
Math.min(preferredLeft, window.innerWidth - popoverRect.width - VIEWPORT_MARGIN),
|
|
107
|
-
);
|
|
159
|
+
const left = Math.max(edges.left, Math.min(preferredLeft, edges.right - popoverRect.width));
|
|
108
160
|
const below = anchorRect.bottom + POPOVER_GAP;
|
|
109
161
|
const above = anchorRect.top - popoverRect.height - POPOVER_GAP;
|
|
110
|
-
const top = below + popoverRect.height <=
|
|
162
|
+
const top = below + popoverRect.height <= edges.bottom
|
|
111
163
|
? below
|
|
112
|
-
: Math.max(
|
|
164
|
+
: Math.max(edges.top, above);
|
|
113
165
|
setPosition({ left, top, visible: true });
|
|
114
|
-
}, [anchorPoint, placement, trigger]);
|
|
166
|
+
}, [anchor, anchorPoint, boundary, placement, trigger]);
|
|
115
167
|
|
|
116
168
|
useLayoutEffect(() => {
|
|
117
169
|
if (!open) {
|
|
@@ -123,10 +175,15 @@ export function WebPopover({
|
|
|
123
175
|
const frame = window.requestAnimationFrame(updatePosition);
|
|
124
176
|
window.addEventListener("resize", updatePosition);
|
|
125
177
|
document.addEventListener("scroll", updatePosition, true);
|
|
178
|
+
// New content (a hover card swapped to another name) can change the size
|
|
179
|
+
// the placement was worked out for.
|
|
180
|
+
const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(updatePosition) : null;
|
|
181
|
+
if (popoverRef.current) resizeObserver?.observe(popoverRef.current);
|
|
126
182
|
return () => {
|
|
127
183
|
window.cancelAnimationFrame(frame);
|
|
128
184
|
window.removeEventListener("resize", updatePosition);
|
|
129
185
|
document.removeEventListener("scroll", updatePosition, true);
|
|
186
|
+
resizeObserver?.disconnect();
|
|
130
187
|
};
|
|
131
188
|
}, [open, updatePosition]);
|
|
132
189
|
|
|
@@ -181,6 +238,8 @@ export function WebPopover({
|
|
|
181
238
|
tabIndex={-1}
|
|
182
239
|
onMouseDown={(event) => event.stopPropagation()}
|
|
183
240
|
onClick={(event) => event.stopPropagation()}
|
|
241
|
+
onMouseEnter={onPointerEnter}
|
|
242
|
+
onMouseLeave={onPointerLeave}
|
|
184
243
|
style={{
|
|
185
244
|
left: position.left,
|
|
186
245
|
top: position.top,
|
|
@@ -27,9 +27,21 @@ function textInputStyle(props: Record<string, unknown>, multiline: boolean): CSS
|
|
|
27
27
|
const backgroundColor = focused && typeof props.focusedBackgroundColor === "string"
|
|
28
28
|
? props.focusedBackgroundColor
|
|
29
29
|
: props.backgroundColor;
|
|
30
|
+
const base = commonStyle(props);
|
|
31
|
+
const overrides = props.style as CSSProperties | undefined;
|
|
30
32
|
|
|
31
33
|
return {
|
|
32
|
-
...
|
|
34
|
+
...base,
|
|
35
|
+
// Flush unless the caller insets the text. Longhands, never the `padding`
|
|
36
|
+
// shorthand: React writes style keys in order, and a shorthand here landed
|
|
37
|
+
// after a caller's `paddingLeft` and wiped it, so every bordered field's
|
|
38
|
+
// text sat on its border.
|
|
39
|
+
...(overrides?.padding === undefined ? {
|
|
40
|
+
paddingTop: base.paddingTop ?? 0,
|
|
41
|
+
paddingRight: base.paddingRight ?? 0,
|
|
42
|
+
paddingBottom: base.paddingBottom ?? 0,
|
|
43
|
+
paddingLeft: base.paddingLeft ?? 0,
|
|
44
|
+
} : {}),
|
|
33
45
|
display: "block",
|
|
34
46
|
resize: "none",
|
|
35
47
|
border: "none",
|
|
@@ -40,10 +52,9 @@ function textInputStyle(props: Record<string, unknown>, multiline: boolean): CSS
|
|
|
40
52
|
overflow: multiline ? "auto" : "hidden",
|
|
41
53
|
width: cellWidth(props.width) ?? "100%",
|
|
42
54
|
height: cellHeight(props.height) ?? (multiline ? "100%" : "var(--cell-h)"),
|
|
43
|
-
padding: 0,
|
|
44
55
|
margin: 0,
|
|
45
56
|
caretColor: typeof props.cursorColor === "string" ? props.cursorColor : "auto",
|
|
46
|
-
...
|
|
57
|
+
...overrides,
|
|
47
58
|
};
|
|
48
59
|
}
|
|
49
60
|
|
|
@@ -140,10 +140,12 @@ button, [data-gloom-interactive="true"] { cursor: pointer; }
|
|
|
140
140
|
-webkit-user-select: none;
|
|
141
141
|
user-select: none;
|
|
142
142
|
}
|
|
143
|
-
[data-gloom-role="pane-
|
|
144
|
-
[data-gloom-role="pane-header-chrome"] {
|
|
143
|
+
[data-gloom-role="pane-header"][data-drag-surface="pane"] {
|
|
145
144
|
cursor: grab;
|
|
146
145
|
}
|
|
146
|
+
[data-gloom-role="pane-header-tabs"] {
|
|
147
|
+
cursor: default;
|
|
148
|
+
}
|
|
147
149
|
[data-gloom-role="pane-header"] [data-gloom-role="tab-button"],
|
|
148
150
|
[data-gloom-role="pane-header"] button,
|
|
149
151
|
[data-gloom-role="pane-header"] [data-gloom-interactive="true"] {
|
|
@@ -157,11 +159,8 @@ button, [data-gloom-interactive="true"] { cursor: pointer; }
|
|
|
157
159
|
[data-gloom-role="pane-restore"] {
|
|
158
160
|
cursor: pointer;
|
|
159
161
|
}
|
|
160
|
-
body.gloom-dragging
|
|
161
|
-
body.gloom-dragging [data-gloom-role="pane-header
|
|
162
|
-
cursor: grabbing;
|
|
163
|
-
}
|
|
164
|
-
body.gloom-dragging {
|
|
162
|
+
body.gloom-dragging,
|
|
163
|
+
body.gloom-dragging [data-gloom-role="pane-header"] {
|
|
165
164
|
cursor: grabbing;
|
|
166
165
|
}
|
|
167
166
|
[data-gloom-role="pane-title"] {
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
} from "../shared/protocol";
|
|
15
15
|
import { decodeRpcResponse, decodeRpcValue, encodeRpcValue } from "../shared/rpc-codec";
|
|
16
16
|
import { subscribeCapability, type CapabilitySubscriptionOptions } from "./capability-subscription";
|
|
17
|
-
import {
|
|
17
|
+
import { RpcTimeoutError } from "../../../utils/rpc-timeout-error";
|
|
18
|
+
import { nameRpcTimeout, RPC_MAX_REQUEST_TIME_MS } from "./rpc-timeout";
|
|
18
19
|
import type { RemoteControlRequest, RemoteControlResponse } from "../../../remote/types";
|
|
19
20
|
|
|
20
21
|
type BackendMessages = ElectrobunDesktopRpcSchema["webview"]["messages"];
|
|
@@ -43,7 +44,7 @@ function emit<K extends BackendMessageName>(name: K, message: BackendMessages[K]
|
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const rpc = Electroview.defineRPC<ElectrobunDesktopRpcSchema>({
|
|
46
|
-
maxRequestTime:
|
|
47
|
+
maxRequestTime: RPC_MAX_REQUEST_TIME_MS,
|
|
47
48
|
handlers: {
|
|
48
49
|
requests: {
|
|
49
50
|
"remote.request": async (message: RemoteControlRequestMessage) => {
|
|
@@ -107,15 +108,20 @@ const rpc = Electroview.defineRPC<ElectrobunDesktopRpcSchema>({
|
|
|
107
108
|
|
|
108
109
|
const electroview = new Electroview({ rpc });
|
|
109
110
|
|
|
111
|
+
const BRIDGE_READY_LIMIT_MS = 5_000;
|
|
112
|
+
|
|
110
113
|
async function waitForBridgeReady(): Promise<void> {
|
|
111
114
|
const start = Date.now();
|
|
112
|
-
while (Date.now() - start <
|
|
115
|
+
while (Date.now() - start < BRIDGE_READY_LIMIT_MS) {
|
|
113
116
|
if (electroview.bunSocket?.readyState === WebSocket.OPEN) {
|
|
114
117
|
return;
|
|
115
118
|
}
|
|
116
119
|
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
117
120
|
}
|
|
118
|
-
throw new
|
|
121
|
+
throw new RpcTimeoutError("Electrobun RPC socket did not open in time.", {
|
|
122
|
+
elapsedMs: Date.now() - start,
|
|
123
|
+
limitMs: BRIDGE_READY_LIMIT_MS,
|
|
124
|
+
});
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
export function backendRequest<T = unknown>(
|
|
@@ -443,6 +443,7 @@ function ShotPane({ payload, registry }: { payload: DesktopPaneShotPayload; regi
|
|
|
443
443
|
component={pane.component}
|
|
444
444
|
paneId={instance.instanceId}
|
|
445
445
|
paneType={instance.paneId}
|
|
446
|
+
title={title}
|
|
446
447
|
focused
|
|
447
448
|
width={bodyFrame.width ?? 1}
|
|
448
449
|
height={bodyFrame.height ?? 1}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { getCloudApiBaseUrl } from "../../../api-client/request";
|
|
2
|
+
import { RpcTimeoutError } from "../../../utils/rpc-timeout-error";
|
|
2
3
|
import type { DesktopBackendRequestMethod } from "../shared/protocol";
|
|
3
4
|
|
|
5
|
+
/** How long the view waits for the Bun process to answer one request. */
|
|
6
|
+
export const RPC_MAX_REQUEST_TIME_MS = 120_000;
|
|
7
|
+
|
|
4
8
|
/** What Electrobun's request timer rejects with: no method, request id or caller. */
|
|
5
9
|
const ELECTROBUN_REQUEST_TIMEOUT_MESSAGE = "RPC request timed out.";
|
|
6
10
|
|
|
@@ -16,7 +20,9 @@ const ELECTROBUN_REQUEST_TIMEOUT_MESSAGE = "RPC request timed out.";
|
|
|
16
20
|
* from the user's config (a broker gateway, a feed, a plugin endpoint) and is
|
|
17
21
|
* only called external. Never the payload, rest of the path, query or headers.
|
|
18
22
|
* Elapsed time is rounded to 10 s because crash reports are deduplicated per
|
|
19
|
-
* session on the message.
|
|
23
|
+
* session on the message. The error keeps its message and `Error` type, and
|
|
24
|
+
* carries the elapsed time so a timer that fired long after its limit (the
|
|
25
|
+
* machine slept) can be told from a request that really stalled.
|
|
20
26
|
*/
|
|
21
27
|
export async function nameRpcTimeout<T>(
|
|
22
28
|
method: DesktopBackendRequestMethod,
|
|
@@ -28,8 +34,13 @@ export async function nameRpcTimeout<T>(
|
|
|
28
34
|
return await request();
|
|
29
35
|
} catch (error) {
|
|
30
36
|
if (!(error instanceof Error) || error.message !== ELECTROBUN_REQUEST_TIMEOUT_MESSAGE) throw error;
|
|
31
|
-
const
|
|
32
|
-
|
|
37
|
+
const elapsedMs = performance.now() - startedAt;
|
|
38
|
+
const seconds = Math.round(elapsedMs / 10_000) * 10;
|
|
39
|
+
throw new RpcTimeoutError(`RPC request timed out: ${describeRequest(method, payload)} after ~${seconds}s`, {
|
|
40
|
+
elapsedMs,
|
|
41
|
+
limitMs: RPC_MAX_REQUEST_TIME_MS,
|
|
42
|
+
cause: error,
|
|
43
|
+
});
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
|
|
@@ -108,6 +108,11 @@ export async function createOpenTuiHost(): Promise<OpenTuiHost> {
|
|
|
108
108
|
enableMouseMovement: true,
|
|
109
109
|
});
|
|
110
110
|
const root = createRoot(renderer);
|
|
111
|
+
// Every mounted ScrollBox listens for `selection` and many components for
|
|
112
|
+
// `resize`, so the counts grow with the panes on screen (14 and 18 with one
|
|
113
|
+
// DES open at 80x24) and fall back when they close. Node's default warning
|
|
114
|
+
// at 11 is not a leak here, and it prints over the panes.
|
|
115
|
+
renderer.setMaxListeners(0);
|
|
111
116
|
installResolutionEventBridge(renderer);
|
|
112
117
|
// Streamed quotes apply and notify on one clock of up to 10 Hz: every
|
|
113
118
|
// visible row stays live while a burst of ticks costs one terminal redraw,
|
|
@@ -40,6 +40,8 @@ import { resolveCurrencyUnit } from "../../utils/currency-units";
|
|
|
40
40
|
import { canonicalExchange, canonicalTickerKey, parsePublicTickerKey } from "../../utils/exchanges";
|
|
41
41
|
import { normalizePriceHistory, priceHistoryIntervalMs, reachesLatestSettledSession } from "../../utils/price-history";
|
|
42
42
|
import { createProviderMiss } from "../provider-errors";
|
|
43
|
+
import { assertSecRegistrantMatches } from "../sec-registrant";
|
|
44
|
+
import { nonUsSecListingVenue } from "../../utils/sec";
|
|
43
45
|
import { publicListingTarget } from "../listing-target";
|
|
44
46
|
import { canonicalHistoryInterval, HistoryRetentionError, parseHistoryRecoveryCandidate, parseHistoryRetention, type HistoryRetention } from "../history-retention";
|
|
45
47
|
import { getRouterEntityKey } from "../provider-router/cache";
|
|
@@ -195,7 +197,7 @@ function mapCloudPriceHistory(
|
|
|
195
197
|
`Cloud chart data is unavailable for ${ticker}`,
|
|
196
198
|
).map((point) => mapPricePoint(point, divisor, exchange)),
|
|
197
199
|
);
|
|
198
|
-
if (stale && !reachesLatestSettledSession(points, Date.now(), { exchange, intervalMs: priceHistoryIntervalMs(interval) })) {
|
|
200
|
+
if (stale && !reachesLatestSettledSession(points, Date.now(), { symbol: ticker, exchange, intervalMs: priceHistoryIntervalMs(interval) })) {
|
|
199
201
|
throw createProviderMiss(`Cloud chart data is stale for ${ticker}`);
|
|
200
202
|
}
|
|
201
203
|
if (
|
|
@@ -486,11 +488,30 @@ export class GloomberbCloudProvider implements AssetDataProvider {
|
|
|
486
488
|
);
|
|
487
489
|
}
|
|
488
490
|
|
|
489
|
-
async getSecFilings(ticker: string, count = 15): Promise<SecFilingItem[]> {
|
|
490
|
-
|
|
491
|
-
|
|
491
|
+
async getSecFilings(ticker: string, count = 15, exchange?: string, context?: MarketDataRequestContext): Promise<SecFilingItem[]> {
|
|
492
|
+
const venue = nonUsSecListingVenue(ticker, exchange);
|
|
493
|
+
const name = venue ? context?.listingName?.trim() || await this.listingName(ticker, venue) || undefined : undefined;
|
|
494
|
+
const filings = await withCloudFallback(async () => {
|
|
495
|
+
const response = await apiClient.getCloudSecFilings({ ticker, exchange, name, limit: count, offset: 0 });
|
|
492
496
|
return response.filings.map(mapCloudSecFiling);
|
|
493
497
|
}, `Cloud SEC filings are unavailable for ${ticker}`);
|
|
498
|
+
if (!venue || filings.length === 0) return filings;
|
|
499
|
+
const symbol = parsePublicTickerKey(ticker).symbol;
|
|
500
|
+
// Without the listing's company the filings cannot be told apart from another company's.
|
|
501
|
+
if (!name) throw createProviderMiss(`SEC filings for ${symbol} could not be matched to its ${venue} listing`);
|
|
502
|
+
assertSecRegistrantMatches(filings, { symbol, exchange: venue, name });
|
|
503
|
+
return filings;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** The company a listing belongs to, from its own quote; null when the quote prices another venue. */
|
|
507
|
+
private async listingName(ticker: string, venue: string): Promise<string | null> {
|
|
508
|
+
try {
|
|
509
|
+
const quote = await this.getQuote(ticker, venue);
|
|
510
|
+
const quoteVenue = canonicalExchange(quote.listingExchangeName || quote.exchangeName);
|
|
511
|
+
return quoteVenue === venue ? quote.name?.trim() || null : null;
|
|
512
|
+
} catch {
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
494
515
|
}
|
|
495
516
|
|
|
496
517
|
async getSecFilingDocuments(filing: SecFilingItem): Promise<SecFilingDocument[]> {
|