gloomberb 0.16.4 → 0.16.6
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 +14 -91
- package/package.json +5 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/central-bank-rates.ts +6 -1
- package/src/api-client/chat.ts +26 -0
- package/src/api-client/credit-boards.ts +2 -0
- package/src/api-client/data.ts +73 -3
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +13 -1
- package/src/api-client/market-discovery.ts +13 -1
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +78 -2
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +50 -2
- package/src/app/keybindings/actions.ts +12 -1
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
- package/src/app/runtime/desktop-deeplink.ts +10 -5
- package/src/app/runtime/startup.ts +1 -1
- package/src/app.tsx +6 -0
- package/src/architecture/core-builtin-allowlist.json +8 -26
- package/src/ask-gloom/pane-context.ts +114 -0
- package/src/ask-gloom/pane-request.ts +70 -0
- package/src/ask-gloom/pane-text.ts +201 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +19 -2
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/central-bank-events.ts +23 -0
- package/src/cli/command-options.ts +17 -5
- package/src/cli/commands/crypto-hints.ts +35 -2
- package/src/cli/commands/fred-series.ts +146 -0
- package/src/cli/commands/market.ts +501 -115
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +132 -26
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +317 -13
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +155 -18
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +76 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +7 -5
- package/src/cli/exit-codes.ts +8 -0
- package/src/cli/export-source.ts +58 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +483 -0
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +118 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +29 -9
- package/src/cli/known-gaps.ts +84 -0
- package/src/cli/listing-arg.ts +551 -97
- package/src/cli/not-a-ticker.ts +24 -9
- package/src/cli/pane-functions/access-gate.ts +13 -2
- package/src/cli/pane-functions/capabilities.ts +4 -3
- package/src/cli/pane-functions/catalog.ts +214 -40
- package/src/cli/pane-functions/data.ts +42 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +37 -8
- package/src/cli/pane-functions/freshness.ts +393 -49
- package/src/cli/pane-functions/function-help.ts +31 -15
- package/src/cli/pane-functions/headless.ts +98 -30
- package/src/cli/pane-functions/index.ts +101 -19
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +71 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +74 -19
- package/src/cli/pane-functions/screenshot.ts +250 -27
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +26 -7
- package/src/cli/result.ts +45 -11
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +27 -0
- package/src/cli/symbol-list.ts +154 -0
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +311 -27
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +14 -3
- package/src/components/chart/composite/composite-chart.tsx +71 -11
- package/src/components/chart/composite/crosshair-readout.tsx +150 -0
- package/src/components/chart/composite/downsample.ts +1 -1
- package/src/components/chart/composite/format.ts +29 -0
- package/src/components/chart/composite/interactions.ts +9 -2
- package/src/components/chart/composite/legend.tsx +100 -33
- package/src/components/chart/composite/panel-bitmap.ts +70 -35
- package/src/components/chart/composite/panel-labels.ts +18 -17
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +46 -21
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +50 -8
- package/src/components/chart/composite/scene.ts +2 -1
- package/src/components/chart/composite/time-scale.ts +26 -9
- package/src/components/chart/composite/types.ts +18 -0
- package/src/components/chart/composite/use-composite-viewport.ts +30 -2
- package/src/components/chart/native/raster/crosshair.ts +8 -3
- package/src/components/chart/native/raster/primitives.ts +85 -21
- package/src/components/chart/native/surface/manager.ts +33 -8
- package/src/components/chart/surface3d/chart.tsx +1 -1
- package/src/components/command-bar/action-runtime.ts +1 -1
- package/src/components/command-bar/commands/collection-list.ts +210 -0
- package/src/components/command-bar/commands/collection.ts +40 -1
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +42 -17
- package/src/components/layout/detached-pane-shell.tsx +68 -39
- package/src/components/layout/floating-pane.tsx +10 -1
- package/src/components/layout/header.tsx +25 -5
- package/src/components/layout/missing-pane.tsx +3 -3
- package/src/components/layout/pane/capture-stamp.ts +41 -0
- package/src/components/layout/pane/capture-status.ts +12 -0
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +41 -1
- package/src/components/layout/pane/header.tsx +50 -1
- package/src/components/layout/pane/index.tsx +21 -3
- package/src/components/layout/pane/sidebar.tsx +88 -21
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +84 -65
- package/src/components/layout/shell/menu.ts +14 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +32 -10
- package/src/components/layout/shell/pane/ask.ts +131 -0
- package/src/components/layout/shell/pane/capture.ts +162 -0
- package/src/components/layout/shell/pane/layers.tsx +218 -50
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +8 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +43 -2
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +18 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +6 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7555 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +65 -5
- package/src/i18n/ja.ts +65 -5
- package/src/i18n/ko.ts +65 -5
- package/src/i18n/zh-cn.ts +65 -5
- package/src/i18n/zh-tw.ts +65 -5
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +84 -20
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +5 -0
- package/src/market-data/quotes/metadata.ts +19 -24
- package/src/market-data/quotes/resolution.ts +5 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/notifications/app-notifier.ts +17 -1
- package/src/notifications/notification-log.ts +180 -0
- package/src/plugins/auto-update-node.ts +2 -2
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +47 -11
- package/src/plugins/builtin/alerts/pane.tsx +27 -1
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -3
- package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +22 -13
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +49 -12
- package/src/plugins/builtin/cds/headless.ts +119 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +214 -32
- package/src/plugins/builtin/cds/pane.tsx +58 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
- package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
- package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
- package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +70 -5
- package/src/plugins/builtin/chart-composer/index.tsx +15 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
- package/src/plugins/builtin/chat/content/composer.tsx +5 -1
- package/src/plugins/builtin/chat/content/footer.tsx +12 -0
- package/src/plugins/builtin/chat/content/index.tsx +89 -5
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
- package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
- package/src/plugins/builtin/chat/content/scroll.ts +127 -27
- package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
- package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/index.ts +123 -1
- package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
- package/src/plugins/builtin/chat/controller/messages.ts +7 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
- package/src/plugins/builtin/chat/controller/send.ts +61 -1
- package/src/plugins/builtin/chat/controller/state.ts +8 -0
- package/src/plugins/builtin/chat/ghost-user.ts +20 -0
- package/src/plugins/builtin/chat/index.tsx +23 -5
- package/src/plugins/builtin/chat/layout.ts +78 -5
- package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
- package/src/plugins/builtin/chat/message/header.tsx +16 -4
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
- package/src/plugins/builtin/chat/message/render-state.ts +18 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
- package/src/plugins/builtin/chat/message/types.ts +12 -0
- package/src/plugins/builtin/chat/reactions.ts +197 -0
- package/src/plugins/builtin/chat/share/flow.tsx +87 -0
- package/src/plugins/builtin/chat/share/targets.ts +27 -0
- package/src/plugins/builtin/chat/status-widget.tsx +6 -3
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
- package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
- package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/plugin.tsx +19 -2
- package/src/plugins/builtin/cloud/team/model.ts +5 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/team/store.ts +8 -3
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +21 -7
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/headless.ts +97 -10
- package/src/plugins/builtin/company-kpis/model.ts +24 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/cpi/headless.ts +3 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
- package/src/plugins/builtin/credit-boards/client.ts +6 -2
- package/src/plugins/builtin/credit-boards/headless.ts +108 -31
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/model.ts +11 -1
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/client.ts +12 -9
- package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +16 -0
- package/src/plugins/builtin/credit-documents/headless.ts +33 -3
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings/index.tsx +9 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
- package/src/plugins/builtin/exposure/drivers.ts +13 -0
- package/src/plugins/builtin/exposure/headless.ts +205 -13
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +14 -12
- package/src/plugins/builtin/fear-greed/index.tsx +18 -10
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +71 -10
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/client.ts +63 -0
- package/src/plugins/builtin/fx-matrix/export.ts +2 -1
- package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +58 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +31 -9
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +20 -6
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +56 -21
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +143 -8
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +26 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +8 -3
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +6 -8
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +18 -6
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/index.tsx +0 -2
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
- package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +4 -3
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +90 -16
- package/src/plugins/builtin/perps/equity-row.tsx +52 -17
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +47 -32
- package/src/plugins/builtin/perps/index.tsx +23 -4
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
- package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
- package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
- package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
- package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +63 -10
- package/src/plugins/builtin/power/headless.ts +77 -9
- package/src/plugins/builtin/power/index.tsx +28 -3
- package/src/plugins/builtin/power/model.ts +73 -2
- package/src/plugins/builtin/power/pane.tsx +37 -9
- package/src/plugins/builtin/power/prices-client.ts +139 -0
- package/src/plugins/builtin/power/prices-headless.ts +137 -0
- package/src/plugins/builtin/power/prices-model.ts +103 -0
- package/src/plugins/builtin/power/prices.tsx +179 -0
- package/src/plugins/builtin/rate-path/headless.ts +46 -18
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/research/index.tsx +2 -0
- package/src/plugins/builtin/research-search/article.ts +65 -0
- package/src/plugins/builtin/research-search/document-view.tsx +33 -215
- package/src/plugins/builtin/research-search/model.ts +0 -9
- package/src/plugins/builtin/research-search/pane.tsx +41 -30
- package/src/plugins/builtin/research-search/snippet.ts +0 -29
- package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +93 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +12 -1
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +2 -1
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/headless.ts +43 -11
- package/src/plugins/builtin/supply-chain/model.ts +13 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
- package/src/plugins/builtin/themes/headless.ts +74 -10
- package/src/plugins/builtin/themes/model.ts +71 -4
- package/src/plugins/builtin/themes/pane.tsx +22 -5
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +49 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +2 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +51 -17
- package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
- package/src/plugins/builtin/vol-surface/model.ts +39 -6
- package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
- package/src/plugins/builtin/vol-surface/stored.ts +63 -3
- package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
- package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
- package/src/plugins/builtin/world-venue-map/model.ts +56 -19
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/installer.ts +2 -2
- package/src/plugins/loader.ts +15 -0
- package/src/plugins/manager-node.ts +1 -1
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
- package/src/plugins/registry/host-actions.ts +11 -0
- package/src/plugins/registry/index.ts +89 -4
- package/src/portfolio/collection-name.ts +31 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +144 -7
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +65 -2
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +4 -3
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +30 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +16 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +8 -0
- package/src/renderers/dom/host/chart-surface.tsx +33 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +41 -0
- package/src/renderers/dom/host/sticky-scroll.ts +128 -0
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/surface-3d.tsx +19 -7
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +102 -5
- package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
- package/src/renderers/electrobun/bun/index.ts +3 -2
- package/src/renderers/electrobun/shared/protocol.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +5 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/opentui/chart-surface.tsx +1 -0
- package/src/renderers/opentui/frame-capture.ts +33 -0
- package/src/renderers/opentui/host.tsx +10 -13
- package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
- package/src/renderers/opentui/pane-image/glyphs.json +1 -0
- package/src/renderers/opentui/pane-image/index.ts +107 -0
- package/src/renderers/opentui/pane-image/raster.ts +428 -0
- package/src/renderers/opentui/start.tsx +3 -3
- package/src/renderers/opentui/test-utils.tsx +3 -0
- package/src/renderers/opentui/ui-host.tsx +29 -1
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +108 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +153 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/chat.ts +34 -0
- package/src/shares/dialog.tsx +295 -0
- package/src/shares/flow.tsx +56 -0
- package/src/shares/live.ts +14 -22
- package/src/shares/pane-image.ts +152 -0
- package/src/shares/personal-pane.ts +64 -0
- package/src/shares/portable-layout.ts +4 -2
- package/src/shares/prepare.ts +20 -0
- package/src/sources/gloomberb-cloud/index.ts +109 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/index.ts +14 -0
- package/src/sources/provider-router/search.ts +1 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/sync/core-contributors.ts +1 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +34 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +13 -4
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +72 -11
- package/src/tickers/search/ranking.ts +98 -20
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +211 -29
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +12 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +10 -2
- package/src/types/data-provider.ts +11 -0
- package/src/types/financials.ts +62 -1
- package/src/types/headless.ts +113 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +52 -2
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker-changes.ts +26 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +57 -3
- package/src/ui/live-resize.ts +91 -0
- package/src/ui/live-stretch.ts +153 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +131 -15
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +439 -52
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +143 -1
- package/src/utils/format.ts +35 -5
- package/src/utils/forward-dividend.ts +14 -0
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/fx-status.ts +6 -1
- package/src/utils/inline-content-tokenizer.ts +22 -3
- package/src/utils/market-capitalization.ts +8 -0
- package/src/utils/one-shot.ts +73 -0
- package/src/utils/options.ts +37 -8
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +63 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
|
|
2
|
+
import { usePaneSharePreparation } from "../../../shares/prepare";
|
|
2
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
4
|
import { Box, useUiCapabilities } from "../../../ui";
|
|
4
5
|
import {
|
|
@@ -116,13 +117,14 @@ import { getActiveQuoteDisplay } from "../../../market-data/market/status";
|
|
|
116
117
|
import { resolveEntryData } from "../../../market-data/selectors";
|
|
117
118
|
import { editPriceLevels, parsePriceLevels, PRICE_LEVELS_KEY, priceLevelTickerKey } from "./price-levels";
|
|
118
119
|
import { canonicalExchange } from "../../../utils/exchanges";
|
|
119
|
-
import { isPlainKey } from "../../../utils/keyboard";
|
|
120
120
|
import { resolveInstrumentForPane } from "../../../core/state/app/instrument";
|
|
121
121
|
import { CHART_FOLLOW_SERIES_SETTING_KEY, rebindFollowChartSpec, resolveFollowSeriesIds } from "./follow-binding";
|
|
122
122
|
import type { InstrumentRef } from "../../../market-data/request-types";
|
|
123
123
|
|
|
124
124
|
const RANGE_OPTIONS = RANGES.map((range, index) => ({ label: range, value: range, hint: String(index + 1) }));
|
|
125
125
|
const AUTO_VIEWPORT_DEBOUNCE_MS = 350;
|
|
126
|
+
/** A load for a moving view that has not answered in this long no longer holds the next one back. */
|
|
127
|
+
const LOAD_AHEAD_TIMEOUT_MS = 4_000;
|
|
126
128
|
/**
|
|
127
129
|
* Drawings persist into pane settings on a short debounce after the pointer
|
|
128
130
|
* settles. A share reads those settings, so it waits at least that long for a
|
|
@@ -144,6 +146,22 @@ interface RuntimeChartViewportState {
|
|
|
144
146
|
requestViewport: RuntimeChartViewport;
|
|
145
147
|
}
|
|
146
148
|
|
|
149
|
+
/** The oldest and newest market bars loaded, and whether every listing has said it keeps nothing older. */
|
|
150
|
+
function loadedMarketHistory(series: readonly ResolvedSeries[]): { start: number; end: number; complete: boolean } | null {
|
|
151
|
+
let start = Number.POSITIVE_INFINITY;
|
|
152
|
+
let end = Number.NEGATIVE_INFINITY;
|
|
153
|
+
let complete = true;
|
|
154
|
+
for (const entry of series) {
|
|
155
|
+
if (entry.observationKind !== "market" || entry.points.length === 0) continue;
|
|
156
|
+
const first = entry.points[0]!.date.getTime();
|
|
157
|
+
const last = entry.points.at(-1)!.date.getTime();
|
|
158
|
+
if (Number.isFinite(first)) start = Math.min(start, first);
|
|
159
|
+
if (Number.isFinite(last)) end = Math.max(end, last);
|
|
160
|
+
if (!entry.historyStart) complete = false;
|
|
161
|
+
}
|
|
162
|
+
return Number.isFinite(start) && Number.isFinite(end) ? { start, end, complete } : null;
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
function runtimeViewportFromSetting(
|
|
148
166
|
setting: ChartInteractionViewport | null,
|
|
149
167
|
authoredViewportKey: string,
|
|
@@ -258,7 +276,7 @@ function ChartComposerSurface({
|
|
|
258
276
|
}: ChartComposerSurfaceProps) {
|
|
259
277
|
const dialog = useDialog();
|
|
260
278
|
const dispatch = useAppDispatch();
|
|
261
|
-
const {
|
|
279
|
+
const { cellWidthPx = 8 } = useUiCapabilities();
|
|
262
280
|
const desktopWeb = useUiCapabilities().nativePaneChrome === true;
|
|
263
281
|
const paneId = usePaneInstanceId();
|
|
264
282
|
const liveStreaming = useLiveStreamingSetting();
|
|
@@ -351,9 +369,15 @@ function ChartComposerSurface({
|
|
|
351
369
|
spec.viewport.range,
|
|
352
370
|
spec.viewport.resolution,
|
|
353
371
|
]);
|
|
372
|
+
// Auto names the bars it is on, which change as the view moves: a pan back
|
|
373
|
+
// past where a source keeps 30-minute bars charts days instead.
|
|
374
|
+
const autoBars = spec.viewport.resolution === "auto" ? resolution.resolution ?? null : null;
|
|
354
375
|
const resolutionOptions = useMemo(
|
|
355
|
-
() => availableResolutions.map((value) => ({
|
|
356
|
-
|
|
376
|
+
() => availableResolutions.map((value) => ({
|
|
377
|
+
label: value === "auto" && autoBars ? `Auto (${formatChartResolution(autoBars)})` : formatChartResolution(value),
|
|
378
|
+
value,
|
|
379
|
+
})),
|
|
380
|
+
[autoBars, availableResolutions],
|
|
357
381
|
);
|
|
358
382
|
const selectedStudies = getSelectedBuiltinStudies(spec);
|
|
359
383
|
const selectedPairStudies = getSelectedPairStudies(spec);
|
|
@@ -396,7 +420,7 @@ function ChartComposerSurface({
|
|
|
396
420
|
),
|
|
397
421
|
[resolution.bufferedSeries, resolution.legendSeries, resolution.series, spec],
|
|
398
422
|
);
|
|
399
|
-
const {
|
|
423
|
+
const { notify } = usePluginAppActions();
|
|
400
424
|
const { runtime } = usePluginRenderContext();
|
|
401
425
|
const [levelStore, setLevelStore] = usePluginConfigState<unknown>(PRICE_LEVELS_KEY, null);
|
|
402
426
|
const alertsJson = useAppSelector((state) => state.config.pluginConfig[PRICE_ALERTS_STORE.pluginId]?.[PRICE_ALERTS_STORE.key]);
|
|
@@ -472,10 +496,6 @@ function ChartComposerSurface({
|
|
|
472
496
|
...(alertsOn ? { action: { label: "alert", title: "Alert at Level", run: (level) => { void alertAtLevel(level.value); } } } : {}),
|
|
473
497
|
};
|
|
474
498
|
}, [alertAtLevel, alertsJson, alertsOn, editLevels, levelStore, listing]);
|
|
475
|
-
const shareTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
476
|
-
useEffect(() => () => {
|
|
477
|
-
if (shareTimerRef.current !== null) clearTimeout(shareTimerRef.current);
|
|
478
|
-
}, []);
|
|
479
499
|
const [interactionCaptured, setInteractionCapturedState] = useState(false);
|
|
480
500
|
// Typing in quick-add must not freeze the plot: it only takes the keyboard.
|
|
481
501
|
const [modalCaptured, setModalCaptured] = useState(false);
|
|
@@ -631,7 +651,19 @@ function ChartComposerSurface({
|
|
|
631
651
|
const activatePane = useCallback(() => {
|
|
632
652
|
if (!focused) dispatch({ type: "FOCUS_PANE", paneId });
|
|
633
653
|
}, [dispatch, focused, paneId]);
|
|
654
|
+
useEffect(() => () => {
|
|
655
|
+
if (runtimeViewportTimerRef.current !== null) {
|
|
656
|
+
clearTimeout(runtimeViewportTimerRef.current);
|
|
657
|
+
runtimeViewportTimerRef.current = null;
|
|
658
|
+
}
|
|
659
|
+
}, []);
|
|
660
|
+
// The view this pane last saved, so its own write coming back through the
|
|
661
|
+
// settings is not mistaken for another device's view: that would cancel the
|
|
662
|
+
// load a pan still in progress has scheduled and put its window back.
|
|
663
|
+
const savedInteractionViewportRef = useRef<string | null>(null);
|
|
634
664
|
useEffect(() => {
|
|
665
|
+
if (persistedInteractionViewport && requestViewportOwnerRef.current === authoredViewportKey
|
|
666
|
+
&& JSON.stringify(persistedInteractionViewport) === savedInteractionViewportRef.current) return;
|
|
635
667
|
if (runtimeViewportTimerRef.current !== null) {
|
|
636
668
|
clearTimeout(runtimeViewportTimerRef.current);
|
|
637
669
|
runtimeViewportTimerRef.current = null;
|
|
@@ -645,30 +677,41 @@ function ChartComposerSurface({
|
|
|
645
677
|
requestViewportOwnerRef.current = authoredViewportKey;
|
|
646
678
|
setRuntimeViewportState((current) => current?.key === authoredViewportKey ? current : restored);
|
|
647
679
|
if (persistedInteractionViewport && !restored) setStoredInteractionViewport(null);
|
|
648
|
-
return () => {
|
|
649
|
-
if (runtimeViewportTimerRef.current !== null) {
|
|
650
|
-
clearTimeout(runtimeViewportTimerRef.current);
|
|
651
|
-
runtimeViewportTimerRef.current = null;
|
|
652
|
-
}
|
|
653
|
-
};
|
|
654
680
|
}, [authoredViewportKey, persistedInteractionViewport, setStoredInteractionViewport]);
|
|
655
|
-
|
|
681
|
+
// The bars loaded so far, and whether the source has said nothing older exists.
|
|
682
|
+
const loadedHistory = useMemo(() => loadedMarketHistory(plottedSeries), [plottedSeries]);
|
|
683
|
+
const loadedHistoryRef = useRef(loadedHistory);
|
|
684
|
+
loadedHistoryRef.current = loadedHistory;
|
|
685
|
+
// The newest bar seen at all: bars loaded for a moved view (finer ones, after
|
|
686
|
+
// a zoom) can end before it, and a pan forward then has more to ask for.
|
|
687
|
+
const newestBarRef = useRef(Number.NEGATIVE_INFINITY);
|
|
688
|
+
if (loadedHistory) newestBarRef.current = Math.max(newestBarRef.current, loadedHistory.end);
|
|
689
|
+
// A window asked for and not answered yet: the result's view ends where the request does once it lands.
|
|
690
|
+
const loadingWindowRef = useRef<{ end: number; at: number } | null>(null);
|
|
691
|
+
const resultViewportEnd = resolution.viewport?.end.getTime() ?? null;
|
|
692
|
+
if (loadingWindowRef.current && resultViewportEnd !== null
|
|
693
|
+
&& Math.abs(resultViewportEnd - loadingWindowRef.current.end) < 1_000) loadingWindowRef.current = null;
|
|
694
|
+
const commitRuntimeViewport = useCallback((save = true) => {
|
|
656
695
|
const requestViewport = requestViewportRef.current;
|
|
657
696
|
if (!requestViewport) return;
|
|
658
697
|
const adaptiveViewport = spec.viewport.resolution === "auto"
|
|
659
698
|
? adaptiveViewportRef.current
|
|
660
699
|
: null;
|
|
700
|
+
loadingWindowRef.current = { end: requestViewport.end.getTime(), at: Date.now() };
|
|
661
701
|
setRuntimeViewportState({
|
|
662
702
|
key: authoredViewportKey,
|
|
663
703
|
adaptiveViewport,
|
|
664
704
|
requestViewport,
|
|
665
705
|
});
|
|
666
|
-
|
|
706
|
+
if (!save) return;
|
|
707
|
+
const saved = {
|
|
667
708
|
authoredViewportKey,
|
|
668
709
|
start: requestViewport.start.toISOString(),
|
|
669
710
|
end: requestViewport.end.toISOString(),
|
|
670
711
|
adaptive: adaptiveViewport !== null,
|
|
671
|
-
} satisfies ChartInteractionViewport
|
|
712
|
+
} satisfies ChartInteractionViewport;
|
|
713
|
+
savedInteractionViewportRef.current = JSON.stringify(parseChartInteractionViewport(saved));
|
|
714
|
+
setStoredInteractionViewport(saved);
|
|
672
715
|
}, [authoredViewportKey, setStoredInteractionViewport, spec.viewport.resolution]);
|
|
673
716
|
const handleChartViewportChange = useCallback((
|
|
674
717
|
next: { start: Date; end: Date } | null,
|
|
@@ -681,6 +724,7 @@ function ChartComposerSurface({
|
|
|
681
724
|
if (!next) {
|
|
682
725
|
adaptiveViewportRef.current = null;
|
|
683
726
|
requestViewportRef.current = null;
|
|
727
|
+
loadingWindowRef.current = null;
|
|
684
728
|
setRuntimeViewportState(null);
|
|
685
729
|
setStoredInteractionViewport(null);
|
|
686
730
|
return;
|
|
@@ -694,24 +738,31 @@ function ChartComposerSurface({
|
|
|
694
738
|
// A pan can leave the window a provider serves at the current resolution
|
|
695
739
|
// just as a zoom can, so both re-pick.
|
|
696
740
|
if (spec.viewport.resolution === "auto") adaptiveViewportRef.current = viewport;
|
|
741
|
+
// Bars are asked for while the view is still moving, once it comes within
|
|
742
|
+
// half a screen of the oldest loaded one (or of the newest, when newer
|
|
743
|
+
// ones exist), so a long pan keeps going instead of running into the end
|
|
744
|
+
// of what is loaded and waiting for the pointer to rest.
|
|
745
|
+
const loaded = loadedHistoryRef.current;
|
|
746
|
+
const loading = loadingWindowRef.current;
|
|
747
|
+
const reach = (end - start) / 2;
|
|
748
|
+
const nearOldest = !!loaded && !loaded.complete && start - loaded.start < reach;
|
|
749
|
+
const nearNewest = !!loaded && loaded.end < newestBarRef.current - reach / 10 && loaded.end - end < reach;
|
|
750
|
+
if ((nearOldest || nearNewest) && (!loading || Date.now() - loading.at > LOAD_AHEAD_TIMEOUT_MS)) {
|
|
751
|
+
commitRuntimeViewport(false);
|
|
752
|
+
}
|
|
697
753
|
runtimeViewportTimerRef.current = globalThis.setTimeout(() => {
|
|
698
754
|
runtimeViewportTimerRef.current = null;
|
|
699
755
|
commitRuntimeViewport();
|
|
700
756
|
}, AUTO_VIEWPORT_DEBOUNCE_MS);
|
|
701
|
-
}, [authoredViewportKey, commitRuntimeViewport, spec.viewport.resolution]);
|
|
702
|
-
|
|
703
|
-
// The share reads pane settings, so the gesture in flight lands there first.
|
|
757
|
+
}, [authoredViewportKey, commitRuntimeViewport, setStoredInteractionViewport, spec.viewport.resolution]);
|
|
758
|
+
usePaneSharePreparation(paneId, async () => {
|
|
704
759
|
if (runtimeViewportTimerRef.current !== null) {
|
|
705
760
|
clearTimeout(runtimeViewportTimerRef.current);
|
|
706
761
|
runtimeViewportTimerRef.current = null;
|
|
707
762
|
commitRuntimeViewport();
|
|
708
763
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
shareTimerRef.current = null;
|
|
712
|
-
sharePane(paneId);
|
|
713
|
-
}, SHARE_SETTLE_DELAY_MS);
|
|
714
|
-
}, [commitRuntimeViewport, paneId, sharePane]);
|
|
764
|
+
await new Promise((resolve) => setTimeout(resolve, SHARE_SETTLE_DELAY_MS));
|
|
765
|
+
});
|
|
715
766
|
|
|
716
767
|
useRemoteUiNode({
|
|
717
768
|
role: "chart-data",
|
|
@@ -800,12 +851,6 @@ function ChartComposerSurface({
|
|
|
800
851
|
);
|
|
801
852
|
useShortcut((event) => {
|
|
802
853
|
if (interactionCaptureRef.current || dialogOpen) return;
|
|
803
|
-
if (publicSharing && isPlainKey(event, "y")) {
|
|
804
|
-
event.preventDefault();
|
|
805
|
-
event.stopPropagation();
|
|
806
|
-
shareChart();
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
854
|
const shortcut = resolveChartComposerShortcut(event, RANGES.length);
|
|
810
855
|
if (!shortcut) return;
|
|
811
856
|
event.preventDefault();
|
|
@@ -871,11 +916,10 @@ function ChartComposerSurface({
|
|
|
871
916
|
});
|
|
872
917
|
|
|
873
918
|
// Footer registrations compare presentation, so their callbacks must read current actions.
|
|
874
|
-
const currentActionsRef = useRef({ openSeriesEditor, openResolutionPicker
|
|
875
|
-
currentActionsRef.current = { openSeriesEditor, openResolutionPicker
|
|
919
|
+
const currentActionsRef = useRef({ openSeriesEditor, openResolutionPicker });
|
|
920
|
+
currentActionsRef.current = { openSeriesEditor, openResolutionPicker };
|
|
876
921
|
const footerSeries = useCallback(() => { void currentActionsRef.current.openSeriesEditor(); }, []);
|
|
877
922
|
const footerResolution = useCallback(() => { void currentActionsRef.current.openResolutionPicker(); }, []);
|
|
878
|
-
const footerShare = useCallback(() => { currentActionsRef.current.shareChart(); }, []);
|
|
879
923
|
const openIndicators = useCallback((event?: PaneFooterPressEvent) => {
|
|
880
924
|
indicatorsDialogRef.current?.open(footerAnchorPoint(event));
|
|
881
925
|
}, []);
|
|
@@ -901,9 +945,8 @@ function ChartComposerSurface({
|
|
|
901
945
|
{ id: "formulas", key: "f", label: "ormulas", onPress: openFormulas, disabled: formulasDisabled },
|
|
902
946
|
{ id: "resolution", key: "t", label: "imeframe", onPress: footerResolution },
|
|
903
947
|
...(anchorable ? [{ id: "vwap-anchor", key: "v", label: "wap anchor", title: "Anchor VWAP", onPress: footerAnchor }] : []),
|
|
904
|
-
...(publicSharing ? [{ id: "share", key: "y", label: " share", onPress: footerShare }] : []),
|
|
905
948
|
],
|
|
906
|
-
}), [resolution.loading, pickingAnchor, footerSeries, openIndicators, indicatorsDisabled, openFormulas, formulasDisabled, footerResolution, anchorable, footerAnchor
|
|
949
|
+
}), [resolution.loading, pickingAnchor, footerSeries, openIndicators, indicatorsDisabled, openFormulas, formulasDisabled, footerResolution, anchorable, footerAnchor]);
|
|
907
950
|
|
|
908
951
|
// A fixed window (a GIP session) highlights no range, so the bar names it.
|
|
909
952
|
const dateWindowLabel = useMemo(() => {
|
|
@@ -7,11 +7,7 @@ import {
|
|
|
7
7
|
type ChartSeriesCatalogItem,
|
|
8
8
|
} from "../../../capabilities";
|
|
9
9
|
import type { TimeSeriesFieldDefinition } from "../../../time-series/types";
|
|
10
|
-
import {
|
|
11
|
-
FUTURES_CONTRACTS,
|
|
12
|
-
FUTURES_SECTOR_LABELS,
|
|
13
|
-
} from "../futures/contracts";
|
|
14
|
-
import { TREASURY_MATURITIES } from "../yield-curve/treasury-data";
|
|
10
|
+
import type { SeriesCatalogEntry } from "../../../series/types";
|
|
15
11
|
import {
|
|
16
12
|
canonicalExchange,
|
|
17
13
|
parsePublicTickerKey,
|
|
@@ -271,50 +267,61 @@ function matchesAliasQuery(query: string, ...values: string[]): boolean {
|
|
|
271
267
|
return tokens.length > 0 && tokens.every((token) => searchable.includes(token));
|
|
272
268
|
}
|
|
273
269
|
|
|
274
|
-
function
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
270
|
+
function suggestionId(expression: ParsedSeriesExpression): string {
|
|
271
|
+
if (expression.kind === "economic") return `fred:${expression.seriesId}`;
|
|
272
|
+
if (expression.kind === "capability") {
|
|
273
|
+
return chartSeriesSourceKey({ kind: "capability", capabilityId: expression.capabilityId, seriesId: expression.seriesId });
|
|
274
|
+
}
|
|
275
|
+
return `${publicTickerKey(expression.symbol, expression.exchange)}:${expression.fieldId}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function registeredMatchRank(entry: SeriesCatalogEntry, query: string): number {
|
|
279
|
+
const name = compact(entry.name);
|
|
280
|
+
const needle = compact(query);
|
|
281
|
+
if (name === needle || compact(entry.expression) === needle) return 0;
|
|
282
|
+
if (name.startsWith(needle)) return 1;
|
|
283
|
+
return 2;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Registered catalog series the query names: by name, expression, group or
|
|
288
|
+
* tags. A series that takes a ticker is filled in with the one the query
|
|
289
|
+
* names, or the chart's own; ticker fields come from the field ranking instead.
|
|
290
|
+
*/
|
|
291
|
+
function registeredSeriesSuggestions(
|
|
292
|
+
query: string,
|
|
293
|
+
registered: readonly SeriesCatalogEntry[],
|
|
294
|
+
analysis: SeriesSearchAnalysis,
|
|
295
|
+
defaultInstrument: SeriesCatalogInstrument,
|
|
296
|
+
): SeriesCatalogSuggestion[] {
|
|
297
|
+
if (!query.trim() || registered.length === 0) return [];
|
|
298
|
+
const instrument = analysis.directInstrument ?? defaultInstrument;
|
|
299
|
+
const tickerQuery = analysis.directInstrument ? analysis.metricQuery : query;
|
|
300
|
+
const hits: Array<{ entry: SeriesCatalogEntry; rank: number; expression: ParsedSeriesExpression }> = [];
|
|
301
|
+
for (const entry of registered) {
|
|
302
|
+
let template = entry.expression;
|
|
303
|
+
let text = query;
|
|
304
|
+
if (entry.input) {
|
|
305
|
+
// Ticker fields are ranked against the security below; options and pairs need their own symbol.
|
|
306
|
+
if (entry.input !== "ticker" || /^\{ticker\}:[A-Za-z]/.test(template) || !tickerQuery.trim()) continue;
|
|
307
|
+
const symbol = publicTickerKey(instrument.symbol, instrument.exchange);
|
|
308
|
+
template = template.replaceAll("{ticker}", template.startsWith("CAP:") ? encodeURIComponent(symbol) : symbol);
|
|
309
|
+
text = tickerQuery;
|
|
310
|
+
}
|
|
311
|
+
if (!matchesAliasQuery(text, entry.name, entry.expression, entry.id, entry.group ?? "", ...(entry.tags ?? []))) continue;
|
|
312
|
+
const parsed = parseSeriesExpression(template);
|
|
313
|
+
if (!parsed) continue;
|
|
314
|
+
const label = entry.input ? `${publicTickerKey(instrument.symbol, instrument.exchange)} · ${entry.name}` : entry.name;
|
|
315
|
+
hits.push({ entry, rank: registeredMatchRank(entry, text), expression: { ...parsed, label } });
|
|
316
|
+
}
|
|
317
|
+
hits.sort((left, right) => left.rank - right.rank || left.entry.name.length - right.entry.name.length);
|
|
318
|
+
return hits.map(({ entry, expression }): SeriesCatalogSuggestion => ({
|
|
319
|
+
id: suggestionId(expression),
|
|
320
|
+
label: expression.kind === "capability" ? expression.label ?? entry.name : `${entry.expression} · ${entry.name}`,
|
|
321
|
+
description: [entry.group, entry.unit, entry.frequency].filter(Boolean).join(" · "),
|
|
322
|
+
detail: entry.group ?? "Series",
|
|
323
|
+
expression,
|
|
324
|
+
}));
|
|
318
325
|
}
|
|
319
326
|
|
|
320
327
|
export function buildCapabilitySeriesSuggestions(
|
|
@@ -345,6 +352,7 @@ export function buildSeriesCatalogSuggestions(
|
|
|
345
352
|
defaultInstrument: SeriesCatalogInstrument,
|
|
346
353
|
searchedInstruments: readonly SeriesCatalogInstrument[] = [],
|
|
347
354
|
limit = 8,
|
|
355
|
+
registered: readonly SeriesCatalogEntry[] = [],
|
|
348
356
|
): SeriesCatalogSuggestion[] {
|
|
349
357
|
const exact = exactExpressionSuggestion(query.trim());
|
|
350
358
|
const analysis = analyzeSeriesSearchQuery(query);
|
|
@@ -362,7 +370,7 @@ export function buildSeriesCatalogSuggestions(
|
|
|
362
370
|
.sort((left, right) => right.score - left.score || left.field.label.localeCompare(right.field.label));
|
|
363
371
|
|
|
364
372
|
const suggestions: SeriesCatalogSuggestion[] = exact ? [exact] : [];
|
|
365
|
-
for (const suggestion of
|
|
373
|
+
for (const suggestion of registeredSeriesSuggestions(query, registered, analysis, defaultInstrument)) {
|
|
366
374
|
if (!suggestions.some((entry) => entry.id === suggestion.id)) suggestions.push(suggestion);
|
|
367
375
|
}
|
|
368
376
|
const fieldLimit = instruments.length > 1 && !analysis.metricQuery ? 1 : rankedFields.length;
|
|
@@ -15,7 +15,8 @@ import {
|
|
|
15
15
|
isValidChartCapabilityId,
|
|
16
16
|
isValidChartSeriesId,
|
|
17
17
|
} from "../../../capabilities/chart-series";
|
|
18
|
-
import {
|
|
18
|
+
import { futuresContractByCode } from "../../../market-data/futures-board";
|
|
19
|
+
import { getSharedRegistry } from "../../registry";
|
|
19
20
|
import { TREASURY_MATURITIES } from "../yield-curve/treasury-data";
|
|
20
21
|
|
|
21
22
|
export const CHART_FIELD_IDS = {
|
|
@@ -100,9 +101,9 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
|
|
|
100
101
|
if (separator < 0) return null;
|
|
101
102
|
const capabilityId = trimmed.slice(4, separator);
|
|
102
103
|
const seriesId = trimmed.slice(separator + 1);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
if (!isValidChartCapabilityId(capabilityId) || !isValidChartSeriesId(seriesId)) return null;
|
|
105
|
+
const label = registeredSeriesName({ capabilityId, seriesId });
|
|
106
|
+
return { kind: "capability", capabilityId, seriesId, ...(label ? { label } : {}) };
|
|
106
107
|
}
|
|
107
108
|
if (parts[0]?.trim().toUpperCase() === "GEO") {
|
|
108
109
|
const seriesId = trimmed.slice(trimmed.indexOf(":") + 1).trim();
|
|
@@ -112,13 +113,13 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
|
|
|
112
113
|
}
|
|
113
114
|
if (parts[0]?.trim().toUpperCase() === "FRED") {
|
|
114
115
|
const seriesId = parts.length === 2 ? parts[1]?.trim().toUpperCase() ?? "" : "";
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
if (!/^[A-Z0-9._-]{1,80}$/.test(seriesId)) return null;
|
|
117
|
+
// The catalog's name for a listed series, so the legend says what the catalog said.
|
|
118
|
+
const label = getSharedRegistry()?.series?.findByExpression(`FRED:${seriesId}`)?.definition.name;
|
|
119
|
+
return { kind: "economic", provider: "fred", seriesId, ...(label ? { label } : {}) };
|
|
118
120
|
}
|
|
119
121
|
if (parts.length === 2 && parts[0]?.trim().toUpperCase() === "FUT") {
|
|
120
|
-
const
|
|
121
|
-
const contract = FUTURES_CONTRACTS.find((entry) => entry.code === code);
|
|
122
|
+
const contract = futuresContractByCode(parts[1]);
|
|
122
123
|
return contract
|
|
123
124
|
? { kind: "security", symbol: contract.symbol, fieldId: CHART_FIELD_IDS.price, label: contract.name }
|
|
124
125
|
: null;
|
|
@@ -189,10 +190,17 @@ export function formatSeriesExpression(series: ChartSeriesSpec): string {
|
|
|
189
190
|
return `${publicTickerKey(series.source.instrument.symbol, series.source.instrument.exchange)}:${series.source.fieldId}`;
|
|
190
191
|
}
|
|
191
192
|
|
|
193
|
+
/** A registered catalog series' name, with the ticker it was charted for. */
|
|
194
|
+
export function registeredSeriesName(source: { capabilityId: string; seriesId: string }): string | null {
|
|
195
|
+
const found = getSharedRegistry()?.series?.findLoaded(source.capabilityId, source.seriesId);
|
|
196
|
+
if (!found) return null;
|
|
197
|
+
return found.ticker ? `${found.ticker} ${found.series.definition.name}` : found.series.definition.name;
|
|
198
|
+
}
|
|
199
|
+
|
|
192
200
|
export function chartSeriesLabel(series: ChartSeriesSpec): string {
|
|
193
201
|
if (series.label?.trim()) return series.label.trim();
|
|
194
202
|
if (series.source.kind === "economic") return `FRED ${series.source.seriesId}`;
|
|
195
|
-
if (series.source.kind === "capability") return series.source.seriesId;
|
|
203
|
+
if (series.source.kind === "capability") return registeredSeriesName(series.source) ?? series.source.seriesId;
|
|
196
204
|
const generic = getTimeSeriesField(series.source.fieldId)?.unitGroup === "price"
|
|
197
205
|
? futuresGenericListing(series.source.instrument.symbol, series.source.instrument.exchange) : null;
|
|
198
206
|
if (generic) return futuresGenericCaption(generic);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from "react";
|
|
1
|
+
import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import {
|
|
3
3
|
buildTickerSearchCandidates,
|
|
4
4
|
searchTickerCandidates,
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
import { useOptionalAppSelector } from "../../../state/app/context";
|
|
7
7
|
import type { TickerRecord } from "../../../types/ticker";
|
|
8
8
|
import { searchChartSeriesCapabilities } from "../../../capabilities";
|
|
9
|
+
import { SERIES_CATALOG_CAPABILITY_ID } from "../../../series/capability";
|
|
10
|
+
import type { SeriesCatalogEntry } from "../../../series/types";
|
|
9
11
|
import { getSharedRegistry } from "../../registry";
|
|
10
12
|
import {
|
|
11
13
|
analyzeSeriesSearchQuery,
|
|
@@ -17,6 +19,9 @@ import {
|
|
|
17
19
|
|
|
18
20
|
const EMPTY_TICKERS: ReadonlyMap<string, TickerRecord> = new Map();
|
|
19
21
|
const EMPTY_RECENT: readonly string[] = [];
|
|
22
|
+
const EMPTY_PLUGINS: readonly string[] = [];
|
|
23
|
+
const EMPTY_ENTRIES: readonly SeriesCatalogEntry[] = [];
|
|
24
|
+
const NO_SUBSCRIPTION = () => () => {};
|
|
20
25
|
const MAX_SERIES_SUGGESTIONS = 8;
|
|
21
26
|
const DEFAULT_CATALOG_INSTRUMENTS: readonly SeriesCatalogInstrument[] = [
|
|
22
27
|
{ symbol: "AAPL", exchange: "NASDAQ", name: "Apple Inc." },
|
|
@@ -72,6 +77,56 @@ function candidateToInstrument(candidate: {
|
|
|
72
77
|
};
|
|
73
78
|
}
|
|
74
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Every registered series of the plugins that are switched on. On the
|
|
82
|
+
* desktop, series only the Bun process has (files in the profile's series
|
|
83
|
+
* folder) are asked for once and listed after the rest; elsewhere, sources
|
|
84
|
+
* that change while the app runs catch up when the catalog opens.
|
|
85
|
+
*/
|
|
86
|
+
export function useRegisteredSeries(): readonly SeriesCatalogEntry[] {
|
|
87
|
+
const registry = getSharedRegistry();
|
|
88
|
+
const series = registry?.series;
|
|
89
|
+
const version = useSyncExternalStore(
|
|
90
|
+
series ? series.subscribe.bind(series) : NO_SUBSCRIPTION,
|
|
91
|
+
() => series?.getVersion() ?? 0,
|
|
92
|
+
() => 0,
|
|
93
|
+
);
|
|
94
|
+
const disabledPlugins = useOptionalAppSelector((state) => state.config.disabledPlugins, EMPTY_PLUGINS);
|
|
95
|
+
const [remote, setRemote] = useState<readonly SeriesCatalogEntry[] | null>(null);
|
|
96
|
+
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (!registry || !series) return;
|
|
99
|
+
if (!registry.usesRemoteCapabilities) {
|
|
100
|
+
void series.refresh();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
let cancelled = false;
|
|
104
|
+
void registry.invokeCapability<{ entries: SeriesCatalogEntry[] }>(SERIES_CATALOG_CAPABILITY_ID, "list", {})
|
|
105
|
+
.then((result) => {
|
|
106
|
+
if (!cancelled && Array.isArray(result?.entries)) setRemote(result.entries);
|
|
107
|
+
})
|
|
108
|
+
.catch(() => {
|
|
109
|
+
// The view's own series still list; only the Bun process's extras are missing.
|
|
110
|
+
});
|
|
111
|
+
return () => { cancelled = true; };
|
|
112
|
+
}, [registry, series]);
|
|
113
|
+
|
|
114
|
+
return useMemo(() => {
|
|
115
|
+
const local = series?.catalog() ?? EMPTY_ENTRIES;
|
|
116
|
+
let entries = local;
|
|
117
|
+
if (remote?.length) {
|
|
118
|
+
const known = new Set(local.map((entry) => entry.id));
|
|
119
|
+
const extra = remote.filter((entry) => !known.has(entry.id));
|
|
120
|
+
if (extra.length) entries = [...local, ...extra];
|
|
121
|
+
}
|
|
122
|
+
if (disabledPlugins.length === 0) return entries;
|
|
123
|
+
const disabled = new Set(disabledPlugins);
|
|
124
|
+
return entries.some((entry) => disabled.has(entry.pluginId))
|
|
125
|
+
? entries.filter((entry) => !disabled.has(entry.pluginId))
|
|
126
|
+
: entries;
|
|
127
|
+
}, [disabledPlugins, remote, series, version]);
|
|
128
|
+
}
|
|
129
|
+
|
|
75
130
|
export function useCatalogUniverse(query: string): {
|
|
76
131
|
instruments: SeriesCatalogInstrument[];
|
|
77
132
|
loading: boolean;
|
|
@@ -193,6 +248,7 @@ export function useSeriesCatalogSuggestions({
|
|
|
193
248
|
enabled: boolean;
|
|
194
249
|
}): SeriesCatalogSearchResult {
|
|
195
250
|
const tickers = useOptionalAppSelector((state) => state.tickers, EMPTY_TICKERS);
|
|
251
|
+
const registered = useRegisteredSeries();
|
|
196
252
|
const analysis = useMemo(() => analyzeSeriesSearchQuery(query), [query]);
|
|
197
253
|
const [providerSearch, setProviderSearch] = useState<{
|
|
198
254
|
query: string;
|
|
@@ -298,11 +354,11 @@ export function useSeriesCatalogSuggestions({
|
|
|
298
354
|
// and they arrive well before plugin catalogs (which can take seconds), so
|
|
299
355
|
// late plugin results append below instead of pushing the list around.
|
|
300
356
|
const suggestions = useMemo(() => {
|
|
301
|
-
const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments);
|
|
357
|
+
const builtIn = buildSeriesCatalogSuggestions(query, defaultInstrument, instruments, MAX_SERIES_SUGGESTIONS, registered);
|
|
302
358
|
const provider = providerSearch.query === query.trim() ? providerSearch.suggestions : [];
|
|
303
359
|
return [...builtIn, ...provider.filter((entry) => !builtIn.some((candidate) => candidate.id === entry.id))]
|
|
304
360
|
.slice(0, MAX_SERIES_SUGGESTIONS);
|
|
305
|
-
}, [defaultInstrument, instruments, providerSearch, query]);
|
|
361
|
+
}, [defaultInstrument, instruments, providerSearch, query, registered]);
|
|
306
362
|
|
|
307
363
|
return {
|
|
308
364
|
suggestions,
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { getCurrentPluginTarget } from "../../current-target";
|
|
2
|
+
import { getSharedRegistry } from "../../registry";
|
|
3
|
+
import { listSeriesFiles, seriesFromFile } from "../../../series/files";
|
|
4
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
5
|
+
import type { GloomPluginContext } from "../../../types/plugin";
|
|
6
|
+
import type { PluginModule } from "../plugin-module";
|
|
7
|
+
|
|
8
|
+
interface RegisteredFile {
|
|
9
|
+
mtimeMs: number;
|
|
10
|
+
dispose: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Keeps the catalog in step with the profile's series folder: a file added,
|
|
15
|
+
* changed or removed shows up the next time the catalog opens.
|
|
16
|
+
*/
|
|
17
|
+
function watchUserSeriesFolder(ctx: GloomPluginContext): () => void {
|
|
18
|
+
const registered = new Map<string, RegisteredFile>();
|
|
19
|
+
let running: Promise<void> = Promise.resolve();
|
|
20
|
+
|
|
21
|
+
const sync = async () => {
|
|
22
|
+
const files = await listSeriesFiles(ctx.getConfig().dataDir);
|
|
23
|
+
const present = new Set(files.map((file) => file.name));
|
|
24
|
+
for (const [name, entry] of registered) {
|
|
25
|
+
if (present.has(name)) continue;
|
|
26
|
+
entry.dispose();
|
|
27
|
+
registered.delete(name);
|
|
28
|
+
}
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
const existing = registered.get(file.name);
|
|
31
|
+
if (existing?.mtimeMs === file.mtimeMs) continue;
|
|
32
|
+
existing?.dispose();
|
|
33
|
+
registered.delete(file.name);
|
|
34
|
+
let definitions: SeriesDefinition[];
|
|
35
|
+
try {
|
|
36
|
+
definitions = seriesFromFile(file.name, await file.readText(), file.readText);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
ctx.log.warn("Series file skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const disposers = definitions.flatMap((definition) => {
|
|
42
|
+
try {
|
|
43
|
+
return [ctx.registerSeries(definition)];
|
|
44
|
+
} catch (error) {
|
|
45
|
+
ctx.log.warn("Series skipped", { file: file.name, error: error instanceof Error ? error.message : String(error) });
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
registered.set(file.name, { mtimeMs: file.mtimeMs, dispose: () => { for (const dispose of disposers) dispose(); } });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const refresh = () => {
|
|
53
|
+
running = running.then(sync, sync);
|
|
54
|
+
return running;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
void refresh();
|
|
58
|
+
const removeRefresher = getSharedRegistry()?.series.addRefresher(refresh);
|
|
59
|
+
return () => {
|
|
60
|
+
removeRefresher?.();
|
|
61
|
+
for (const entry of registered.values()) entry.dispose();
|
|
62
|
+
registered.clear();
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let stopWatching: (() => void) | null = null;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* CSV files in `<data dir>/series/` as catalog series, chartable against
|
|
70
|
+
* anything else. Files are read where the app can reach the disk: the
|
|
71
|
+
* terminal, and the desktop's Bun process, which lists them for its view.
|
|
72
|
+
*/
|
|
73
|
+
export const userSeriesModule: PluginModule = {
|
|
74
|
+
setup(ctx) {
|
|
75
|
+
const target = getCurrentPluginTarget();
|
|
76
|
+
if (target !== "cli" && target !== "tui") return;
|
|
77
|
+
stopWatching?.();
|
|
78
|
+
stopWatching = watchUserSeriesFolder(ctx);
|
|
79
|
+
},
|
|
80
|
+
dispose() {
|
|
81
|
+
stopWatching?.();
|
|
82
|
+
stopWatching = null;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
@@ -11,6 +11,8 @@ import type { ChatContentController } from "./types";
|
|
|
11
11
|
import { getComposerCursorOffset, moveComposerCursorToOffset } from "./composer-cursor";
|
|
12
12
|
import { insertedText, pastedImagePaths } from "../attachments/transfer";
|
|
13
13
|
import { chatTextWithImages } from "../attachments/model";
|
|
14
|
+
import { isManagedBot } from "../ghost-user";
|
|
15
|
+
import { CHAT_AI_BADGE_WIDTH } from "../message/ai-badge";
|
|
14
16
|
|
|
15
17
|
interface MutableRef<T> {
|
|
16
18
|
current: T;
|
|
@@ -398,7 +400,10 @@ export function useChatComposerRuntime({
|
|
|
398
400
|
const replyPreview = replyTo
|
|
399
401
|
? formatInlinePreview(
|
|
400
402
|
chatTextWithImages(replyTo.content, replyTo.attachments?.length ?? 0),
|
|
401
|
-
Math.max(
|
|
403
|
+
Math.max(
|
|
404
|
+
contentWidth - ` replying to @${replyTo.user.username}`.length - (isManagedBot(replyTo.user) ? CHAT_AI_BADGE_WIDTH + 1 : 2) - COMPOSER_ACTION_WIDTH - 1,
|
|
405
|
+
0,
|
|
406
|
+
),
|
|
402
407
|
)
|
|
403
408
|
: "";
|
|
404
409
|
const editingPreview = editingMessage
|