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
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import type { AppConfig } from "../types/config";
|
|
2
|
+
import type { InstrumentSearchResult } from "../types/instrument";
|
|
3
|
+
import type { TickerRecord, Watchlist } from "../types/ticker";
|
|
4
|
+
import { AmbiguousTickerError, resolveTickerSearch, type ResolvedTickerSearch } from "../tickers/search";
|
|
5
|
+
import { canonicalExchange, parsePublicTickerKey, publicTickerKey } from "../utils/exchanges";
|
|
6
|
+
import {
|
|
7
|
+
applyCollectionMembershipChange,
|
|
8
|
+
materializeResolvedTicker,
|
|
9
|
+
type SharedWorkflowDeps,
|
|
10
|
+
} from "../components/command-bar/workflow/tickers";
|
|
11
|
+
import {
|
|
12
|
+
AmbiguousCollectionTickerError,
|
|
13
|
+
resolveCollectionTicker,
|
|
14
|
+
} from "../components/command-bar/workflow/collection-ticker";
|
|
15
|
+
import type { RemoteChangePrompt } from "./types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* `watchlist.add` and `watchlist.remove`: one ticker on one of the person's
|
|
19
|
+
* own watchlists, through the same membership change the AW and RW commands
|
|
20
|
+
* make. A plan resolves the list and the listing without writing anything,
|
|
21
|
+
* so a caller can show it, ask, and then apply exactly that plan.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export type WatchlistAction = "add" | "remove";
|
|
25
|
+
|
|
26
|
+
/** A change the app will not make, in words a caller can repeat to the person. */
|
|
27
|
+
class WatchlistRefusal extends Error {
|
|
28
|
+
constructor(message: string) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "WatchlistRefusal";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface WatchlistChangeInput {
|
|
35
|
+
symbol: string;
|
|
36
|
+
exchange?: string;
|
|
37
|
+
watchlist?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type ResolvedListing =
|
|
41
|
+
| { kind: "saved"; ticker: TickerRecord }
|
|
42
|
+
| { kind: "listing"; resolved: Extract<ResolvedTickerSearch, { kind: "provider" }> }
|
|
43
|
+
| { kind: "absent" };
|
|
44
|
+
|
|
45
|
+
export interface WatchlistChangePlan {
|
|
46
|
+
action: WatchlistAction;
|
|
47
|
+
watchlist: Pick<Watchlist, "id" | "name">;
|
|
48
|
+
symbol: string;
|
|
49
|
+
exchange: string;
|
|
50
|
+
name: string | null;
|
|
51
|
+
/** False when the ticker is already on the list (add) or not on it (remove). */
|
|
52
|
+
changes: boolean;
|
|
53
|
+
/** The change in one line, as the person approves it. */
|
|
54
|
+
summary: string;
|
|
55
|
+
/** Names this exact change: action, list and saved listing. */
|
|
56
|
+
confirmKey: string;
|
|
57
|
+
listing: ResolvedListing;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type WatchlistChangeOutcome = "added" | "removed" | "already-listed" | "not-listed" | "declined";
|
|
61
|
+
|
|
62
|
+
export interface WatchlistChangeResult {
|
|
63
|
+
changed: boolean;
|
|
64
|
+
outcome: WatchlistChangeOutcome;
|
|
65
|
+
message: string;
|
|
66
|
+
watchlist: Pick<Watchlist, "id" | "name">;
|
|
67
|
+
symbol: string;
|
|
68
|
+
exchange: string | null;
|
|
69
|
+
name: string | null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isTeamWatchlist(watchlist: Watchlist): boolean {
|
|
73
|
+
return !!watchlist.teamId || watchlist.id.startsWith("team:");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function personalWatchlists(config: AppConfig): Watchlist[] {
|
|
77
|
+
return config.watchlists.filter((watchlist) => !isTeamWatchlist(watchlist));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function listNames(watchlists: readonly Watchlist[]): string {
|
|
81
|
+
return watchlists.map((watchlist) => `"${watchlist.name}" (id ${watchlist.id})`).join(", ");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The personal watchlist a call names by id or name, or else the default
|
|
86
|
+
* one: the first personal watchlist, which a new profile calls Watchlist and
|
|
87
|
+
* onboarding fills. The confirmation names it, so a wrong guess is declined.
|
|
88
|
+
* Team watchlists are shared with everyone on the team and portfolios are
|
|
89
|
+
* not watchlists, so both are refused, as the list's own remove key does.
|
|
90
|
+
*/
|
|
91
|
+
function resolveWatchlistTarget(config: AppConfig, requested: string | undefined): Watchlist {
|
|
92
|
+
const personal = personalWatchlists(config);
|
|
93
|
+
const raw = requested?.trim() ?? "";
|
|
94
|
+
if (!raw) {
|
|
95
|
+
if (personal[0]) return personal[0];
|
|
96
|
+
throw new WatchlistRefusal("There is no personal watchlist to change. Create one with New Watchlist first.");
|
|
97
|
+
}
|
|
98
|
+
const lower = raw.toLowerCase();
|
|
99
|
+
const matches = (entry: { id: string; name: string }) => entry.id.toLowerCase() === lower || entry.name.toLowerCase() === lower;
|
|
100
|
+
const watchlist = config.watchlists.find((entry) => entry.id === raw) ?? config.watchlists.find(matches);
|
|
101
|
+
if (watchlist) {
|
|
102
|
+
if (isTeamWatchlist(watchlist)) {
|
|
103
|
+
throw new WatchlistRefusal(`Refused: "${watchlist.name}" is a team watchlist, shared with everyone on the team. Only personal watchlists can be changed this way.`);
|
|
104
|
+
}
|
|
105
|
+
return watchlist;
|
|
106
|
+
}
|
|
107
|
+
const portfolio = config.portfolios.find((entry) => entry.id === raw) ?? config.portfolios.find(matches);
|
|
108
|
+
if (portfolio) {
|
|
109
|
+
const kind = portfolio.brokerId || portfolio.brokerInstanceId
|
|
110
|
+
? "a broker portfolio, whose positions come from the broker"
|
|
111
|
+
: portfolio.teamId ? "a team portfolio" : "a portfolio";
|
|
112
|
+
throw new WatchlistRefusal(`Refused: "${portfolio.name}" is ${kind}, not a watchlist.`);
|
|
113
|
+
}
|
|
114
|
+
throw new WatchlistRefusal(personal.length > 0
|
|
115
|
+
? `There is no watchlist "${raw}". Personal watchlists: ${listNames(personal)}.`
|
|
116
|
+
: `There is no watchlist "${raw}", and no personal watchlist at all.`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function listingExchange(result: InstrumentSearchResult): string {
|
|
120
|
+
return result.exchange === "SMART" ? result.primaryExchange || result.exchange
|
|
121
|
+
: result.exchange || result.primaryExchange || "";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function listingLabel(symbol: string, exchange: string): string {
|
|
125
|
+
return exchange ? `${symbol} (${exchange})` : symbol;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function resolveListing(
|
|
129
|
+
input: WatchlistChangeInput,
|
|
130
|
+
deps: SharedWorkflowDeps,
|
|
131
|
+
): Promise<ResolvedTickerSearch | null> {
|
|
132
|
+
const symbol = input.symbol.trim().toUpperCase();
|
|
133
|
+
const exchange = input.exchange?.trim().toUpperCase();
|
|
134
|
+
if (!symbol) throw new WatchlistRefusal("symbol is required.");
|
|
135
|
+
const query = exchange ? `${parsePublicTickerKey(symbol).symbol}:${exchange}` : symbol;
|
|
136
|
+
try {
|
|
137
|
+
return await resolveTickerSearch({
|
|
138
|
+
query,
|
|
139
|
+
activeTicker: null,
|
|
140
|
+
tickers: deps.getState().tickers,
|
|
141
|
+
dataProvider: deps.dataProvider,
|
|
142
|
+
searchContext: { preferBroker: true, interactive: true },
|
|
143
|
+
});
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (error instanceof AmbiguousTickerError) {
|
|
146
|
+
throw new WatchlistRefusal(error.listings.length > 0
|
|
147
|
+
? `${query} matches more than one listing: ${error.listings.slice(0, 6).join(", ")}. Pass exchange to pick one.`
|
|
148
|
+
: error.message);
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** The saved record that owns this listing on the list, as the AW command picks it. */
|
|
155
|
+
function savedOwner(ticker: TickerRecord, deps: SharedWorkflowDeps, watchlistId: string): TickerRecord {
|
|
156
|
+
try {
|
|
157
|
+
return resolveCollectionTicker(ticker, deps.getState().tickers, "watchlist", watchlistId);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error instanceof AmbiguousCollectionTickerError) throw new WatchlistRefusal(error.message);
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** What the call would change, resolved without writing anything. */
|
|
165
|
+
export async function planWatchlistChange(
|
|
166
|
+
action: WatchlistAction,
|
|
167
|
+
input: WatchlistChangeInput,
|
|
168
|
+
deps: SharedWorkflowDeps,
|
|
169
|
+
): Promise<WatchlistChangePlan> {
|
|
170
|
+
const watchlist = resolveWatchlistTarget(deps.getState().config, input.watchlist);
|
|
171
|
+
const resolved = await resolveListing(input, deps);
|
|
172
|
+
let listing: ResolvedListing;
|
|
173
|
+
let symbol: string;
|
|
174
|
+
let exchange: string;
|
|
175
|
+
let name: string | null;
|
|
176
|
+
let key: string;
|
|
177
|
+
let member: boolean;
|
|
178
|
+
if (resolved?.kind === "local") {
|
|
179
|
+
const ticker = savedOwner(resolved.ticker, deps, watchlist.id);
|
|
180
|
+
listing = { kind: "saved", ticker };
|
|
181
|
+
symbol = parsePublicTickerKey(ticker.metadata.ticker).symbol;
|
|
182
|
+
exchange = canonicalExchange(ticker.metadata.exchange);
|
|
183
|
+
name = ticker.metadata.name && ticker.metadata.name !== ticker.metadata.ticker ? ticker.metadata.name : null;
|
|
184
|
+
key = ticker.metadata.ticker;
|
|
185
|
+
member = ticker.metadata.watchlists.includes(watchlist.id);
|
|
186
|
+
} else if (resolved?.kind === "provider") {
|
|
187
|
+
if (action === "add") {
|
|
188
|
+
listing = { kind: "listing", resolved };
|
|
189
|
+
} else {
|
|
190
|
+
listing = { kind: "absent" };
|
|
191
|
+
}
|
|
192
|
+
symbol = parsePublicTickerKey(resolved.symbol).symbol;
|
|
193
|
+
exchange = canonicalExchange(listingExchange(resolved.result));
|
|
194
|
+
name = resolved.result.name?.trim() || null;
|
|
195
|
+
key = publicTickerKey(resolved.symbol, listingExchange(resolved.result));
|
|
196
|
+
member = false;
|
|
197
|
+
} else {
|
|
198
|
+
if (action === "add") throw new WatchlistRefusal(`No listing found for ${input.symbol.trim().toUpperCase()}.`);
|
|
199
|
+
listing = { kind: "absent" };
|
|
200
|
+
symbol = parsePublicTickerKey(input.symbol.trim().toUpperCase()).symbol;
|
|
201
|
+
exchange = canonicalExchange(input.exchange);
|
|
202
|
+
name = null;
|
|
203
|
+
key = symbol;
|
|
204
|
+
member = false;
|
|
205
|
+
}
|
|
206
|
+
const label = listingLabel(symbol, exchange);
|
|
207
|
+
return {
|
|
208
|
+
action,
|
|
209
|
+
watchlist: { id: watchlist.id, name: watchlist.name },
|
|
210
|
+
symbol,
|
|
211
|
+
exchange,
|
|
212
|
+
name,
|
|
213
|
+
changes: action === "add" ? !member : member,
|
|
214
|
+
summary: action === "add" ? `Add ${label} to ${watchlist.name}` : `Remove ${label} from ${watchlist.name}`,
|
|
215
|
+
confirmKey: `${action}|${watchlist.id}|${key}`,
|
|
216
|
+
listing,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** The dialog the app shows before it applies a plan. */
|
|
221
|
+
export function watchlistChangePrompt(plan: WatchlistChangePlan): RemoteChangePrompt {
|
|
222
|
+
return {
|
|
223
|
+
title: plan.action === "add"
|
|
224
|
+
? `Add ${plan.symbol} to ${plan.watchlist.name}?`
|
|
225
|
+
: `Remove ${plan.symbol} from ${plan.watchlist.name}?`,
|
|
226
|
+
lines: watchlistChangeLines(plan),
|
|
227
|
+
confirmLabel: plan.action === "add" ? "Add" : "Remove",
|
|
228
|
+
destructive: plan.action === "remove",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function watchlistChangeLines(plan: WatchlistChangePlan): RemoteChangePrompt["lines"] {
|
|
233
|
+
return [
|
|
234
|
+
{ label: "Watchlist", value: plan.watchlist.name },
|
|
235
|
+
{ label: "Ticker", value: plan.symbol },
|
|
236
|
+
{ label: "Exchange", value: plan.exchange || "not known" },
|
|
237
|
+
...(plan.name ? [{ label: "Name", value: plan.name }] : []),
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** What a dry run reports: the plan a caller can show, and the key it passes back once approved. */
|
|
242
|
+
export function describeWatchlistPlan(plan: WatchlistChangePlan) {
|
|
243
|
+
return {
|
|
244
|
+
dryRun: true,
|
|
245
|
+
action: plan.action,
|
|
246
|
+
watchlist: plan.watchlist,
|
|
247
|
+
symbol: plan.symbol,
|
|
248
|
+
exchange: plan.exchange || null,
|
|
249
|
+
name: plan.name,
|
|
250
|
+
changes: plan.changes,
|
|
251
|
+
summary: plan.changes ? plan.summary : unchangedMessage(plan),
|
|
252
|
+
lines: watchlistChangeLines(plan),
|
|
253
|
+
confirmKey: plan.confirmKey,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function result(plan: WatchlistChangePlan, outcome: WatchlistChangeOutcome, message: string, ticker?: TickerRecord): WatchlistChangeResult {
|
|
258
|
+
return {
|
|
259
|
+
changed: outcome === "added" || outcome === "removed",
|
|
260
|
+
outcome,
|
|
261
|
+
message,
|
|
262
|
+
watchlist: plan.watchlist,
|
|
263
|
+
symbol: ticker ? parsePublicTickerKey(ticker.metadata.ticker).symbol : plan.symbol,
|
|
264
|
+
exchange: (ticker ? canonicalExchange(ticker.metadata.exchange) : plan.exchange) || null,
|
|
265
|
+
name: plan.name,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function unchangedMessage(plan: WatchlistChangePlan): string {
|
|
270
|
+
const label = listingLabel(plan.symbol, plan.exchange);
|
|
271
|
+
return plan.action === "add"
|
|
272
|
+
? `${label} is already on ${plan.watchlist.name}; nothing changed.`
|
|
273
|
+
: `${label} is not on ${plan.watchlist.name}; nothing changed.`;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function unchangedWatchlistResult(plan: WatchlistChangePlan): WatchlistChangeResult {
|
|
277
|
+
return result(plan, plan.action === "add" ? "already-listed" : "not-listed", unchangedMessage(plan));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function declinedWatchlistResult(plan: WatchlistChangePlan): WatchlistChangeResult {
|
|
281
|
+
return result(plan, "declined", `Declined in the app: ${plan.watchlist.name} is unchanged.`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Writes an approved plan through the AW command's membership change. The
|
|
286
|
+
* list is checked again first: it may have been deleted or shared with a
|
|
287
|
+
* team while the person decided.
|
|
288
|
+
*/
|
|
289
|
+
export async function applyWatchlistChange(
|
|
290
|
+
plan: WatchlistChangePlan,
|
|
291
|
+
deps: SharedWorkflowDeps,
|
|
292
|
+
): Promise<WatchlistChangeResult> {
|
|
293
|
+
const watchlist = resolveWatchlistTarget(deps.getState().config, plan.watchlist.id);
|
|
294
|
+
if (watchlist.id !== plan.watchlist.id) throw new WatchlistRefusal(`${plan.watchlist.name} changed while the app asked; nothing changed.`);
|
|
295
|
+
if (plan.listing.kind === "absent") return unchangedWatchlistResult(plan);
|
|
296
|
+
const ticker = plan.listing.kind === "saved"
|
|
297
|
+
? deps.getState().tickers.get(plan.listing.ticker.metadata.ticker) ?? plan.listing.ticker
|
|
298
|
+
: (await materializeResolvedTicker(plan.listing.resolved, deps)).ticker;
|
|
299
|
+
const owner = savedOwner(ticker, deps, watchlist.id);
|
|
300
|
+
const { changed, ticker: saved } = await applyCollectionMembershipChange(owner, "watchlist", plan.action, watchlist.id, deps);
|
|
301
|
+
if (!changed) return result(plan, plan.action === "add" ? "already-listed" : "not-listed", unchangedMessage(plan), saved);
|
|
302
|
+
const label = listingLabel(parsePublicTickerKey(saved.metadata.ticker).symbol, canonicalExchange(saved.metadata.exchange));
|
|
303
|
+
return plan.action === "add"
|
|
304
|
+
? result(plan, "added", `Added ${label} to ${watchlist.name}.`, saved)
|
|
305
|
+
: result(plan, "removed", `Removed ${label} from ${watchlist.name}.`, saved);
|
|
306
|
+
}
|
|
@@ -20,7 +20,7 @@ import { browserRendererHost, browserUiHost } from "./ui-host";
|
|
|
20
20
|
import { createBrowserDeepLinkBridge } from "./deeplink-bridge";
|
|
21
21
|
import { initializeBrowserResearchActivity, recordResearchActivity } from "../../api-client/research-activity";
|
|
22
22
|
import { flushPendingPersistence } from "../../state/persist-scheduler";
|
|
23
|
-
import { loadOfficialPluginIds } from "../../plugins/
|
|
23
|
+
import { loadOfficialPluginIds } from "../../plugins/marketplace/feed";
|
|
24
24
|
import { crashReportsEnabled, installCrashReporter, reportCrash } from "../../telemetry/crash-reports";
|
|
25
25
|
import {
|
|
26
26
|
browserDoNotTrack,
|
|
@@ -71,6 +71,9 @@ async function boot(): Promise<void> {
|
|
|
71
71
|
if (document.visibilityState === "hidden") void flushPendingPersistence();
|
|
72
72
|
});
|
|
73
73
|
installBrowserFetchTransports();
|
|
74
|
+
// Read the saved Usage switch before any research activity or attribution.
|
|
75
|
+
const config = await loadConfig(BROWSER_DATA_DIR);
|
|
76
|
+
loadedConfig = config;
|
|
74
77
|
initializeBrowserResearchActivity();
|
|
75
78
|
installFocusScopeRelease();
|
|
76
79
|
installDomMarketDataFrames();
|
|
@@ -84,8 +87,6 @@ async function boot(): Promise<void> {
|
|
|
84
87
|
recordResearchActivity("workspace_opened");
|
|
85
88
|
// Nothing was restored on a first visit, only the starter workspace shown.
|
|
86
89
|
if (!hasSavedBrowserConfig()) recordRestoredFunctions([]);
|
|
87
|
-
const config = await loadConfig(BROWSER_DATA_DIR);
|
|
88
|
-
loadedConfig = config;
|
|
89
90
|
applyLanguageFromConfig(config);
|
|
90
91
|
const externalPlugins = await bundledPlugins;
|
|
91
92
|
const deepLinkBridge = createBrowserDeepLinkBridge();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tickerHasListingSuffix } from "../../sources/listing-symbols";
|
|
2
|
-
import { parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
|
|
2
|
+
import { isSharedExchangeCode, parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
|
|
3
3
|
|
|
4
4
|
export function researchEntryFromSearch(search: string): { symbol: string; tab: string } | null {
|
|
5
5
|
const params = new URLSearchParams(search);
|
|
@@ -13,8 +13,10 @@ export function researchEntryFromSearch(search: string): { symbol: string; tab:
|
|
|
13
13
|
if ([exchange, requested.exchange].some((venue) => venue && !/^[A-Z0-9][A-Z0-9 ._-]{0,31}$/.test(venue))) return null;
|
|
14
14
|
// Carry a separate venue through the same listing-qualified resolver used by
|
|
15
15
|
// search and deep links. An explicit symbol suffix/key remains authoritative.
|
|
16
|
+
// A code that names several venues (TSE: Tokyo or Toronto) stays as typed for
|
|
17
|
+
// the resolver to read as the one the symbol trades on.
|
|
16
18
|
const target = exchange && !requested.exchange && !tickerHasListingSuffix(symbol)
|
|
17
|
-
? publicTickerKey(symbol, exchange)
|
|
19
|
+
? isSharedExchangeCode(exchange) ? `${symbol}:${exchange}` : publicTickerKey(symbol, exchange)
|
|
18
20
|
: symbol;
|
|
19
21
|
const tab = params.get("tab") ?? "overview";
|
|
20
22
|
return { symbol: target, tab: /^[a-z-]{1,40}$/.test(tab) ? tab : "overview" };
|
|
@@ -54,7 +54,7 @@ type ApiFetch = (request: Request) => Promise<Response>;
|
|
|
54
54
|
const proxySessions = createProxySessionGate({ sessionUrl: `${API_ORIGIN}/auth/get-session` });
|
|
55
55
|
|
|
56
56
|
export const SECURITY_HEADERS = {
|
|
57
|
-
"content-security-policy": "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; media-src 'self' https:; connect-src 'self' https://api.github.com https://api.fiscaldata.treasury.gov https://plugins.gloom.sh; form-action 'self'; upgrade-insecure-requests",
|
|
57
|
+
"content-security-policy": "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; media-src 'self' https:; connect-src 'self' https://api.github.com https://api.fiscaldata.treasury.gov https://plugins.gloom.sh https://gloom.sh; form-action 'self'; upgrade-insecure-requests",
|
|
58
58
|
"cross-origin-opener-policy": "same-origin",
|
|
59
59
|
"cross-origin-resource-policy": "same-origin",
|
|
60
60
|
"permissions-policy": "camera=(), geolocation=(), microphone=(), payment=(), usb=()",
|
|
@@ -7,7 +7,9 @@ export function useFrozenColumnInsets(enabled: boolean, scrollLeft: number, view
|
|
|
7
7
|
useLayoutEffect(() => {
|
|
8
8
|
const cells = ref.current?.children;
|
|
9
9
|
if (!enabled || !cells?.length) {
|
|
10
|
-
|
|
10
|
+
// Most tables freeze nothing: leave their rows' state alone, since a
|
|
11
|
+
// state update from a layout effect costs every render a second commit.
|
|
12
|
+
if (insets.length) setInsets([]);
|
|
11
13
|
return;
|
|
12
14
|
}
|
|
13
15
|
const first = cells[0]!.getBoundingClientRect();
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
hasMeaningfulTableHorizontalOverflow,
|
|
27
27
|
} from "../../../components/ui/table-layout";
|
|
28
28
|
import { WEB_CELL_HEIGHT, WEB_CELL_WIDTH } from "../../../theme/font-scale";
|
|
29
|
+
import { isLiveResizing, onLiveResizeEnd } from "../../../ui/live-resize";
|
|
29
30
|
import { useScrollbarActivity } from "../scrollbar-activity";
|
|
30
31
|
import { useHorizontalScrollEdges } from "../host/overflow-fade";
|
|
31
32
|
import {
|
|
@@ -214,12 +215,29 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
|
|
|
214
215
|
scheduleVisibleRangeMeasure();
|
|
215
216
|
const element = bodyElementRef.current;
|
|
216
217
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
217
|
-
const
|
|
218
|
+
const measure = () => {
|
|
218
219
|
scheduleViewportWidthMeasure();
|
|
219
220
|
scheduleVisibleRangeMeasure();
|
|
221
|
+
};
|
|
222
|
+
// While the pointer resizes the pane, its columns stretch by CSS and the
|
|
223
|
+
// pane renders the table at the new size a few times a second; measuring
|
|
224
|
+
// on every cell the body crosses would render it once per cell. It is
|
|
225
|
+
// measured once the resize ends, a frame after its layout lands.
|
|
226
|
+
let measureAfterResize = false;
|
|
227
|
+
const observer = new ResizeObserver(() => {
|
|
228
|
+
if (isLiveResizing()) measureAfterResize = true;
|
|
229
|
+
else measure();
|
|
230
|
+
});
|
|
231
|
+
const stopListening = onLiveResizeEnd(() => {
|
|
232
|
+
if (!measureAfterResize) return;
|
|
233
|
+
measureAfterResize = false;
|
|
234
|
+
measure();
|
|
220
235
|
});
|
|
221
236
|
observer.observe(element);
|
|
222
|
-
return () =>
|
|
237
|
+
return () => {
|
|
238
|
+
observer.disconnect();
|
|
239
|
+
stopListening();
|
|
240
|
+
};
|
|
223
241
|
}, [measureViewportWidth, scheduleViewportWidthMeasure, scheduleVisibleRangeMeasure]);
|
|
224
242
|
|
|
225
243
|
useEffect(() => {
|
|
@@ -310,8 +328,9 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
|
|
|
310
328
|
const next = frozenCell && body
|
|
311
329
|
? Math.max(0, frozenCell.getBoundingClientRect().right - body.getBoundingClientRect().left + columnGap * WEB_CELL_WIDTH)
|
|
312
330
|
: 0;
|
|
313
|
-
|
|
314
|
-
|
|
331
|
+
// Set only on a change: a state update from a layout effect costs the render a second commit.
|
|
332
|
+
if (next !== frozenEdgePx) setFrozenEdgePx(next);
|
|
333
|
+
}, [columnGap, columns, freezeFirstColumn, frozenEdgePx, overflowEdges.start, viewportWidth]);
|
|
315
334
|
|
|
316
335
|
const rootStyle: CSSProperties = {
|
|
317
336
|
position: "relative",
|
|
@@ -323,6 +342,12 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
|
|
|
323
342
|
minHeight: 0,
|
|
324
343
|
backgroundColor: CSS_BG,
|
|
325
344
|
overflow: "hidden",
|
|
345
|
+
// Its width comes from where it sits, never from its columns. When the
|
|
346
|
+
// columns overflow, the content is laid out at their full width; in a box
|
|
347
|
+
// that sizes to its content (a pane's side beside a sidebar), that widened
|
|
348
|
+
// the box until they fit, which turned the scrolling off and narrowed it
|
|
349
|
+
// again: a measure and a render every frame, at rest.
|
|
350
|
+
contain: "inline-size",
|
|
326
351
|
};
|
|
327
352
|
const bodyScrollerStyle: CSSProperties = {
|
|
328
353
|
width: "100%",
|
|
@@ -386,7 +411,7 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
|
|
|
386
411
|
columns={columns}
|
|
387
412
|
freezeFirstColumn={freezeFirstColumn}
|
|
388
413
|
scrollLeft={frozenScrollLeft}
|
|
389
|
-
viewportWidth={viewportWidth}
|
|
414
|
+
viewportWidth={freezeFirstColumn ? viewportWidth : 0}
|
|
390
415
|
columnGap={columnGap}
|
|
391
416
|
horizontalPadding={horizontalPadding}
|
|
392
417
|
focusPane={focusPane}
|
|
@@ -433,7 +458,9 @@ export function WebDataTable<T, C extends DataTableColumn = DataTableColumn>({
|
|
|
433
458
|
columns={columns}
|
|
434
459
|
freezeFirstColumn={freezeFirstColumn}
|
|
435
460
|
scrollLeft={frozenScrollLeft}
|
|
436
|
-
|
|
461
|
+
// Only a frozen first column places itself by it: every
|
|
462
|
+
// other row stays memoized when the viewport changes width.
|
|
463
|
+
viewportWidth={freezeFirstColumn ? viewportWidth : 0}
|
|
437
464
|
columnGap={columnGap}
|
|
438
465
|
horizontalPadding={horizontalPadding}
|
|
439
466
|
focusPane={focusPane}
|
|
@@ -267,6 +267,7 @@ function WebDataTableRowInner<
|
|
|
267
267
|
if (sectionHeader) {
|
|
268
268
|
// A header the cursor can land on (a collapsible group) shows it like a row.
|
|
269
269
|
const headerColor = sectionHeader.color ?? (selected ? CSS_SELECTED_TEXT : CSS_TEXT_BRIGHT);
|
|
270
|
+
const action = sectionHeader.action;
|
|
270
271
|
return (
|
|
271
272
|
<div
|
|
272
273
|
key={itemKey}
|
|
@@ -298,12 +299,37 @@ function WebDataTableRowInner<
|
|
|
298
299
|
display: "flex",
|
|
299
300
|
alignItems: "center",
|
|
300
301
|
gap: 4,
|
|
302
|
+
// Kept to the columns in view, so a table wider than its pane does not push the action out of sight.
|
|
303
|
+
...(action && viewportWidth > 0 ? { maxWidth: Math.max(0, viewportWidth * WEB_CELL_WIDTH - inlinePaddingPx(horizontalPadding) * 2) } : {}),
|
|
301
304
|
}}
|
|
302
305
|
>
|
|
303
306
|
{sectionHeader.expanded !== undefined && (
|
|
304
307
|
<DisclosureMarker expanded={sectionHeader.expanded} color={headerColor} />
|
|
305
308
|
)}
|
|
306
|
-
{
|
|
309
|
+
{action ? (
|
|
310
|
+
<>
|
|
311
|
+
<span style={{ flex: "0 1 auto", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis" }}>{sectionHeader.text}</span>
|
|
312
|
+
<button
|
|
313
|
+
type="button"
|
|
314
|
+
data-gloom-role="data-table-section-action"
|
|
315
|
+
title={action.title ?? action.label}
|
|
316
|
+
aria-haspopup="dialog"
|
|
317
|
+
style={{ color: selected ? CSS_SELECTED_TEXT : CSS_TEXT }}
|
|
318
|
+
onMouseDown={(event) => {
|
|
319
|
+
// The action, not the header's own press (a group's collapse).
|
|
320
|
+
event.stopPropagation();
|
|
321
|
+
focusPane();
|
|
322
|
+
}}
|
|
323
|
+
onClick={(event) => {
|
|
324
|
+
event.stopPropagation();
|
|
325
|
+
action.onPress();
|
|
326
|
+
}}
|
|
327
|
+
>
|
|
328
|
+
{action.label}
|
|
329
|
+
<WebIcon name="chevron-down" size={9} />
|
|
330
|
+
</button>
|
|
331
|
+
</>
|
|
332
|
+
) : sectionHeader.text}
|
|
307
333
|
</div>
|
|
308
334
|
</div>
|
|
309
335
|
);
|
|
@@ -355,6 +381,8 @@ function WebDataTableRowInner<
|
|
|
355
381
|
data-gloom-role="data-table-cell"
|
|
356
382
|
// The instant behind a shortened time ("Wed 11:27"), so a rendered-view report can print it whole.
|
|
357
383
|
data-gloom-cell-instant={cell.value instanceof Date && Number.isFinite(cell.value.getTime()) ? cell.value.toISOString() : undefined}
|
|
384
|
+
// The full-precision number behind a rounded cell (a trade of -9.4596 for -9.45963753), for the same reports.
|
|
385
|
+
data-gloom-cell-value={typeof cell.value === "number" && Number.isFinite(cell.value) ? String(cell.value) : undefined}
|
|
358
386
|
style={{
|
|
359
387
|
minWidth: 0,
|
|
360
388
|
position: freezeFirstColumn && columnIndex === 0 ? "sticky" : undefined,
|
|
@@ -365,6 +393,7 @@ function WebDataTableRowInner<
|
|
|
365
393
|
boxSizing: "border-box",
|
|
366
394
|
height: WEB_CELL_HEIGHT,
|
|
367
395
|
overflow: "hidden",
|
|
396
|
+
cursor: cell.onMouseDown ? "pointer" : undefined,
|
|
368
397
|
backgroundColor: cell.backgroundColor ?? rowBg,
|
|
369
398
|
boxShadow: freezeFirstColumn && columnIndex === 0 ? `-${inlinePaddingPx(horizontalPadding)}px 0 0 ${cell.backgroundColor ?? rowBg}, ${columnGap * WEB_CELL_WIDTH}px 0 0 ${cell.backgroundColor ?? rowBg}` : undefined,
|
|
370
399
|
}}
|
|
@@ -25,12 +25,74 @@ export function controlBorderColor(focused = false, active = false, palette: The
|
|
|
25
25
|
return panelBorder(palette);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function activeHalo(palette: ThemeColors): string {
|
|
29
|
+
return `0 0 0 1px ${blendHex(palette.bg, palette.borderFocused, 0.18)}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
export function controlShadow(active = false, palette: ThemeColors = colors): string {
|
|
29
33
|
return active
|
|
30
|
-
?
|
|
34
|
+
? `${activeHalo(palette)}, inset 0 1px 0 ${blendHex(palette.bg, palette.textBright, 0.06)}`
|
|
31
35
|
: `inset 0 1px 0 ${blendHex(palette.bg, palette.textBright, 0.04)}`;
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
const WHITE = "#ffffff";
|
|
39
|
+
const BLACK = "#000000";
|
|
40
|
+
|
|
41
|
+
function withAlpha(hex: string, alpha: number): string {
|
|
42
|
+
return `${hex}${Math.round(alpha * 255).toString(16).padStart(2, "0")}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** How far a raised button's tones move from its fill, toward white at the top and black below. */
|
|
46
|
+
const SOLID_RELIEF = { light: 0.12, shade: 0.06, edge: 0.18, shadow: 0.3 };
|
|
47
|
+
const SURFACE_RELIEF = { light: 0.05, shade: 0.03, edge: 0.08, shadow: 0.14 };
|
|
48
|
+
|
|
49
|
+
interface ButtonRelief {
|
|
50
|
+
backgroundImage?: string;
|
|
51
|
+
boxShadow: string;
|
|
52
|
+
/** Replaces the border colour, so a solid fill runs to its edge. */
|
|
53
|
+
borderColor?: string;
|
|
54
|
+
/** What the button shows while it is held down. */
|
|
55
|
+
pressedImage?: string;
|
|
56
|
+
pressedShadow?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Light from above, built from the button's own fill so it reads the same on
|
|
61
|
+
* any surface and in every theme: a little lighter at the top, a little darker
|
|
62
|
+
* toward the bottom, a darker band on the bottom edge and a soft shadow under
|
|
63
|
+
* it. Nothing draws a line along the top edge. Held down, the light flips and
|
|
64
|
+
* the shadow goes, so the button sinks.
|
|
65
|
+
*/
|
|
66
|
+
function raisedRelief(fill: string, tone: typeof SOLID_RELIEF, ring?: string): ButtonRelief {
|
|
67
|
+
const shade = blendHex(fill, BLACK, tone.shade);
|
|
68
|
+
const edge = blendHex(fill, BLACK, tone.edge);
|
|
69
|
+
const drop = `0 1px 2px ${withAlpha(blendHex(fill, BLACK, 0.75), tone.shadow)}`;
|
|
70
|
+
return {
|
|
71
|
+
backgroundImage: `linear-gradient(${blendHex(fill, WHITE, tone.light)}, ${shade} calc(100% - 1px), ${edge} calc(100% - 1px))`,
|
|
72
|
+
boxShadow: ring ? `${ring}, ${drop}` : drop,
|
|
73
|
+
pressedImage: `linear-gradient(${shade}, ${fill})`,
|
|
74
|
+
pressedShadow: ring ?? "none",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* A button's relief. Primary, danger and a selected button are raised from
|
|
80
|
+
* their fill; a secondary one gets the same light, fainter. Ghost and plain
|
|
81
|
+
* buttons have no fill to light and stay flat, and so does a disabled one.
|
|
82
|
+
*/
|
|
83
|
+
export function buttonRelief(
|
|
84
|
+
props: Pick<ButtonProps, "variant" | "active" | "disabled">,
|
|
85
|
+
palette: ThemeColors = colors,
|
|
86
|
+
): ButtonRelief {
|
|
87
|
+
if (props.variant === "plain" || props.variant === "ghost" || props.disabled) return { boxShadow: "none" };
|
|
88
|
+
const fill = buttonPalette(props, palette).bg;
|
|
89
|
+
if (props.active) return raisedRelief(fill, SOLID_RELIEF, `0 0 0 1px ${withAlpha(palette.borderFocused, 0.18)}`);
|
|
90
|
+
if (props.variant === "primary" || props.variant === "danger") {
|
|
91
|
+
return { ...raisedRelief(fill, SOLID_RELIEF), borderColor: "transparent" };
|
|
92
|
+
}
|
|
93
|
+
return raisedRelief(fill, SURFACE_RELIEF);
|
|
94
|
+
}
|
|
95
|
+
|
|
34
96
|
export function buttonPalette(
|
|
35
97
|
props: Pick<ButtonProps, "variant" | "active" | "disabled">,
|
|
36
98
|
palette: ThemeColors = colors,
|