gloomberb 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/README.zh-CN.md +11 -11
- package/bin/{gloomberb → gloom} +3 -1
- package/package.json +6 -2
- package/src/account/checkout-handoff.tsx +225 -0
- package/src/account/device-signin-dialog.tsx +2 -2
- package/src/account/device-signin.ts +2 -2
- package/src/account/upgrade-dialog.tsx +1 -1
- package/src/api-client/askg.ts +2 -2
- package/src/api-client/auth.ts +2 -2
- package/src/api-client/central-bank-rates.ts +6 -0
- package/src/api-client/collections.ts +5 -1
- package/src/api-client/cot.ts +2 -0
- package/src/api-client/crypto-etf-flows.ts +37 -0
- package/src/api-client/crypto-markets.ts +60 -0
- package/src/api-client/data.ts +84 -5
- package/src/api-client/doe.ts +15 -0
- package/src/api-client/equity-screener.ts +28 -0
- package/src/api-client/exchange-announcements.ts +38 -0
- package/src/api-client/fund-facts.ts +39 -0
- package/src/api-client/futures-curve.ts +9 -1
- package/src/api-client/hiring.ts +301 -0
- package/src/api-client/index.ts +22 -5
- package/src/api-client/market-discovery.ts +14 -0
- package/src/api-client/members.ts +6 -0
- package/src/api-client/mna.ts +6 -0
- package/src/api-client/paths.ts +18 -1
- package/src/api-client/request.ts +21 -4
- package/src/api-client/short-side-publications.ts +37 -0
- package/src/api-client/socket.ts +64 -4
- package/src/api-client/swap-curve.ts +35 -0
- package/src/api-client/themes.ts +7 -1
- package/src/api-client/types.ts +90 -2
- package/src/app/pane-runtime/plugin-bindings.ts +9 -2
- package/src/app/runtime/desktop-deeplink.ts +5 -5
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +13 -0
- package/src/app/star-prompt/status-line.tsx +2 -2
- package/src/architecture/core-builtin-allowlist.json +5 -2
- package/src/architecture/ui-literals-allowlist.json +3 -3
- package/src/architecture/ui-tokens-allowlist.json +1 -1
- package/src/brokers/broker-portfolio-sync.ts +37 -0
- package/src/brokers/directory.ts +11 -0
- package/src/brokers/logos.ts +3 -1
- package/src/brokers/signed-in/adapter.ts +304 -26
- package/src/brokers/signed-in/client.ts +14 -2
- package/src/brokers/signed-in/connect.ts +10 -2
- package/src/brokers/sync-broker-instance.ts +9 -1
- package/src/capabilities/chart-series.ts +22 -6
- package/src/cli/bank-section.ts +1 -1
- package/src/cli/base-converter.ts +23 -14
- package/src/cli/central-bank-events.ts +1 -1
- package/src/cli/command-options.ts +59 -4
- package/src/cli/commands/api.ts +9 -6
- package/src/cli/commands/broker.ts +2 -2
- package/src/cli/commands/command-utils.ts +2 -2
- package/src/cli/commands/crypto-hints.ts +7 -20
- package/src/cli/commands/fred-series.ts +4 -2
- package/src/cli/commands/keybindings.ts +2 -2
- package/src/cli/commands/market.ts +1117 -264
- package/src/cli/commands/news-hints.ts +2 -2
- package/src/cli/commands/news-search.ts +59 -6
- package/src/cli/commands/options-leaps.ts +41 -26
- package/src/cli/commands/overview.ts +121 -48
- package/src/cli/commands/plugins.ts +9 -9
- package/src/cli/commands/remote.ts +13 -10
- package/src/cli/commands/search.ts +64 -44
- package/src/cli/commands/system.ts +27 -19
- package/src/cli/commands/themes.ts +1 -1
- package/src/cli/commands/ticker.ts +192 -47
- package/src/cli/context.ts +3 -2
- package/src/cli/desktop-pane-shot-view.ts +2 -2
- package/src/cli/desktop-pane-shot.ts +1 -1
- package/src/cli/earnings-calendar.ts +4 -4
- package/src/cli/entry.ts +18 -1
- package/src/cli/errors.ts +20 -2
- package/src/cli/exit-codes.ts +1 -1
- package/src/cli/export-source.ts +10 -4
- package/src/cli/freshness.ts +2 -8
- package/src/cli/fx-forward.ts +130 -0
- package/src/cli/fx-pair.ts +10 -9
- package/src/cli/glossary.ts +64 -20
- package/src/cli/help.ts +19 -13
- package/src/cli/history-export.ts +126 -0
- package/src/cli/history-rows.ts +196 -43
- package/src/cli/index-roots.ts +5 -45
- package/src/cli/index.ts +24 -18
- package/src/cli/known-gaps.ts +118 -25
- package/src/cli/listing-arg.ts +300 -41
- package/src/cli/name-entries.ts +30 -18
- package/src/cli/native-smoke.ts +2 -0
- package/src/cli/not-a-ticker.ts +19 -9
- package/src/cli/opentui-libc.ts +5 -0
- package/src/cli/options.ts +12 -0
- package/src/cli/pane-functions/capabilities.ts +75 -20
- package/src/cli/pane-functions/catalog.ts +24 -23
- package/src/cli/pane-functions/discovery.ts +1 -1
- package/src/cli/pane-functions/dom.ts +10 -7
- package/src/cli/pane-functions/financial-ratio-shot.ts +2 -2
- package/src/cli/pane-functions/freshness.ts +174 -23
- package/src/cli/pane-functions/function-help.ts +66 -27
- package/src/cli/pane-functions/headless.ts +24 -11
- package/src/cli/pane-functions/index.ts +18 -16
- package/src/cli/pane-functions/options.ts +22 -2
- package/src/cli/pane-functions/report-notices.ts +12 -4
- package/src/cli/pane-functions/report.ts +5 -5
- package/src/cli/pane-functions/resolver.ts +47 -10
- package/src/cli/pane-functions/screenshot-assessment.ts +322 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +152 -0
- package/src/cli/pane-functions/screenshot-chart-evidence.ts +396 -0
- package/src/cli/pane-functions/screenshot-data-evidence.ts +383 -0
- package/src/cli/pane-functions/screenshot-evidence.ts +1 -1
- package/src/cli/pane-functions/screenshot-payload.ts +453 -0
- package/src/cli/pane-functions/screenshot-render.ts +316 -0
- package/src/cli/pane-functions/screenshot-types.ts +162 -0
- package/src/cli/pane-functions/shot-options.ts +8 -3
- package/src/cli/peso-dollar-rates.ts +79 -0
- package/src/cli/quote-answer.ts +38 -3
- package/src/cli/report-tables.ts +61 -16
- package/src/cli/restore-plugins.ts +29 -14
- package/src/cli/result.ts +111 -22
- package/src/cli/series-search.ts +5 -5
- package/src/cli/statement-filings.ts +19 -0
- package/src/cli/suffixed-listing-rows.ts +49 -0
- package/src/cli/symbol-args.ts +50 -15
- package/src/cli/symbol-cells.ts +120 -0
- package/src/cli/symbol-list.ts +198 -68
- package/src/cli/symbol-rows.ts +131 -25
- package/src/cli/ticker-resolution.ts +108 -11
- package/src/cli/treasury-yields.ts +5 -5
- package/src/cli/types.ts +2 -0
- package/src/cli/uncovered-instrument.ts +3 -3
- package/src/cli/unknown-command.ts +6 -6
- package/src/components/chart/composite/chart-layout.ts +131 -0
- package/src/components/chart/composite/composite-chart.tsx +373 -16
- package/src/components/chart/composite/interactions.ts +7 -2
- package/src/components/chart/composite/legend.tsx +75 -3
- package/src/components/chart/composite/levels.ts +5 -0
- package/src/components/chart/composite/panel-gestures.ts +41 -0
- package/src/components/chart/composite/panel-labels.ts +2 -1
- package/src/components/chart/composite/panel-surface.tsx +305 -11
- package/src/components/chart/composite/price-axis-labels.tsx +27 -3
- package/src/components/chart/composite/rasterizer.ts +44 -19
- package/src/components/chart/composite/scene.ts +16 -4
- package/src/components/chart/composite/text-renderer.ts +48 -21
- package/src/components/chart/composite/toolbar.tsx +52 -5
- package/src/components/chart/composite/types.ts +13 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +120 -13
- package/src/components/chart/composite/use-composite-value-scales.ts +44 -0
- package/src/components/chart/composite/use-composite-viewport.ts +12 -3
- package/src/components/chart/composite/value-scale.ts +149 -0
- package/src/components/chart/composite/volume-profile-paint.ts +6 -3
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart-table/index.ts +2 -0
- package/src/components/chart-table/read.tsx +74 -0
- package/src/components/command-bar/commands/collection-list.ts +41 -19
- package/src/components/command-bar/commands/collection.ts +9 -3
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/commands/direct/runtime.ts +3 -2
- package/src/components/command-bar/pane-templates/items.ts +59 -6
- package/src/components/command-bar/pane-templates/workflow.ts +10 -1
- package/src/components/command-bar/routes/root/plugin-install.ts +1 -1
- package/src/components/command-bar/routes/root/provider-search.ts +42 -11
- package/src/components/command-bar/routes/root/results.ts +18 -4
- package/src/components/command-bar/routes/root/runtime.ts +15 -3
- package/src/components/command-bar/routes/root/search-providers.ts +25 -2
- package/src/components/command-bar/routes/root/selection.ts +6 -1
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +4 -1
- package/src/components/command-bar/routes/root/shortcuts.ts +30 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +73 -4
- package/src/components/command-bar/selection-runtime.ts +50 -10
- package/src/components/command-bar/surface/index.tsx +24 -2
- package/src/components/command-bar/view-model.ts +7 -0
- package/src/components/command-bar/workflow/broker.ts +2 -2
- package/src/components/command-bar/workflow/collection-actions.ts +46 -7
- package/src/components/command-bar/workflow/collection-ticker.ts +32 -4
- package/src/components/command-bar/workflow/fields.ts +8 -2
- package/src/components/command-bar/workflow/ops.ts +18 -4
- package/src/components/command-bar/workflow/portfolio-position.ts +53 -4
- package/src/components/command-bar/workflow/submit.ts +3 -2
- package/src/components/command-bar/workflow/tickers.ts +5 -1
- package/src/components/company-logo.tsx +39 -0
- package/src/components/data-table/sections.ts +4 -2
- package/src/components/form-modal/confirm.tsx +2 -1
- package/src/components/form-modal/request.ts +5 -0
- package/src/components/form-modal/routes.ts +4 -1
- package/src/components/index.ts +12 -6
- package/src/components/layout/header.tsx +7 -6
- package/src/components/layout/market-summary.ts +9 -6
- package/src/components/layout/pane/capture-status.ts +1 -1
- package/src/components/layout/pane/footer/model.ts +11 -5
- package/src/components/layout/shell/chrome.ts +19 -6
- package/src/components/layout/shell/index.tsx +2 -1
- package/src/components/layout/shell/pane/layers.tsx +19 -1
- package/src/components/layout/status-bar.tsx +2 -2
- package/src/components/market-board/index.tsx +11 -3
- package/src/components/onboarding/onboarding-wizard.tsx +1 -0
- package/src/components/onboarding/portfolio-step/broker-setup-panel.tsx +2 -2
- package/src/components/onboarding/wizard-broker-sync.ts +4 -1
- package/src/components/pane-settings-dialog/desktop.tsx +20 -7
- package/src/components/pane-settings-dialog/tui.tsx +17 -9
- package/src/components/pane-settings-dialog/value.ts +8 -1
- package/src/components/pane-settings-dialog.tsx +44 -13
- package/src/components/sign-in-code-panel.tsx +27 -19
- package/src/components/ui/column-grid.tsx +48 -4
- package/src/components/ui/country-flag-art.tsx +180 -0
- package/src/components/ui/country-flag.tsx +118 -12
- package/src/components/ui/data-table/opentui/index.tsx +61 -2
- package/src/components/ui/data-table/opentui/model.ts +109 -2
- package/src/components/ui/data-table/types.ts +1 -1
- package/src/components/ui/display.tsx +5 -1
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/logo-mark.tsx +11 -2
- package/src/components/ui/query-bar.tsx +1 -1
- package/src/components/ui/row-notes.ts +79 -0
- package/src/core/state/app/layout.ts +4 -4
- package/src/data/cached-query.ts +8 -1
- package/src/data/config/chart-settings.ts +3 -3
- package/src/data/config/home.ts +10 -2
- package/src/data/config/layout.ts +4 -1
- package/src/data/config/store/node.ts +4 -0
- package/src/data/config/store/normalize.ts +13 -3
- package/src/data/config/store/portfolio-as-of-column.ts +2 -2
- package/src/data/json-storage.ts +2 -0
- package/src/data/saved-copies.ts +84 -0
- package/src/docs/snapshot.json +65 -32
- package/src/i18n/es.ts +29 -12
- package/src/i18n/ja.ts +29 -12
- package/src/i18n/ko.ts +29 -12
- package/src/i18n/zh-cn.ts +29 -12
- package/src/i18n/zh-tw.ts +29 -12
- package/src/layout/desks.ts +1 -1
- package/src/layout/launch-layout.ts +1 -1
- package/src/layout/pane-manager/floating-actions.ts +5 -3
- package/src/layout/pane-manager/floating.ts +43 -1
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/layout/selected-ticker.ts +74 -0
- package/src/market-data/depositary-pair.ts +251 -0
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +124 -40
- package/src/market-data/fx-closes.ts +17 -2
- package/src/market-data/hooks.tsx +19 -11
- package/src/market-data/market/change-basis.ts +49 -7
- package/src/market-data/market/freshness.ts +34 -5
- package/src/market-data/market/period-return.ts +163 -0
- package/src/market-data/market/trading-sessions.ts +13 -0
- package/src/market-data/market/year-to-date.ts +8 -13
- package/src/market-data/performance.ts +20 -14
- package/src/market-data/perpetual-premium.ts +32 -0
- package/src/market-data/published-apac-sessions.ts +2 -1
- package/src/market-data/published-futures-sessions.ts +69 -0
- package/src/market-data/quotes/contributions.ts +5 -1
- package/src/market-data/quotes/freshness.ts +42 -0
- package/src/market-data/quotes/intraday-bar.ts +37 -0
- package/src/market-data/quotes/regular-session-valuation.ts +13 -8
- package/src/market-data/quotes/resolution.ts +4 -2
- package/src/market-data/tax-equivalent.ts +1 -1
- package/src/market-data/ticker-price-returns.ts +3 -1
- package/src/news/aggregator.ts +5 -1
- package/src/news/news-model.ts +4 -0
- package/src/news/types.ts +11 -0
- package/src/notifications/app-notifier.ts +1 -1
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/pane.tsx +9 -8
- package/src/plugins/builtin/alerts/alert-engine.ts +29 -19
- package/src/plugins/builtin/alerts/calendar-events.ts +378 -0
- package/src/plugins/builtin/alerts/cli.ts +485 -76
- package/src/plugins/builtin/alerts/command.ts +5 -10
- package/src/plugins/builtin/alerts/event-rows.ts +9 -5
- package/src/plugins/builtin/alerts/events-pane.tsx +71 -56
- package/src/plugins/builtin/alerts/events.ts +107 -5
- package/src/plugins/builtin/alerts/fired-log.ts +78 -0
- package/src/plugins/builtin/alerts/format.ts +2 -1
- package/src/plugins/builtin/alerts/headless.ts +100 -39
- package/src/plugins/builtin/alerts/history-pane.tsx +105 -62
- package/src/plugins/builtin/alerts/history-rows.ts +89 -0
- package/src/plugins/builtin/alerts/index.tsx +45 -18
- package/src/plugins/builtin/alerts/iv-level.ts +365 -0
- package/src/plugins/builtin/alerts/levels.ts +3 -3
- package/src/plugins/builtin/alerts/pane.tsx +97 -29
- package/src/plugins/builtin/alerts/price.ts +35 -0
- package/src/plugins/builtin/alerts/quotes.ts +24 -0
- package/src/plugins/builtin/alerts/research-builder.ts +84 -11
- package/src/plugins/builtin/alerts/research-rules.ts +76 -3
- package/src/plugins/builtin/alerts/scheduled-check.ts +206 -32
- package/src/plugins/builtin/alerts/scheduled-sources.ts +26 -3
- package/src/plugins/builtin/alerts/scheduled.ts +188 -29
- package/src/plugins/builtin/alerts/storage.ts +13 -10
- package/src/plugins/builtin/alerts/targets.ts +12 -3
- package/src/plugins/builtin/analytics/index.tsx +8 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -1
- package/src/plugins/builtin/analytics/risk-book.ts +215 -0
- package/src/plugins/builtin/analytics/risk-client.ts +13 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +55 -21
- package/src/plugins/builtin/analytics/risk-math.ts +6 -3
- package/src/plugins/builtin/analytics/risk-model.ts +297 -104
- package/src/plugins/builtin/analytics/risk-options.ts +17 -2
- package/src/plugins/builtin/analytics/risk-pane.tsx +97 -36
- package/src/plugins/builtin/attention/pane.tsx +6 -2
- package/src/plugins/builtin/awards/headless.ts +7 -3
- package/src/plugins/builtin/awards/model.ts +18 -0
- package/src/plugins/builtin/awards/pane.tsx +6 -3
- package/src/plugins/builtin/backtest/headless.ts +3 -3
- package/src/plugins/builtin/backtest/rules.ts +41 -5
- package/src/plugins/builtin/broker-manager/add-flow.tsx +12 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +47 -19
- package/src/plugins/builtin/broker-manager/footer.ts +27 -11
- package/src/plugins/builtin/broker-manager/index.tsx +21 -12
- package/src/plugins/builtin/broker-manager/keyboard.ts +1 -1
- package/src/plugins/builtin/broker-manager/model.ts +12 -2
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +183 -57
- package/src/plugins/builtin/broker-manager/table.ts +28 -12
- package/src/plugins/builtin/broker-trading/account-picker.tsx +2 -1
- package/src/plugins/builtin/broker-trading/chart-levels.ts +82 -13
- package/src/plugins/builtin/broker-trading/controller.ts +45 -13
- package/src/plugins/builtin/broker-trading/dock.tsx +22 -4
- package/src/plugins/builtin/broker-trading/headless.ts +2 -1
- package/src/plugins/builtin/broker-trading/index.tsx +7 -1
- package/src/plugins/builtin/broker-trading/linked-orders.ts +148 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +75 -7
- package/src/plugins/builtin/broker-trading/orders.tsx +109 -31
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +9 -3
- package/src/plugins/builtin/broker-trading/pane-model.ts +30 -2
- package/src/plugins/builtin/broker-trading/pane.tsx +110 -23
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +36 -7
- package/src/plugins/builtin/broker-trading/ticket.tsx +112 -31
- package/src/plugins/builtin/buildout/cells.tsx +4 -0
- package/src/plugins/builtin/buildout/detail/index.tsx +5 -1
- package/src/plugins/builtin/buildout/detail/ui.tsx +7 -4
- package/src/plugins/builtin/buildout/pane/index.tsx +25 -12
- package/src/plugins/builtin/buildout/pane/status.tsx +0 -4
- package/src/plugins/builtin/builtin-plugin-meta.ts +1 -1
- package/src/plugins/builtin/catalysts/detail.tsx +3 -2
- package/src/plugins/builtin/catalysts/index.tsx +1 -1
- package/src/plugins/builtin/catalysts/model.ts +49 -4
- package/src/plugins/builtin/catalysts/pane.tsx +6 -8
- package/src/plugins/builtin/central-bank-rates/client.ts +5 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +36 -10
- package/src/plugins/builtin/central-bank-rates/model.ts +33 -8
- package/src/plugins/builtin/changelog/index.tsx +1 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +2 -1
- package/src/plugins/builtin/chart-composer/chart-spec.ts +7 -0
- package/src/plugins/builtin/chart-composer/cli-options.ts +2 -5
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/editor/controller.ts +2 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +4 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +28 -26
- package/src/plugins/builtin/chart-composer/headless.ts +253 -35
- package/src/plugins/builtin/chart-composer/index.tsx +12 -2
- package/src/plugins/builtin/chart-composer/leverage-overlay.ts +142 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +127 -28
- package/src/plugins/builtin/chart-composer/series-catalog.ts +1 -0
- package/src/plugins/builtin/chart-composer/series-expression.ts +65 -6
- package/src/plugins/builtin/chart-composer/session-history.ts +15 -21
- package/src/plugins/builtin/chart-composer/session-range.ts +4 -2
- package/src/plugins/builtin/chart-composer/settings.ts +31 -19
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +5 -6
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +18 -8
- package/src/plugins/builtin/chat/attachments/model.ts +3 -1
- package/src/plugins/builtin/chat/content/index.tsx +1 -1
- package/src/plugins/builtin/chat/pane-links/open.ts +1 -1
- package/src/plugins/builtin/chat/people.ts +1 -1
- package/src/plugins/builtin/clinical-trials/client.ts +5 -2
- package/src/plugins/builtin/clinical-trials/model.ts +13 -4
- package/src/plugins/builtin/clinical-trials/pane.tsx +32 -12
- package/src/plugins/builtin/clinical-trials/ticker-sponsor.ts +17 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +1 -1
- package/src/plugins/builtin/cloud/askg/lock-note.ts +1 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +3 -3
- package/src/plugins/builtin/cloud/team/pane-sections.tsx +105 -47
- package/src/plugins/builtin/cloud/team/pane-ui.tsx +42 -4
- package/src/plugins/builtin/cloud/team/pane.tsx +204 -64
- package/src/plugins/builtin/cloud/thesis/store.ts +45 -22
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/commodities-energy/index.tsx +29 -2
- package/src/plugins/builtin/commodities-energy/view-state.ts +2 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +11 -4
- package/src/plugins/builtin/company-attention/app-rank.tsx +7 -5
- package/src/plugins/builtin/company-attention/building-model.ts +222 -0
- package/src/plugins/builtin/company-attention/building.tsx +172 -0
- package/src/plugins/builtin/company-attention/client.ts +117 -1
- package/src/plugins/builtin/company-attention/evidence.ts +16 -3
- package/src/plugins/builtin/company-attention/headless.ts +101 -5
- package/src/plugins/builtin/company-attention/index.tsx +6 -3
- package/src/plugins/builtin/company-attention/model.ts +33 -7
- package/src/plugins/builtin/company-attention/moves-model.ts +253 -0
- package/src/plugins/builtin/company-attention/moves.tsx +159 -0
- package/src/plugins/builtin/company-attention/pane.tsx +79 -23
- package/src/plugins/builtin/company-attention/signals-model.ts +229 -0
- package/src/plugins/builtin/company-attention/signals.tsx +160 -0
- package/src/plugins/builtin/company-kpis/headless.ts +3 -2
- package/src/plugins/builtin/company-kpis/model.ts +2 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +1 -1
- package/src/plugins/builtin/composite-plugins.ts +2 -1
- package/src/plugins/builtin/congress-trades/headless.ts +1 -1
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +5 -3
- package/src/plugins/builtin/cot/headless.ts +28 -6
- package/src/plugins/builtin/cot/model.ts +12 -0
- package/src/plugins/builtin/cot/pane.tsx +3 -2
- package/src/plugins/builtin/cpi/headless.ts +5 -1
- package/src/plugins/builtin/cpi/pane.tsx +11 -9
- package/src/plugins/builtin/credit-boards/model.ts +2 -0
- package/src/plugins/builtin/credit-documents/headless.ts +1 -1
- package/src/plugins/builtin/crypto-board/client.ts +86 -0
- package/src/plugins/builtin/crypto-board/defi-view.tsx +218 -0
- package/src/plugins/builtin/crypto-board/defi.ts +239 -0
- package/src/plugins/builtin/crypto-board/headless.ts +117 -6
- package/src/plugins/builtin/crypto-board/index.tsx +8 -3
- package/src/plugins/builtin/crypto-board/model.ts +40 -8
- package/src/plugins/builtin/crypto-board/pane.tsx +55 -21
- package/src/plugins/builtin/crypto-board/series.ts +19 -1
- package/src/plugins/builtin/crypto-etf-flows/client.ts +60 -0
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +132 -0
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +44 -0
- package/src/plugins/builtin/crypto-etf-flows/model.ts +121 -0
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +193 -0
- package/src/plugins/builtin/debug/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/docs/index.tsx +1 -1
- package/src/plugins/builtin/docs/pane.tsx +2 -2
- package/src/plugins/builtin/docs/targets.ts +1 -1
- package/src/plugins/builtin/doe/client.ts +5 -1
- package/src/plugins/builtin/doe/headless.ts +12 -6
- package/src/plugins/builtin/doe/model.ts +43 -6
- package/src/plugins/builtin/doe/pane.tsx +18 -11
- package/src/plugins/builtin/earnings/board-model.ts +13 -6
- package/src/plugins/builtin/earnings/board-table.ts +4 -1
- package/src/plugins/builtin/earnings/board.tsx +253 -50
- package/src/plugins/builtin/earnings/calendar-model.ts +188 -0
- package/src/plugins/builtin/earnings/calendar.tsx +338 -0
- package/src/plugins/builtin/earnings/client.ts +4 -3
- package/src/plugins/builtin/earnings/headless.ts +53 -15
- package/src/plugins/builtin/earnings/history-model.ts +53 -36
- package/src/plugins/builtin/earnings/index.tsx +15 -22
- package/src/plugins/builtin/earnings/model.ts +17 -12
- package/src/plugins/builtin/earnings/scope.ts +89 -0
- package/src/plugins/builtin/earnings-calls/calendar.tsx +310 -0
- package/src/plugins/builtin/earnings-calls/data.ts +146 -2
- package/src/plugins/builtin/earnings-calls/headless.ts +151 -9
- package/src/plugins/builtin/earnings-calls/index.tsx +3 -3
- package/src/plugins/builtin/earnings-calls/lock-note.ts +1 -1
- package/src/plugins/builtin/earnings-calls/pane.tsx +149 -31
- package/src/plugins/builtin/earnings-calls/upcoming.ts +195 -0
- package/src/plugins/builtin/earnings-ripple/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +132 -20
- package/src/plugins/builtin/econ/detail-view.tsx +48 -10
- package/src/plugins/builtin/econ/fred-catalog.ts +23 -6
- package/src/plugins/builtin/econ/fred-series-map.ts +4 -0
- package/src/plugins/builtin/econ/index.tsx +112 -25
- package/src/plugins/builtin/econ/print-watch.ts +2 -1
- package/src/plugins/builtin/econ/types.ts +32 -1
- package/src/plugins/builtin/econ-statistics/client.ts +16 -3
- package/src/plugins/builtin/econ-statistics/defs.ts +4 -0
- package/src/plugins/builtin/econ-statistics/detail.tsx +2 -2
- package/src/plugins/builtin/econ-statistics/headless.ts +13 -2
- package/src/plugins/builtin/econ-statistics/index.tsx +3 -3
- package/src/plugins/builtin/econ-statistics/pane.tsx +2 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +103 -0
- package/src/plugins/builtin/econ-statistics/view.ts +16 -1
- package/src/plugins/builtin/equity-screener/client.ts +21 -3
- package/src/plugins/builtin/equity-screener/headless.ts +68 -6
- package/src/plugins/builtin/equity-screener/live.ts +1 -1
- package/src/plugins/builtin/equity-screener/model.ts +6 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +45 -10
- package/src/plugins/builtin/equity-screener/screen-check.ts +90 -0
- package/src/plugins/builtin/equity-screener/ticker-check.tsx +148 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -1
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/model.ts +8 -10
- package/src/plugins/builtin/exposure/headless.ts +51 -6
- package/src/plugins/builtin/exposure/index.tsx +28 -2
- package/src/plugins/builtin/exposure/model.ts +7 -0
- package/src/plugins/builtin/exposure/pane.tsx +6 -1
- package/src/plugins/builtin/fear-greed/index.tsx +1 -1
- package/src/plugins/builtin/filing-events/index.tsx +1 -1
- package/src/plugins/builtin/futures/model.ts +10 -9
- package/src/plugins/builtin/futures/returns.ts +8 -36
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +40 -9
- package/src/plugins/builtin/futures-curve/headless.ts +39 -17
- package/src/plugins/builtin/futures-curve/model.ts +258 -69
- package/src/plugins/builtin/futures-curve/pane.tsx +46 -17
- package/src/plugins/builtin/fx-matrix/client.ts +15 -8
- package/src/plugins/builtin/fx-matrix/headless.ts +32 -14
- package/src/plugins/builtin/fx-matrix/index.tsx +13 -11
- package/src/plugins/builtin/fx-matrix/live-legs.ts +22 -0
- package/src/plugins/builtin/fx-matrix/settings.ts +2 -1
- package/src/plugins/builtin/gpu/headless.ts +9 -4
- package/src/plugins/builtin/help/index.tsx +13 -3
- package/src/plugins/builtin/holders/beneficial-model.ts +8 -11
- package/src/plugins/builtin/holders/beneficial-report.ts +6 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +13 -1
- package/src/plugins/builtin/holders/format.ts +28 -17
- package/src/plugins/builtin/holders/headless.ts +46 -7
- package/src/plugins/builtin/holders/index-holders.ts +264 -0
- package/src/plugins/builtin/holders/pane.tsx +79 -15
- package/src/plugins/builtin/holders/report-rows.ts +35 -7
- package/src/plugins/builtin/holders/table-model.ts +2 -1
- package/src/plugins/builtin/holders/treemap.tsx +2 -2
- package/src/plugins/builtin/insider/headless.ts +1 -1
- package/src/plugins/builtin/insider/signals-client.ts +1 -1
- package/src/plugins/builtin/insider/signals.tsx +1 -1
- package/src/plugins/builtin/ipo-calendar/pane.tsx +7 -4
- package/src/plugins/builtin/iv-history/client.ts +20 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -4
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/iv-history/model.ts +13 -4
- package/src/plugins/builtin/iv-history/series.ts +3 -1
- package/src/plugins/builtin/jobs/lock-note.ts +1 -1
- package/src/plugins/builtin/jobs/model.ts +4 -15
- package/src/plugins/builtin/jobs/pane.tsx +7 -5
- package/src/plugins/builtin/jobs/share-bars.tsx +11 -5
- package/src/plugins/builtin/jodi/pane.tsx +10 -4
- package/src/plugins/builtin/layout-manager/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +20 -7
- package/src/plugins/builtin/macro-day/index.tsx +3 -2
- package/src/plugins/builtin/macro-day/model.ts +29 -8
- package/src/plugins/builtin/macro-day/pane.tsx +46 -10
- package/src/plugins/builtin/macro-day/releases.ts +55 -13
- package/src/plugins/builtin/market-heatmap/data.ts +9 -2
- package/src/plugins/builtin/market-heatmap/evidence.ts +1 -1
- package/src/plugins/builtin/market-heatmap/headless.ts +9 -6
- package/src/plugins/builtin/market-heatmap/index.tsx +3 -3
- package/src/plugins/builtin/market-heatmap/model.ts +10 -7
- package/src/plugins/builtin/market-movers/client.ts +33 -19
- package/src/plugins/builtin/market-movers/headless.ts +8 -2
- package/src/plugins/builtin/market-movers/index.tsx +16 -10
- package/src/plugins/builtin/market-movers/screener.ts +29 -8
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -2
- package/src/plugins/builtin/market-movers/session-table.ts +4 -2
- package/src/plugins/builtin/market-movers/table.ts +4 -1
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/view.ts +5 -0
- package/src/plugins/builtin/members/headless.ts +6 -5
- package/src/plugins/builtin/members/pane.tsx +11 -4
- package/src/plugins/builtin/mna/client.ts +1 -0
- package/src/plugins/builtin/mna/detail.tsx +20 -32
- package/src/plugins/builtin/mna/distress/detail.tsx +16 -4
- package/src/plugins/builtin/mna/distress/model.ts +3 -2
- package/src/plugins/builtin/mna/distress/pane.tsx +7 -4
- package/src/plugins/builtin/mna/headless.ts +6 -13
- package/src/plugins/builtin/mna/model.ts +93 -15
- package/src/plugins/builtin/mna/pane.tsx +5 -4
- package/src/plugins/builtin/news/headless.ts +12 -6
- package/src/plugins/builtin/news/index.tsx +10 -1
- package/src/plugins/builtin/news/wire/index.tsx +3 -2
- package/src/plugins/builtin/news/wire/news/command-bar-search.ts +26 -10
- package/src/plugins/builtin/news/wire/news/query-presets.ts +6 -2
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -3
- package/src/plugins/builtin/notes/cli.ts +49 -14
- package/src/plugins/builtin/openfda/pane.tsx +1 -1
- package/src/plugins/builtin/options/carry.ts +2 -2
- package/src/plugins/builtin/options/index.tsx +1 -1
- package/src/plugins/builtin/options/view.tsx +10 -10
- package/src/plugins/builtin/options-calculator/headless.ts +46 -7
- package/src/plugins/builtin/options-scenario/client.ts +123 -28
- package/src/plugins/builtin/options-scenario/collar.ts +8 -6
- package/src/plugins/builtin/options-scenario/csp-screen-headless.ts +127 -0
- package/src/plugins/builtin/options-scenario/csp-screen-pane.tsx +165 -0
- package/src/plugins/builtin/options-scenario/csp-screen.ts +258 -0
- package/src/plugins/builtin/options-scenario/csp.ts +101 -21
- package/src/plugins/builtin/options-scenario/headless.ts +36 -15
- package/src/plugins/builtin/options-scenario/hedge.ts +20 -14
- package/src/plugins/builtin/options-scenario/index.tsx +28 -3
- package/src/plugins/builtin/options-scenario/model.ts +13 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +9 -5
- package/src/plugins/builtin/perps/equity-row.tsx +11 -3
- package/src/plugins/builtin/perps/freshness.ts +8 -5
- package/src/plugins/builtin/perps/headless.ts +3 -1
- package/src/plugins/builtin/perps/list-perpetuals.ts +25 -4
- package/src/plugins/builtin/perps/live-rows.ts +161 -0
- package/src/plugins/builtin/perps/markets-section.tsx +154 -0
- package/src/plugins/builtin/perps/pane.tsx +36 -17
- package/src/plugins/builtin/perps/venue-markets.ts +96 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +143 -59
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +72 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +158 -141
- package/src/plugins/builtin/portfolio-list/cli/render.ts +49 -20
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +3 -3
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +29 -24
- package/src/plugins/builtin/portfolio-list/headless.ts +6 -3
- package/src/plugins/builtin/portfolio-list/income.ts +13 -2
- package/src/plugins/builtin/portfolio-list/index.tsx +9 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +21 -8
- package/src/plugins/builtin/portfolio-list/pane/purchase-date-fx.ts +46 -0
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +16 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +2 -15
- package/src/plugins/builtin/power/client.ts +4 -1
- package/src/plugins/builtin/power/evidence.ts +22 -7
- package/src/plugins/builtin/power/gas.tsx +5 -1
- package/src/plugins/builtin/power/pane.tsx +8 -1
- package/src/plugins/builtin/power/prices.tsx +10 -3
- package/src/plugins/builtin/research/analyst-headless.ts +25 -8
- package/src/plugins/builtin/research/analyst-model.ts +68 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +63 -14
- package/src/plugins/builtin/research/event-model.ts +3 -1
- package/src/plugins/builtin/research/event-sources.ts +12 -4
- package/src/plugins/builtin/research/index.tsx +2 -1
- package/src/plugins/builtin/research/relative-valuation-basis.ts +58 -0
- package/src/plugins/builtin/research/relative-valuation-columns.ts +31 -2
- package/src/plugins/builtin/research/relative-valuation-currency.ts +12 -5
- package/src/plugins/builtin/research/relative-valuation-headless.ts +84 -26
- package/src/plugins/builtin/research/relative-valuation-model.ts +88 -19
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +76 -9
- package/src/plugins/builtin/research/relative-valuation-peers.ts +1 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +6 -2
- package/src/plugins/builtin/risk-factors/index.tsx +2 -2
- package/src/plugins/builtin/scanner/lock-note.ts +1 -1
- package/src/plugins/builtin/sec/forms.ts +13 -0
- package/src/plugins/builtin/sec/fund-abroad.ts +32 -0
- package/src/plugins/builtin/sec/fund-facts.ts +68 -8
- package/src/plugins/builtin/sec/headless.ts +85 -8
- package/src/plugins/builtin/sec/index.tsx +58 -12
- package/src/plugins/builtin/sectors/client.ts +2 -1
- package/src/plugins/builtin/sectors/sector-model.ts +11 -15
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/broker-reconnect.ts +107 -22
- package/src/plugins/builtin/shared/cloud-upgrade.ts +34 -6
- package/src/plugins/builtin/shared/earnings-calendar.ts +375 -0
- package/src/plugins/builtin/{earnings/estimate-basis.ts → shared/earnings-estimate-basis.ts} +1 -1
- package/src/plugins/builtin/shared/earnings-report.ts +3 -3
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +23 -1
- package/src/plugins/builtin/shared/job-posting.ts +129 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +3 -3
- package/src/plugins/builtin/shared/report-freshness.ts +3 -0
- package/src/plugins/builtin/shared/research-trading.tsx +21 -0
- package/src/plugins/builtin/shared/series-cache.ts +2 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +2 -1
- package/src/plugins/builtin/short-interest/client.ts +2 -0
- package/src/plugins/builtin/short-interest/headless.ts +41 -12
- package/src/plugins/builtin/short-interest/index.tsx +23 -1
- package/src/plugins/builtin/short-interest/model.ts +70 -19
- package/src/plugins/builtin/short-interest/pane.tsx +19 -2
- package/src/plugins/builtin/short-interest/publications-client.ts +82 -0
- package/src/plugins/builtin/short-interest/publications-headless.ts +29 -0
- package/src/plugins/builtin/short-interest/publications-model.ts +50 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +66 -0
- package/src/plugins/builtin/short-interest/schedule.ts +35 -2
- package/src/plugins/builtin/short-interest/surface.tsx +11 -4
- package/src/plugins/builtin/short-interest/types.ts +9 -0
- package/src/plugins/builtin/short-interest/watch-client.ts +14 -8
- package/src/plugins/builtin/short-interest/watch-model.ts +12 -25
- package/src/plugins/builtin/short-interest/watch-pane.tsx +5 -1
- package/src/plugins/builtin/supply-chain/flow.tsx +33 -9
- package/src/plugins/builtin/supply-chain/model.ts +51 -3
- package/src/plugins/builtin/supply-chain/pane.tsx +78 -39
- package/src/plugins/builtin/supply-chain/row-evidence.tsx +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -5
- package/src/plugins/builtin/themes/model.ts +14 -4
- package/src/plugins/builtin/themes/pane.tsx +24 -5
- package/src/plugins/builtin/thirteenf/headless.ts +5 -5
- package/src/plugins/builtin/thirteenf/signals.ts +3 -1
- package/src/plugins/builtin/ticker-detail/adr-pair/headless.ts +123 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/model.ts +132 -0
- package/src/plugins/builtin/ticker-detail/adr-pair/tab.tsx +87 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +40 -26
- package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +8 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +67 -3
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +112 -5
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +17 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +21 -7
- package/src/plugins/builtin/ticker-detail/financials/model.ts +36 -1
- package/src/plugins/builtin/ticker-detail/financials/offerings.ts +56 -0
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +62 -13
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +30 -4
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +14 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +148 -35
- package/src/plugins/builtin/ticker-detail/index.tsx +37 -5
- package/src/plugins/builtin/ticker-detail/overview/model.ts +65 -10
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +9 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +68 -11
- package/src/plugins/builtin/ticker-detail/pane.tsx +11 -0
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +8 -3
- package/src/plugins/builtin/ticker-detail/research-tabs.ts +11 -0
- package/src/plugins/builtin/vol-surface/client.ts +5 -4
- package/src/plugins/builtin/vol-surface/headless.ts +12 -3
- package/src/plugins/builtin/vol-surface/model.ts +4 -2
- package/src/plugins/builtin/volatility/model.ts +5 -10
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +4 -3
- package/src/plugins/builtin/world-venue-map/basemap.ts +3 -1
- package/src/plugins/builtin/world-venue-map/chokepoint-chart.ts +40 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +90 -11
- package/src/plugins/builtin/world-venue-map/headless.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -26
- package/src/plugins/builtin/world-venue-map/layers.ts +1 -1
- package/src/plugins/builtin/world-venue-map/map.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/pane.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +15 -4
- package/src/plugins/builtin/yield-curve/client.ts +25 -0
- package/src/plugins/builtin/yield-curve/curves.ts +7 -4
- package/src/plugins/builtin/yield-curve/headless.ts +38 -4
- package/src/plugins/builtin/yield-curve/history.ts +4 -3
- package/src/plugins/builtin/yield-curve/index.tsx +12 -6
- package/src/plugins/builtin/yield-curve/swaps-model.ts +93 -0
- package/src/plugins/builtin/yield-curve/swaps.tsx +99 -0
- package/src/plugins/bundle.ts +1 -1
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/compat.ts +3 -3
- package/src/plugins/dependencies.ts +75 -14
- package/src/plugins/extracted-plugins.ts +132 -34
- package/src/plugins/host-link.ts +149 -34
- package/src/plugins/installer.ts +35 -10
- package/src/plugins/loader.ts +206 -38
- package/src/plugins/manager-node.ts +2 -2
- package/src/plugins/marketplace/deactivation.ts +22 -0
- package/src/plugins/marketplace/model.ts +2 -2
- package/src/plugins/marketplace/packs.ts +1 -1
- package/src/plugins/ownership.ts +1 -1
- package/src/plugins/peer-retry.ts +155 -0
- package/src/plugins/registry/contributions.ts +3 -1
- package/src/plugins/registry/index.ts +4 -3
- package/src/plugins/registry/plugin-state.ts +3 -0
- package/src/plugins/seed-notice.ts +20 -0
- package/src/plugins/shortcut-argument.ts +39 -0
- package/src/portfolio/allocation.ts +1 -1
- package/src/portfolio/collection-name.ts +31 -0
- package/src/portfolio/column-values.ts +10 -8
- package/src/portfolio/cost-fx.ts +296 -19
- package/src/portfolio/manual-lots.ts +75 -0
- package/src/portfolio/mutations.ts +60 -22
- package/src/portfolio/suffixed-listings.ts +209 -0
- package/src/portfolio/totals-currency.ts +24 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +14 -0
- package/src/public/time-series.ts +11 -8
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/config-host.ts +3 -0
- package/src/renderers/browser/main.tsx +23 -3
- package/src/renderers/dom/boot-frame-page.ts +187 -0
- package/src/renderers/dom/boot-frame.ts +237 -0
- package/src/renderers/dom/build-assets.ts +46 -8
- package/src/renderers/dom/dom-ui-host.tsx +4 -29
- package/src/renderers/dom/host/ascii-text.ts +16 -2
- package/src/renderers/dom/host/box.tsx +43 -2
- package/src/renderers/dom/host/chart-surface.tsx +2 -0
- package/src/renderers/dom/host/hls.chunk.ts +3 -0
- package/src/renderers/dom/host/image-surface.tsx +49 -0
- package/src/renderers/dom/host/media-surface.tsx +24 -18
- package/src/renderers/dom/host/mouse.ts +30 -0
- package/src/renderers/dom/host/size-observer.ts +1 -1
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/styles.css +76 -0
- package/src/renderers/dom/test-utils.tsx +2 -1
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -3
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +3 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +46 -3
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +1 -1
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +9 -3
- package/src/renderers/electrobun/bun/desktop/initialization.ts +81 -18
- package/src/renderers/electrobun/bun/external-plugins.ts +29 -7
- package/src/renderers/electrobun/bun/index.ts +11 -1
- package/src/renderers/electrobun/bun/window/boot-frame.ts +67 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -1
- package/src/renderers/electrobun/shared/boot-frame.ts +7 -0
- package/src/renderers/electrobun/shared/protocol.ts +6 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/config-host.ts +3 -0
- package/src/renderers/electrobun/view/fatal-screen.tsx +1 -1
- package/src/renderers/electrobun/view/main.tsx +30 -4
- package/src/renderers/electrobun/view/news-source.ts +5 -5
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -1
- package/src/renderers/opentui/browser-open.ts +88 -0
- package/src/renderers/opentui/host.tsx +5 -14
- package/src/renderers/opentui/image/loader.ts +3 -2
- package/src/renderers/opentui/native-smoke.ts +10 -1
- package/src/renderers/opentui/pane-image/index.ts +2 -1
- package/src/renderers/opentui/render-lib.ts +253 -0
- package/src/renderers/opentui/render-timing-smoke.ts +1 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/share/layout-view.tsx +2 -2
- package/src/renderers/share/main.tsx +4 -4
- package/src/renderers/share/view.tsx +1 -1
- package/src/series/resolve.ts +22 -6
- package/src/series/standalone.ts +30 -2
- package/src/series/types.ts +8 -1
- package/src/shares/api.ts +4 -1
- package/src/shares/pane.ts +1 -1
- package/src/sources/gloomberb-cloud/fred-series.ts +46 -1
- package/src/sources/gloomberb-cloud/index.ts +32 -16
- package/src/sources/gloomberb-cloud/news.ts +39 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +14 -1
- package/src/sources/gloomberb-cloud/perpetuals.ts +49 -1
- package/src/sources/listing-symbols.ts +37 -0
- package/src/sources/provider-errors.ts +16 -2
- package/src/sources/provider-router/financial-routes.ts +21 -3
- package/src/sources/provider-router/financials.ts +15 -2
- package/src/sources/provider-router/history.ts +30 -8
- package/src/sources/provider-router/primary.ts +1 -1
- package/src/state/app/bootstrap.ts +23 -0
- package/src/state/hooks/inline-tickers.ts +30 -5
- package/src/sync/controller.ts +1 -1
- package/src/sync/core-contributors.ts +46 -14
- package/src/team/collections-sync.ts +2 -1
- package/src/team/collections.ts +178 -17
- package/src/telemetry/crash-reports.ts +17 -4
- package/src/test-support/builtin-panes.ts +1 -1
- package/src/theme/colors.ts +3 -30
- package/src/theme/ui-tokens.ts +37 -1
- package/src/tickers/company-name-listing.ts +210 -33
- package/src/tickers/index-roots.ts +47 -0
- package/src/tickers/instrument-label.ts +5 -1
- package/src/tickers/metadata.ts +10 -0
- package/src/tickers/perpetual-listing.ts +5 -2
- package/src/tickers/search/home-listing.ts +75 -0
- package/src/tickers/search/index.ts +76 -27
- package/src/tickers/search/ranking.ts +54 -4
- package/src/tickers/search/upsert.ts +29 -0
- package/src/tickers/terminal-codes.ts +416 -40
- package/src/time-series/bar-aggregation.ts +243 -0
- package/src/time-series/base-series.ts +307 -0
- package/src/time-series/chart-bounds.ts +349 -0
- package/src/time-series/chart-seed.ts +142 -0
- package/src/time-series/economic.ts +5 -0
- package/src/time-series/fundamentals.ts +18 -3
- package/src/time-series/history-acquisition.ts +499 -0
- package/src/time-series/leverage.ts +100 -0
- package/src/time-series/market-resolution.ts +4 -2
- package/src/time-series/market.ts +2 -1
- package/src/time-series/price-comparison.ts +175 -30
- package/src/time-series/range.ts +9 -1
- package/src/time-series/resolution.ts +174 -16
- package/src/time-series/resolve-context.ts +157 -0
- package/src/time-series/resolve.ts +126 -1577
- package/src/time-series/series-name.ts +38 -0
- package/src/time-series/series-presentation.ts +208 -0
- package/src/time-series/spec.ts +11 -6
- package/src/time-series/studies.ts +109 -12
- package/src/time-series/tail-reconcile.ts +121 -0
- package/src/time-series/types.ts +29 -2
- package/src/time-series/use-chart-resolution.ts +4 -5
- package/src/types/broker.ts +10 -0
- package/src/types/config.ts +14 -0
- package/src/types/data-provider.ts +14 -0
- package/src/types/exchange-rate.ts +6 -0
- package/src/types/financials.ts +104 -7
- package/src/types/headless.ts +76 -6
- package/src/types/instrument.ts +3 -0
- package/src/types/plugin.ts +65 -8
- package/src/types/price-history.ts +2 -0
- package/src/types/ticker.ts +13 -0
- package/src/types/trading.ts +59 -1
- package/src/ui/ascii-font.ts +13 -1
- package/src/ui/host.tsx +6 -1
- package/src/updater/command-names.ts +175 -0
- package/src/updater/index.ts +10 -5
- package/src/utils/calendar-date.ts +32 -15
- package/src/utils/cash-runway.ts +241 -0
- package/src/utils/central-banks.ts +42 -0
- package/src/utils/cli-output.ts +259 -80
- package/src/utils/contract-month.ts +16 -0
- package/src/utils/crypto-pair.ts +61 -3
- package/src/utils/currency-units.ts +29 -0
- package/src/utils/datetime-format.ts +10 -0
- package/src/utils/debug-log.ts +1 -1
- package/src/utils/decimal-comma.ts +39 -6
- package/src/utils/exchange-announcements.ts +71 -0
- package/src/utils/exchange-rate-snapshot.ts +10 -0
- package/src/utils/financial-statements.ts +83 -4
- package/src/utils/format.ts +34 -16
- package/src/utils/fundamentals.ts +150 -34
- package/src/utils/fx-market-hours.ts +10 -1
- package/src/utils/latest-financial-period.ts +8 -0
- package/src/utils/linux-libc.ts +54 -0
- package/src/utils/market-capitalization.ts +111 -15
- package/src/utils/max-drawdown.ts +64 -0
- package/src/utils/network-failure.ts +83 -0
- package/src/utils/option-expiry.ts +139 -7
- package/src/utils/price-earnings.ts +11 -5
- package/src/utils/price-history.ts +18 -8
- package/src/utils/price-window.ts +131 -0
- package/src/utils/release-date.ts +47 -0
- package/src/utils/sec.ts +3 -0
- package/src/utils/throttled-fetch.ts +11 -4
- package/src/utils/trailing-eps.ts +67 -0
- package/src/utils/typed-text.ts +21 -0
- package/src/utils/utc-time.ts +24 -1
- package/src/version.ts +6 -0
- package/src/cli/pane-functions/screenshot.ts +0 -2122
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
} from "../../../ui";
|
|
11
11
|
import { colors as themeColors } from "../../../theme/colors";
|
|
12
12
|
import { consumeChartMouseEvent, getGlobalMouseX, getLocalPlotPointer, type ChartMouseEvent } from "../core/pointer";
|
|
13
|
+
import { Button } from "../../ui/button";
|
|
14
|
+
import { clamp } from "../../../utils/math";
|
|
15
|
+
import { panValueRange, resolveAxisDragSpanFactor, zoomValueRange, type CompositeValueRange } from "./value-scale";
|
|
13
16
|
import { useStaticChartBitmapSize } from "./bitmap";
|
|
14
17
|
import { useMeasuredCells } from "../../../ui/measured-cells";
|
|
15
18
|
import { PriceAxisLabels, placeAxisTicks } from "./price-axis-labels";
|
|
@@ -57,16 +60,21 @@ import {
|
|
|
57
60
|
import { compositeRightOffsetRatio, unprojectCompositeTimestamp } from "./time-scale";
|
|
58
61
|
import { resolveCompositeCursorDate, unprojectCompositeValue } from "./scene";
|
|
59
62
|
import { compositeAxisTickLabels, renderCompositeAxisText, renderCompositePanelText } from "./text-renderer";
|
|
60
|
-
import type { CompositeChartColors, CompositeChartScene, CompositePanelScene } from "./types";
|
|
63
|
+
import type { CompositeAxisSide, CompositeChartColors, CompositeChartScene, CompositePanelScene } from "./types";
|
|
61
64
|
import { useCompositePanelBitmap } from "./panel-bitmap";
|
|
62
65
|
import { nextDrawingId, nextLevelId } from "./drawing-store";
|
|
63
66
|
import {
|
|
67
|
+
AXIS_DOUBLE_PRESS_MS,
|
|
68
|
+
PLOT_DOUBLE_CLICK_MS,
|
|
64
69
|
COMPOSITE_PANEL_ROLE,
|
|
65
70
|
isVerticalWheelDirection,
|
|
71
|
+
manualValueAxes,
|
|
66
72
|
startPanGesture,
|
|
67
73
|
releaseEditableFocus,
|
|
68
74
|
type PanGesture,
|
|
75
|
+
type PendingAxisWheel,
|
|
69
76
|
type PendingWheel,
|
|
77
|
+
type ValueAxisStart,
|
|
70
78
|
} from "./panel-gestures";
|
|
71
79
|
import { resolvePanelCrosshair, axisLabelRows, cursorAxisLabel, resolveSeriesCursorYRatio, resolveSeriesAxisTags } from "./panel-labels";
|
|
72
80
|
import type { KeyboardToolDrag } from "./use-composite-chart-keyboard";
|
|
@@ -78,6 +86,11 @@ const webFrame = globalThis as typeof globalThis & {
|
|
|
78
86
|
|
|
79
87
|
const NO_LEVELS: readonly ProjectedLevel[] = [];
|
|
80
88
|
|
|
89
|
+
/** The pointer's height in rows, to a fraction of one where the host reports it. */
|
|
90
|
+
function pointerRow(event: ChartMouseEvent): number {
|
|
91
|
+
return typeof event.preciseY === "number" ? event.preciseY : event.y;
|
|
92
|
+
}
|
|
93
|
+
|
|
81
94
|
interface CompositePanelSurfaceProps {
|
|
82
95
|
panel: CompositePanelScene;
|
|
83
96
|
scene: CompositeChartScene;
|
|
@@ -121,13 +134,41 @@ interface CompositePanelSurfaceProps {
|
|
|
121
134
|
showTextFallback: boolean;
|
|
122
135
|
/** Set while the owner is picking a bar: a press picks instead of panning. */
|
|
123
136
|
onPickTime?: (date: Date) => void;
|
|
137
|
+
/** Set while the owner is picking a price on the levels' series: a press picks the one under it. */
|
|
138
|
+
onPickPrice?: (value: number) => void;
|
|
124
139
|
/** The chart's levels when they draw on this panel. */
|
|
125
140
|
levels: CompositeChartLevels | null;
|
|
126
141
|
selectedLevelId: string | null;
|
|
127
142
|
onSelectLevel: (id: string | null) => void;
|
|
143
|
+
/** The value axes stretch and squeeze under a drag or the wheel, and a double click fits them again. */
|
|
144
|
+
valueScalable: boolean;
|
|
145
|
+
onSetValueScale: (panelId: string, side: CompositeAxisSide, key: string, range: CompositeValueRange) => void;
|
|
146
|
+
onResetValueScale: (panelId: string) => void;
|
|
147
|
+
/** The line above this panel, which a drag moves (desktop and web): null for the top panel. */
|
|
148
|
+
dividerAbove?: { active: boolean; gestures: PanelDividerGestures } | null;
|
|
149
|
+
/** A double click on bare plot gives this panel the whole chart, or gives the others back. */
|
|
150
|
+
onToggleMaximized?: () => void;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
interface PanelDividerGestures {
|
|
154
|
+
onMouseDown: (event: ChartMouseEvent) => void;
|
|
155
|
+
onMouseDrag: (event: ChartMouseEvent) => void;
|
|
156
|
+
onMouseUp: (event: ChartMouseEvent) => void;
|
|
157
|
+
onMouseDragEnd: (event: ChartMouseEvent) => void;
|
|
128
158
|
}
|
|
129
159
|
|
|
130
160
|
const DESKTOP_PLOT_STYLE = { flex: "1 1 0px", width: "auto", minWidth: 0, height: "auto", alignSelf: "stretch" } as const;
|
|
161
|
+
/** Over a level that drags, or while one does: it moves up and down only. */
|
|
162
|
+
const DESKTOP_PLOT_LEVEL_STYLE = { ...DESKTOP_PLOT_STYLE, cursor: "ns-resize" } as const;
|
|
163
|
+
const DESKTOP_PLOT_PICK_STYLE = { ...DESKTOP_PLOT_STYLE, cursor: "crosshair" } as const;
|
|
164
|
+
/** The grab strip over the line between two panels: the line and a few pixels either side of it. */
|
|
165
|
+
const PANEL_DIVIDER_STYLE = {
|
|
166
|
+
left: 0,
|
|
167
|
+
right: 0,
|
|
168
|
+
width: "auto",
|
|
169
|
+
top: "calc(-1 * var(--gloom-space-xs))",
|
|
170
|
+
height: "calc(2 * var(--gloom-space-xs) + 1px)",
|
|
171
|
+
} as const;
|
|
131
172
|
|
|
132
173
|
export function CompositePanelSurface({
|
|
133
174
|
panel,
|
|
@@ -162,9 +203,15 @@ export function CompositePanelSurface({
|
|
|
162
203
|
onPointerPress,
|
|
163
204
|
showTextFallback,
|
|
164
205
|
onPickTime,
|
|
206
|
+
onPickPrice,
|
|
165
207
|
levels,
|
|
166
208
|
selectedLevelId,
|
|
167
209
|
onSelectLevel,
|
|
210
|
+
valueScalable,
|
|
211
|
+
onSetValueScale,
|
|
212
|
+
onResetValueScale,
|
|
213
|
+
dividerAbove = null,
|
|
214
|
+
onToggleMaximized,
|
|
168
215
|
}: CompositePanelSurfaceProps) {
|
|
169
216
|
const isDesktopWeb = useUiCapabilities().nativePaneChrome === true;
|
|
170
217
|
const { cellHeightPx = 18, cellWidthPx = 8, fractionalViewport = false } = useUiCapabilities();
|
|
@@ -186,6 +233,8 @@ export function CompositePanelSurface({
|
|
|
186
233
|
const activeCursorYRatio = scene.cursorXRatio === null
|
|
187
234
|
? null
|
|
188
235
|
: heldCursorYRatio ?? seriesCursorYRatio;
|
|
236
|
+
// The last press on bare plot, for a double press where the host does not count clicks.
|
|
237
|
+
const lastPlotPressRef = useRef<{ at: number; x: number; y: number } | null>(null);
|
|
189
238
|
const dragRef = useRef<
|
|
190
239
|
| PanGesture
|
|
191
240
|
| {
|
|
@@ -302,6 +351,13 @@ export function CompositePanelSurface({
|
|
|
302
351
|
() => levels && levelDomain ? projectLevels(levels.items, levelDomain, levelDraft) : NO_LEVELS,
|
|
303
352
|
[levelDomain, levelDraft, levels],
|
|
304
353
|
);
|
|
354
|
+
// Over a line a plain drag moves, and while one moves, the pointer says it goes up and down.
|
|
355
|
+
const levelGrab = useMemo(() => {
|
|
356
|
+
if (levelDraft) return true;
|
|
357
|
+
if (!levels?.onEdit || cursorYRatio === null || onPickTime || onPickPrice || (armedTool && armedTool !== "level")) return false;
|
|
358
|
+
const hit = hitTestLevel(projectedLevels, cursorYRatio, levelGrabRatio(panel.height));
|
|
359
|
+
return !!hit?.editable && !!hit.draggable;
|
|
360
|
+
}, [armedTool, cursorYRatio, levelDraft, levels?.onEdit, onPickPrice, onPickTime, panel.height, projectedLevels]);
|
|
305
361
|
// Drawings project through the time scale alone: the crosshair moving,
|
|
306
362
|
// here or on a linked chart, must not repaint the plot, which the terminal's
|
|
307
363
|
// kitty surface would upload whole again.
|
|
@@ -569,6 +625,13 @@ export function CompositePanelSurface({
|
|
|
569
625
|
if (date) onPickTime(date);
|
|
570
626
|
return;
|
|
571
627
|
}
|
|
628
|
+
if (onPickPrice) {
|
|
629
|
+
// Only the levels' own panel has their prices; a press elsewhere picks nothing.
|
|
630
|
+
const ratios = pointerRatios(event);
|
|
631
|
+
const value = ratios && levelDomain ? unprojectCompositeValue(ratios.yRatio, levelDomain) : null;
|
|
632
|
+
if (value !== null && levelDomain) onPickPrice(roundLevelValue(value, levelDomain));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
572
635
|
// A keyboard-armed tool covers terminals that never forward modifier drags.
|
|
573
636
|
const tool = resolveChartToolKind(event.modifiers) ?? armedTool;
|
|
574
637
|
if (tool === "level" && levels?.onEdit && levelDomain) {
|
|
@@ -626,6 +689,7 @@ export function CompositePanelSurface({
|
|
|
626
689
|
// With no tool in hand, a press on a drawing or a level picks it so Backspace
|
|
627
690
|
// or Delete can remove it; the press still pans, and one on bare plot lets go.
|
|
628
691
|
const ratios = pointerRatios(event);
|
|
692
|
+
let bare = true;
|
|
629
693
|
if (ratios) {
|
|
630
694
|
const drawingHit = drawings.length > 0 ? hitTestDrawings(drawings, scene, panel, ratios, plotAspect) : null;
|
|
631
695
|
const levelHit = !drawingHit && levels?.onEdit && levelDomain
|
|
@@ -633,15 +697,46 @@ export function CompositePanelSurface({
|
|
|
633
697
|
: null;
|
|
634
698
|
onSelectDrawing(drawingHit ? drawingHit.drawing.id : null);
|
|
635
699
|
onSelectLevel(levelHit?.editable ? levelHit.id : null);
|
|
700
|
+
bare = !drawingHit && !levelHit;
|
|
701
|
+
// An order's line drags without the level tool; other levels keep the press for panning.
|
|
702
|
+
if (levelHit?.editable && levelHit.draggable) {
|
|
703
|
+
dragRef.current = { kind: "level-move", id: levelHit.id };
|
|
704
|
+
lastPlotPressRef.current = null;
|
|
705
|
+
updateCursor(event);
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
// A double click on bare plot gives the panel the whole chart, or the
|
|
710
|
+
// others back (the terminal counts two presses on one spot). Its first
|
|
711
|
+
// press must have landed here too: a double click on a button that goes
|
|
712
|
+
// away under it (All panels) ends on this plot, and is not one of its.
|
|
713
|
+
if (!bare) lastPlotPressRef.current = null;
|
|
714
|
+
if (onToggleMaximized && bare) {
|
|
715
|
+
const now = Date.now();
|
|
716
|
+
const last = lastPlotPressRef.current;
|
|
717
|
+
const double = typeof event.detail === "number"
|
|
718
|
+
? event.detail >= 2 && !!last && now - last.at < PLOT_DOUBLE_CLICK_MS
|
|
719
|
+
: !!last && now - last.at < AXIS_DOUBLE_PRESS_MS && Math.abs(last.x - event.x) <= 1 && Math.abs(last.y - event.y) <= 1;
|
|
720
|
+
lastPlotPressRef.current = double ? null : { at: now, x: event.x, y: event.y };
|
|
721
|
+
if (double) {
|
|
722
|
+
dragRef.current = null;
|
|
723
|
+
onToggleMaximized();
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
636
726
|
}
|
|
637
727
|
if (!updateCursor(event)) return;
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
728
|
+
const values = manualValueAxes(panel);
|
|
729
|
+
dragRef.current = {
|
|
730
|
+
...startPanGesture(
|
|
731
|
+
frame,
|
|
732
|
+
viewport,
|
|
733
|
+
plotSize.width,
|
|
734
|
+
getGlobalMouseX(event, renderer),
|
|
735
|
+
plotSpanFactor,
|
|
736
|
+
),
|
|
737
|
+
// A panel scaled by hand moves up and down with the drag as well.
|
|
738
|
+
...(values.length > 0 ? { startCellY: pointerRow(event), values } : {}),
|
|
739
|
+
};
|
|
645
740
|
}, [
|
|
646
741
|
armedTool,
|
|
647
742
|
drawings,
|
|
@@ -650,6 +745,7 @@ export function CompositePanelSurface({
|
|
|
650
745
|
levels,
|
|
651
746
|
onActivate,
|
|
652
747
|
onPickTime,
|
|
748
|
+
onPickPrice,
|
|
653
749
|
onPointerPress,
|
|
654
750
|
onSelectDrawing,
|
|
655
751
|
onSelectLevel,
|
|
@@ -665,6 +761,7 @@ export function CompositePanelSurface({
|
|
|
665
761
|
scene,
|
|
666
762
|
updateCursor,
|
|
667
763
|
viewport,
|
|
764
|
+
onToggleMaximized,
|
|
668
765
|
]);
|
|
669
766
|
const pressCursor = useCallback((event: ChartMouseEvent) => {
|
|
670
767
|
onActivate?.();
|
|
@@ -678,7 +775,11 @@ export function CompositePanelSurface({
|
|
|
678
775
|
if (drag.kind === "level-move") {
|
|
679
776
|
const ratios = pointerRatios(event);
|
|
680
777
|
const value = ratios && levelDomain ? unprojectCompositeValue(ratios.yRatio, levelDomain) : null;
|
|
681
|
-
if (value
|
|
778
|
+
if (value === null || !levelDomain) return;
|
|
779
|
+
const draft = { id: drag.id, value: roundLevelValue(value, levelDomain) };
|
|
780
|
+
// The release reads the ref, and a quick drag lets go before the next render.
|
|
781
|
+
levelDraftRef.current = draft;
|
|
782
|
+
setLevelDraft(draft);
|
|
682
783
|
return;
|
|
683
784
|
}
|
|
684
785
|
if (drag.kind === "edit") {
|
|
@@ -716,11 +817,19 @@ export function CompositePanelSurface({
|
|
|
716
817
|
(globalX - drag.startGlobalX) * drag.positionsPerCell,
|
|
717
818
|
{ frame: drag.frame, from: drag.startViewport },
|
|
718
819
|
);
|
|
820
|
+
if (drag.values && drag.startCellY !== undefined) {
|
|
821
|
+
const deltaRatio = (pointerRow(event) - drag.startCellY) / Math.max(plotSize.height, 1);
|
|
822
|
+
for (const axis of drag.values) {
|
|
823
|
+
onSetValueScale(panel.id, axis.side, axis.key, panValueRange(axis.start, axis.scale, deltaRatio));
|
|
824
|
+
}
|
|
825
|
+
}
|
|
719
826
|
}, [
|
|
720
827
|
frame,
|
|
721
828
|
levelDomain,
|
|
722
829
|
onEditDrawing,
|
|
723
830
|
onPanViewport,
|
|
831
|
+
onSetValueScale,
|
|
832
|
+
plotSize.height,
|
|
724
833
|
panel,
|
|
725
834
|
plotSize.width,
|
|
726
835
|
plotSpanFactor,
|
|
@@ -849,6 +958,136 @@ export function CompositePanelSurface({
|
|
|
849
958
|
updateCursor,
|
|
850
959
|
]);
|
|
851
960
|
|
|
961
|
+
// A value axis under the pointer: a drag stretches (up) or squeezes (down)
|
|
962
|
+
// it around its middle, the wheel around the pointer, and a double click
|
|
963
|
+
// fits it to the data again. Read through refs, so the handlers stay put.
|
|
964
|
+
const axisGestureRef = useRef<(ValueAxisStart & { startRow: number; moved: boolean }) | null>(null);
|
|
965
|
+
const lastAxisPressRef = useRef<{ side: CompositeAxisSide; at: number } | null>(null);
|
|
966
|
+
const latestAxesRef = useRef({ panel, onSetValueScale, onResetValueScale, onActivate });
|
|
967
|
+
latestAxesRef.current = { panel, onSetValueScale, onResetValueScale, onActivate };
|
|
968
|
+
/** The pointer's height down the panel, 0 at the top and 1 at the bottom. */
|
|
969
|
+
const axisPointerRatio = useCallback((event: ChartMouseEvent): number => {
|
|
970
|
+
const plot = plotRef.current as unknown as { absoluteY?: number; y?: number; height?: number } | null;
|
|
971
|
+
const top = plot?.absoluteY ?? plot?.y;
|
|
972
|
+
const height = plot?.height ?? 0;
|
|
973
|
+
if (top === undefined || height <= 1) return 0.5;
|
|
974
|
+
return clamp((pointerRow(event) - top) / (fractionalViewport ? height : height - 1), 0, 1);
|
|
975
|
+
}, [fractionalViewport]);
|
|
976
|
+
const pressAxis = useCallback((side: CompositeAxisSide, event: ChartMouseEvent) => {
|
|
977
|
+
const latest = latestAxesRef.current;
|
|
978
|
+
const domain = latest.panel.axes[side];
|
|
979
|
+
if (!domain?.scaleKey) return;
|
|
980
|
+
latest.onActivate?.();
|
|
981
|
+
consumeChartMouseEvent(event);
|
|
982
|
+
// The desktop counts clicks; the terminal has two presses close together.
|
|
983
|
+
const now = Date.now();
|
|
984
|
+
const last = lastAxisPressRef.current;
|
|
985
|
+
const double = typeof event.detail === "number"
|
|
986
|
+
? event.detail >= 2
|
|
987
|
+
: !!last && last.side === side && now - last.at < AXIS_DOUBLE_PRESS_MS;
|
|
988
|
+
if (double) {
|
|
989
|
+
lastAxisPressRef.current = null;
|
|
990
|
+
axisGestureRef.current = null;
|
|
991
|
+
latest.onResetValueScale(latest.panel.id);
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
lastAxisPressRef.current = { side, at: now };
|
|
995
|
+
axisGestureRef.current = {
|
|
996
|
+
side,
|
|
997
|
+
key: domain.scaleKey,
|
|
998
|
+
scale: domain.scale,
|
|
999
|
+
start: { min: domain.min, max: domain.max },
|
|
1000
|
+
startRow: pointerRow(event),
|
|
1001
|
+
moved: false,
|
|
1002
|
+
};
|
|
1003
|
+
}, []);
|
|
1004
|
+
const dragAxis = useCallback((event: ChartMouseEvent) => {
|
|
1005
|
+
const gesture = axisGestureRef.current;
|
|
1006
|
+
if (!gesture) return;
|
|
1007
|
+
consumeChartMouseEvent(event);
|
|
1008
|
+
const deltaPx = (pointerRow(event) - gesture.startRow) * cellHeightPx;
|
|
1009
|
+
if (!gesture.moved && Math.abs(deltaPx) < 1) return;
|
|
1010
|
+
// A drag is not the first half of a double click.
|
|
1011
|
+
gesture.moved = true;
|
|
1012
|
+
lastAxisPressRef.current = null;
|
|
1013
|
+
const latest = latestAxesRef.current;
|
|
1014
|
+
latest.onSetValueScale(
|
|
1015
|
+
latest.panel.id,
|
|
1016
|
+
gesture.side,
|
|
1017
|
+
gesture.key,
|
|
1018
|
+
zoomValueRange(gesture.start, gesture.scale, resolveAxisDragSpanFactor(deltaPx), 0.5),
|
|
1019
|
+
);
|
|
1020
|
+
}, [cellHeightPx]);
|
|
1021
|
+
const releaseAxis = useCallback(() => {
|
|
1022
|
+
axisGestureRef.current = null;
|
|
1023
|
+
}, []);
|
|
1024
|
+
const pendingAxisWheelRef = useRef<PendingAxisWheel | null>(null);
|
|
1025
|
+
const axisWheelFrameRef = useRef<number | null>(null);
|
|
1026
|
+
const flushAxisWheel = useCallback(() => {
|
|
1027
|
+
axisWheelFrameRef.current = null;
|
|
1028
|
+
const pending = pendingAxisWheelRef.current;
|
|
1029
|
+
pendingAxisWheelRef.current = null;
|
|
1030
|
+
const latest = latestAxesRef.current;
|
|
1031
|
+
const domain = pending ? latest.panel.axes[pending.side] : undefined;
|
|
1032
|
+
if (!pending || !domain?.scaleKey || pending.spanLog === 0) return;
|
|
1033
|
+
latest.onSetValueScale(
|
|
1034
|
+
latest.panel.id,
|
|
1035
|
+
pending.side,
|
|
1036
|
+
domain.scaleKey,
|
|
1037
|
+
zoomValueRange({ min: domain.min, max: domain.max }, domain.scale, Math.exp(pending.spanLog), pending.anchorRatio),
|
|
1038
|
+
);
|
|
1039
|
+
}, []);
|
|
1040
|
+
useEffect(() => () => {
|
|
1041
|
+
pendingAxisWheelRef.current = null;
|
|
1042
|
+
if (axisWheelFrameRef.current !== null) {
|
|
1043
|
+
webFrame.cancelAnimationFrame?.(axisWheelFrameRef.current);
|
|
1044
|
+
axisWheelFrameRef.current = null;
|
|
1045
|
+
}
|
|
1046
|
+
}, []);
|
|
1047
|
+
const wheelAxis = useCallback((side: CompositeAxisSide, event: ChartMouseEvent) => {
|
|
1048
|
+
const scroll = event.scroll;
|
|
1049
|
+
if (!scroll || !latestAxesRef.current.panel.axes[side]?.scaleKey) return;
|
|
1050
|
+
latestAxesRef.current.onActivate?.();
|
|
1051
|
+
consumeChartMouseEvent(event);
|
|
1052
|
+
if (!isVerticalWheelDirection(scroll.direction)) return;
|
|
1053
|
+
const pending = pendingAxisWheelRef.current?.side === side
|
|
1054
|
+
? pendingAxisWheelRef.current
|
|
1055
|
+
: { side, spanLog: 0, anchorRatio: 0.5 };
|
|
1056
|
+
// Up stretches, as Ctrl and the wheel zoom the plot in.
|
|
1057
|
+
pending.spanLog -= Math.log(resolveCompositeWheelZoom(scroll));
|
|
1058
|
+
pending.anchorRatio = axisPointerRatio(event);
|
|
1059
|
+
pendingAxisWheelRef.current = pending;
|
|
1060
|
+
if (!isDesktopWeb || typeof webFrame.requestAnimationFrame !== "function") {
|
|
1061
|
+
flushAxisWheel();
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
if (axisWheelFrameRef.current === null) {
|
|
1065
|
+
axisWheelFrameRef.current = webFrame.requestAnimationFrame(flushAxisWheel);
|
|
1066
|
+
}
|
|
1067
|
+
}, [axisPointerRatio, flushAxisWheel, isDesktopWeb]);
|
|
1068
|
+
const leftAxisGestures = useMemo(() => valueScalable ? {
|
|
1069
|
+
onMouseDown: (event: ChartMouseEvent) => pressAxis("left", event),
|
|
1070
|
+
onMouseDrag: dragAxis,
|
|
1071
|
+
onMouseUp: releaseAxis,
|
|
1072
|
+
onMouseDragEnd: releaseAxis,
|
|
1073
|
+
onMouseScroll: (event: ChartMouseEvent) => wheelAxis("left", event),
|
|
1074
|
+
} : undefined, [dragAxis, pressAxis, releaseAxis, valueScalable, wheelAxis]);
|
|
1075
|
+
const rightAxisGestures = useMemo(() => valueScalable ? {
|
|
1076
|
+
onMouseDown: (event: ChartMouseEvent) => pressAxis("right", event),
|
|
1077
|
+
onMouseDrag: dragAxis,
|
|
1078
|
+
onMouseUp: releaseAxis,
|
|
1079
|
+
onMouseDragEnd: releaseAxis,
|
|
1080
|
+
onMouseScroll: (event: ChartMouseEvent) => wheelAxis("right", event),
|
|
1081
|
+
} : undefined, [dragAxis, pressAxis, releaseAxis, valueScalable, wheelAxis]);
|
|
1082
|
+
// While the panel is scaled by hand, the foot of the axis scaled says so
|
|
1083
|
+
// and is the way back.
|
|
1084
|
+
const manuallyScaled = !!panel.axes.left?.manual || !!panel.axes.right?.manual;
|
|
1085
|
+
const manualSide: CompositeAxisSide | null = !valueScalable || !manuallyScaled ? null
|
|
1086
|
+
: panel.axes.right?.manual && rightAxisWidth > 0 ? "right"
|
|
1087
|
+
: panel.axes.left?.manual && leftAxisWidth > 0 ? "left"
|
|
1088
|
+
: rightAxisWidth > 0 ? "right" : leftAxisWidth > 0 ? "left" : null;
|
|
1089
|
+
const manualLabel = (manualSide === "left" ? leftAxisWidth : rightAxisWidth) >= 4 ? "Auto" : "A";
|
|
1090
|
+
|
|
852
1091
|
return (
|
|
853
1092
|
<Box
|
|
854
1093
|
flexDirection="row"
|
|
@@ -860,6 +1099,23 @@ export function CompositePanelSurface({
|
|
|
860
1099
|
// follows it by CSS. At rest, the size the cells give it.
|
|
861
1100
|
style={isDesktopWeb ? { width: "100%", flex: `${panel.height} 1 calc(${panel.height} * var(--cell-h))`, height: "auto", minHeight: 0 } : undefined}
|
|
862
1101
|
>
|
|
1102
|
+
{dividerAbove && isDesktopWeb ? (
|
|
1103
|
+
// A line too thin to grab, so the handle straddles it, as a pane
|
|
1104
|
+
// sidebar's does; it draws only while the pointer is on it.
|
|
1105
|
+
<Box
|
|
1106
|
+
position="absolute"
|
|
1107
|
+
left={0}
|
|
1108
|
+
top={0}
|
|
1109
|
+
height={1}
|
|
1110
|
+
zIndex={29}
|
|
1111
|
+
style={PANEL_DIVIDER_STYLE}
|
|
1112
|
+
{...dividerAbove.gestures}
|
|
1113
|
+
title="Drag to resize the panels, double-click for the default split"
|
|
1114
|
+
data-gloom-interactive="true"
|
|
1115
|
+
data-gloom-role="composite-chart-panel-divider"
|
|
1116
|
+
data-active={dividerAbove.active ? "true" : undefined}
|
|
1117
|
+
/>
|
|
1118
|
+
) : null}
|
|
863
1119
|
{measureReadout ? (
|
|
864
1120
|
<Box
|
|
865
1121
|
position="absolute"
|
|
@@ -900,6 +1156,8 @@ export function CompositePanelSurface({
|
|
|
900
1156
|
extraMarkers={leftAxisMarkers}
|
|
901
1157
|
seriesTags={isDesktopWeb ? seriesAxisTags.filter((tag) => tag.side === "left") : undefined}
|
|
902
1158
|
measuredPixelHeight={plotSize.height * cellHeightPx}
|
|
1159
|
+
gestures={leftAxisGestures}
|
|
1160
|
+
footButton={manualSide === "left"}
|
|
903
1161
|
/>
|
|
904
1162
|
<Box width={axisGap} />
|
|
905
1163
|
</>
|
|
@@ -910,7 +1168,7 @@ export function CompositePanelSurface({
|
|
|
910
1168
|
width={plotSize.width}
|
|
911
1169
|
height={plotSize.height}
|
|
912
1170
|
// Desktop: the width the axes leave, and the row's height.
|
|
913
|
-
style={isDesktopWeb ? DESKTOP_PLOT_STYLE : undefined}
|
|
1171
|
+
style={isDesktopWeb ? levelGrab ? DESKTOP_PLOT_LEVEL_STYLE : onPickPrice ? DESKTOP_PLOT_PICK_STYLE : DESKTOP_PLOT_STYLE : undefined}
|
|
914
1172
|
flexDirection="column"
|
|
915
1173
|
bitmaps={bitmapLayers}
|
|
916
1174
|
crosshair={crosshair}
|
|
@@ -922,11 +1180,12 @@ export function CompositePanelSurface({
|
|
|
922
1180
|
onMouseDragEnd={interactive && navigable ? releasePlot : undefined}
|
|
923
1181
|
onMouseScroll={interactive && navigable ? panFromWheel : undefined}
|
|
924
1182
|
onMouseOut={interactive ? clearCursor : undefined}
|
|
925
|
-
cursor={interactive ? toolDrag || !navigable || onPickTime ? "crosshair" : "grab" : undefined}
|
|
1183
|
+
cursor={interactive ? levelGrab ? "ns-resize" : toolDrag || !navigable || onPickTime || onPickPrice ? "crosshair" : "grab" : undefined}
|
|
926
1184
|
data-gloom-interactive={interactive ? "true" : undefined}
|
|
927
1185
|
data-gloom-role={COMPOSITE_PANEL_ROLE}
|
|
928
1186
|
data-gloom-remote-kind={remoteKind}
|
|
929
1187
|
data-gloom-label={panel.label ?? panel.id}
|
|
1188
|
+
data-gloom-value-scale={manuallyScaled ? "manual" : undefined}
|
|
930
1189
|
>
|
|
931
1190
|
{textLines.map((line, index) => <Text key={index} fg={colors.text}>{line}</Text>)}
|
|
932
1191
|
</ChartSurface>
|
|
@@ -970,9 +1229,44 @@ export function CompositePanelSurface({
|
|
|
970
1229
|
extraMarkers={rightAxisMarkers}
|
|
971
1230
|
seriesTags={isDesktopWeb ? seriesAxisTags.filter((tag) => tag.side === "right") : undefined}
|
|
972
1231
|
measuredPixelHeight={plotSize.height * cellHeightPx}
|
|
1232
|
+
gestures={rightAxisGestures}
|
|
1233
|
+
footButton={manualSide === "right"}
|
|
973
1234
|
/>
|
|
974
1235
|
</>
|
|
975
1236
|
) : null}
|
|
1237
|
+
{manualSide ? (
|
|
1238
|
+
<Box
|
|
1239
|
+
position="absolute"
|
|
1240
|
+
left={manualSide === "left"
|
|
1241
|
+
? 0
|
|
1242
|
+
: leftAxisWidth + (leftAxisWidth ? axisGap : 0) + plotWidth + axisGap + Math.max(0, rightAxisWidth - manualLabel.length)}
|
|
1243
|
+
top={Math.max(0, panel.height - 1)}
|
|
1244
|
+
width={manualLabel.length}
|
|
1245
|
+
height={1}
|
|
1246
|
+
zIndex={26}
|
|
1247
|
+
style={isDesktopWeb
|
|
1248
|
+
? {
|
|
1249
|
+
left: manualSide === "left" ? 0 : "auto",
|
|
1250
|
+
right: manualSide === "right" ? 0 : "auto",
|
|
1251
|
+
top: "auto",
|
|
1252
|
+
bottom: "var(--gloom-space-xs)",
|
|
1253
|
+
width: "auto",
|
|
1254
|
+
height: "auto",
|
|
1255
|
+
}
|
|
1256
|
+
: undefined}
|
|
1257
|
+
data-gloom-role="composite-chart-value-scale"
|
|
1258
|
+
>
|
|
1259
|
+
<Button
|
|
1260
|
+
label="Auto Scale"
|
|
1261
|
+
displayLabel={manualLabel}
|
|
1262
|
+
title="Values scaled by hand. Fit them to the data again (or double-click the axis)."
|
|
1263
|
+
variant="secondary"
|
|
1264
|
+
compact
|
|
1265
|
+
stopPropagation
|
|
1266
|
+
onPress={() => onResetValueScale(panel.id)}
|
|
1267
|
+
/>
|
|
1268
|
+
</Box>
|
|
1269
|
+
) : null}
|
|
976
1270
|
</Box>
|
|
977
1271
|
);
|
|
978
1272
|
}
|
|
@@ -4,6 +4,7 @@ import { colors } from "../../../theme/colors";
|
|
|
4
4
|
import { clamp } from "../../../utils/math";
|
|
5
5
|
import type { SeriesAxisTag } from "./panel-labels";
|
|
6
6
|
import { placeSeriesAxisTags, SeriesAxisTags } from "./series-axis-tags";
|
|
7
|
+
import type { ChartMouseEvent } from "../core/pointer";
|
|
7
8
|
|
|
8
9
|
function formatAxisCell(label: string | null, width: number): string {
|
|
9
10
|
if (width <= 0) return "";
|
|
@@ -39,6 +40,21 @@ interface PriceAxisLabelsProps {
|
|
|
39
40
|
/** Desktop/web observations, separate from a drawing tool's endpoint. */
|
|
40
41
|
seriesTags?: readonly SeriesAxisTag[];
|
|
41
42
|
measuredPixelHeight?: number;
|
|
43
|
+
/** A value axis the pointer stretches and squeezes: a drag or the wheel on it, a double click back. */
|
|
44
|
+
gestures?: PriceAxisGestures;
|
|
45
|
+
/** A button sits at the foot of the axis (Auto, while scaled by hand): tick labels make room for it. */
|
|
46
|
+
footButton?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The button at the foot of an axis sits this far above its bottom edge (`--gloom-space-xs`). */
|
|
50
|
+
const FOOT_BUTTON_INSET_PX = 4;
|
|
51
|
+
|
|
52
|
+
interface PriceAxisGestures {
|
|
53
|
+
onMouseDown: (event: ChartMouseEvent) => void;
|
|
54
|
+
onMouseDrag: (event: ChartMouseEvent) => void;
|
|
55
|
+
onMouseUp: (event: ChartMouseEvent) => void;
|
|
56
|
+
onMouseDragEnd: (event: ChartMouseEvent) => void;
|
|
57
|
+
onMouseScroll: (event: ChartMouseEvent) => void;
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
interface CursorPriceAxisOverlay {
|
|
@@ -141,8 +157,10 @@ export function PriceAxisLabels({
|
|
|
141
157
|
extraMarkers,
|
|
142
158
|
seriesTags,
|
|
143
159
|
measuredPixelHeight,
|
|
160
|
+
gestures,
|
|
161
|
+
footButton = false,
|
|
144
162
|
}: PriceAxisLabelsProps) {
|
|
145
|
-
const { cellHeightPx = 18, fractionalViewport = false } = useUiCapabilities();
|
|
163
|
+
const { cellHeightPx = 18, fractionalViewport = false, nativePaneChrome } = useUiCapabilities();
|
|
146
164
|
const overlay = useMemo(() => buildCursorPriceAxisOverlay({
|
|
147
165
|
axisWidth,
|
|
148
166
|
axisSectionWidth,
|
|
@@ -168,6 +186,7 @@ export function PriceAxisLabels({
|
|
|
168
186
|
...(usePixelOverlay ? [(overlay.topPercent! / 100) * (pixelHeight - 1)] : []),
|
|
169
187
|
...(visibleMarkers?.map((marker) => marker.pixelY) ?? []),
|
|
170
188
|
...placedSeriesTags.map((tag) => tag.centerY),
|
|
189
|
+
...(footButton ? [pixelHeight - FOOT_BUTTON_INSET_PX - cellHeightPx / 2] : []),
|
|
171
190
|
],
|
|
172
191
|
})
|
|
173
192
|
: null;
|
|
@@ -196,6 +215,7 @@ export function PriceAxisLabels({
|
|
|
196
215
|
)
|
|
197
216
|
);
|
|
198
217
|
|
|
218
|
+
const placedStyle = usePixelOverlay || usePixelTicks ? { position: "relative", height: "auto", alignSelf: "stretch" } : undefined;
|
|
199
219
|
return (
|
|
200
220
|
<Box
|
|
201
221
|
width={axisSectionWidth}
|
|
@@ -204,7 +224,11 @@ export function PriceAxisLabels({
|
|
|
204
224
|
overflow="hidden"
|
|
205
225
|
// Labels placed in percentages follow the row's height as a resize
|
|
206
226
|
// draws the chart at a new size between renders.
|
|
207
|
-
style={
|
|
227
|
+
style={gestures && nativePaneChrome ? { ...placedStyle, cursor: "ns-resize" } : placedStyle}
|
|
228
|
+
{...gestures}
|
|
229
|
+
data-gloom-interactive={gestures ? "true" : undefined}
|
|
230
|
+
data-gloom-role={side ? "composite-chart-value-axis" : undefined}
|
|
231
|
+
data-gloom-side={side}
|
|
208
232
|
>
|
|
209
233
|
{Array.from({ length: height }, (_, row) => {
|
|
210
234
|
const isCursorRow = !usePixelOverlay && cursorLabel !== null && cursorRow === row;
|
|
@@ -213,7 +237,7 @@ export function PriceAxisLabels({
|
|
|
213
237
|
: extraMarkers?.find((entry) => entry.row === row);
|
|
214
238
|
const label = isCursorRow
|
|
215
239
|
? cursorLabel
|
|
216
|
-
: marker?.label ?? (usePixelTicks ? null : axisLabels.get(row) ?? null);
|
|
240
|
+
: marker?.label ?? (usePixelTicks || (footButton && row === height - 1) ? null : axisLabels.get(row) ?? null);
|
|
217
241
|
return (
|
|
218
242
|
<Box key={row} height={1}>
|
|
219
243
|
{renderAxisLabel(
|
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
CompositeProjectedSeries,
|
|
28
28
|
} from "./types";
|
|
29
29
|
import { clamp } from "../../../utils/math";
|
|
30
|
+
import { clipSegmentToBand } from "./value-scale";
|
|
30
31
|
|
|
31
32
|
interface RenderCompositePanelBitmapOptions {
|
|
32
33
|
pixelWidth: number;
|
|
@@ -45,18 +46,29 @@ const PRIOR_CLOSE_DOT_PIXELS = 2;
|
|
|
45
46
|
const PRIOR_CLOSE_GAP_PIXELS = 3;
|
|
46
47
|
const PRIOR_CLOSE_OPACITY = 0.7;
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Where a point falls in the bitmap. An axis fitted to the data holds every
|
|
51
|
+
* point; one scaled by hand can put points past the edges, which `keepY` keeps
|
|
52
|
+
* there for the drawing to clip, rather than flattening them onto the edge.
|
|
53
|
+
*/
|
|
54
|
+
function pixelPoint(point: CompositeProjectedPoint, width: number, height: number, keepY = false): { x: number; y: number } {
|
|
55
|
+
const y = point.yRatio * Math.max(height - 1, 0);
|
|
49
56
|
return {
|
|
50
57
|
x: clamp(point.xRatio * Math.max(width - 1, 0), 0, Math.max(width - 1, 0)),
|
|
51
|
-
y:
|
|
58
|
+
y: keepY ? y : clamp(y, 0, Math.max(height - 1, 0)),
|
|
52
59
|
};
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
function pixelY(value: number, domain: CompositeAxisDomain, height: number): number | null {
|
|
56
63
|
const ratio = projectCompositeValue(value, domain);
|
|
57
|
-
|
|
64
|
+
if (ratio === null) return null;
|
|
65
|
+
const y = ratio * Math.max(height - 1, 0);
|
|
66
|
+
return domain.manual ? y : clamp(y, 0, Math.max(height - 1, 0));
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
/** Rows past the bitmap's edges a clipped stroke still reaches, so its end is not cut square. */
|
|
70
|
+
const CLIP_MARGIN_PIXELS = 4;
|
|
71
|
+
|
|
60
72
|
const AREA_FILL_MAX_OPACITY = 0.3;
|
|
61
73
|
const AREA_FILL_MIN_OPACITY = 0.02;
|
|
62
74
|
|
|
@@ -270,7 +282,8 @@ function drawConnectedSeries(
|
|
|
270
282
|
area: boolean,
|
|
271
283
|
cue?: SeriesLineCue,
|
|
272
284
|
): void {
|
|
273
|
-
const
|
|
285
|
+
const manual = domain.manual === true;
|
|
286
|
+
const points = series.points.map((point) => pixelPoint(point, width, height, manual));
|
|
274
287
|
if (points.length === 0) return;
|
|
275
288
|
const baseline = pixelY(0, domain, height) ?? height - 1;
|
|
276
289
|
const step = series.source.style === "step" || series.source.interpolation === "step-after";
|
|
@@ -278,22 +291,23 @@ function drawConnectedSeries(
|
|
|
278
291
|
if (area) fillAreaGradient(data, width, height, series, points, baseline, step, color);
|
|
279
292
|
|
|
280
293
|
const stroke = cue ? new DashedStroke(data, width, height, color, cue) : null;
|
|
294
|
+
// A hand-scaled axis can send a segment far past the plot: only the part
|
|
295
|
+
// near it is stroked, so a dash pattern never walks the rest.
|
|
296
|
+
const segment = (x0: number, y0: number, x1: number, y1: number, thickness: number) => {
|
|
297
|
+
const clipped = manual ? clipSegmentToBand(x0, y0, x1, y1, -CLIP_MARGIN_PIXELS, height - 1 + CLIP_MARGIN_PIXELS) : [x0, y0, x1, y1] as const;
|
|
298
|
+
if (!clipped) return;
|
|
299
|
+
if (stroke) stroke.segment(clipped[0], clipped[1], clipped[2], clipped[3]);
|
|
300
|
+
else drawLine(data, width, height, clipped[0], clipped[1], clipped[2], clipped[3], color, thickness);
|
|
301
|
+
};
|
|
281
302
|
for (let index = 1; index < points.length; index += 1) {
|
|
282
303
|
const previous = points[index - 1]!;
|
|
283
304
|
const current = points[index]!;
|
|
284
305
|
if (series.points[index]?.breakBefore) continue;
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
stroke.segment(current.x, previous.y, current.x, current.y);
|
|
289
|
-
} else {
|
|
290
|
-
stroke.segment(previous.x, previous.y, current.x, current.y);
|
|
291
|
-
}
|
|
292
|
-
} else if (step) {
|
|
293
|
-
drawLine(data, width, height, previous.x, previous.y, current.x, previous.y, color, 1.4);
|
|
294
|
-
drawLine(data, width, height, current.x, previous.y, current.x, current.y, color, 1.4);
|
|
306
|
+
if (step) {
|
|
307
|
+
segment(previous.x, previous.y, current.x, previous.y, 1.4);
|
|
308
|
+
segment(current.x, previous.y, current.x, current.y, 1.4);
|
|
295
309
|
} else {
|
|
296
|
-
|
|
310
|
+
segment(previous.x, previous.y, current.x, current.y, 1.5);
|
|
297
311
|
}
|
|
298
312
|
}
|
|
299
313
|
|
|
@@ -429,7 +443,7 @@ function drawColumns(
|
|
|
429
443
|
const baseline = pixelY(0, domain, height) ?? height - 1;
|
|
430
444
|
for (const projected of series.points) {
|
|
431
445
|
const fill = projected.value < 0 ? negativeColor : color;
|
|
432
|
-
const point = pixelPoint(projected, width, height);
|
|
446
|
+
const point = pixelPoint(projected, width, height, domain.manual);
|
|
433
447
|
const geometry = columnPixelGeometry(projected, width, layout, widthByFamily);
|
|
434
448
|
fillRect(
|
|
435
449
|
data,
|
|
@@ -583,12 +597,23 @@ export function renderCompositePanelBitmap(
|
|
|
583
597
|
fillBand(data, width, height, series, domain, color);
|
|
584
598
|
drawConnectedSeries(data, width, height, series, domain, color, false, cue);
|
|
585
599
|
break;
|
|
586
|
-
case "points":
|
|
600
|
+
case "points": {
|
|
601
|
+
// Like candles, a point owns its full mark at the viewport edge.
|
|
602
|
+
// Reserve its radius and antialias fringe instead of clipping half a disc.
|
|
603
|
+
const radius = Math.min(2.4, (width - 1) / 2, (height - 1) / 2);
|
|
604
|
+
const insetX = Math.min(Math.ceil(radius + 1), (width - 1) / 2);
|
|
605
|
+
const insetY = Math.min(Math.ceil(radius + 1), (height - 1) / 2);
|
|
587
606
|
for (const point of series.points) {
|
|
588
|
-
|
|
589
|
-
|
|
607
|
+
// Inset only visible values: a manual axis must not pull an
|
|
608
|
+
// out-of-range observation back onto the plot's edge.
|
|
609
|
+
if (domain.manual && (point.yRatio < 0 || point.yRatio > 1)) continue;
|
|
610
|
+
const projected = pixelPoint(point, width, height, domain.manual);
|
|
611
|
+
drawCircle(data, width, height,
|
|
612
|
+
clamp(projected.x, insetX, width - 1 - insetX),
|
|
613
|
+
clamp(projected.y, insetY, height - 1 - insetY), radius, color);
|
|
590
614
|
}
|
|
591
615
|
break;
|
|
616
|
+
}
|
|
592
617
|
case "candles":
|
|
593
618
|
case "ohlc":
|
|
594
619
|
case "hlc":
|