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,527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns the text of an indexed article, call or filing into blocks a reader
|
|
3
|
+
* can lay out: paragraphs of a few sentences, headings, lists and tables, with
|
|
4
|
+
* web page chrome and wire boilerplate left out.
|
|
5
|
+
*
|
|
6
|
+
* Everything here is extractive. Lines are dropped only when they match a
|
|
7
|
+
* known kind of page furniture as a whole ("Share this article", a cookie
|
|
8
|
+
* banner, the headline printed again), sentences are never reworded, and a
|
|
9
|
+
* paragraph is split only between sentences. When a rule is unsure it keeps
|
|
10
|
+
* the text: a stray share link costs a glance, a lost sentence costs the
|
|
11
|
+
* story. The reader keeps the raw text one action away for the same reason.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type ArticleBlock =
|
|
15
|
+
| { kind: "paragraph"; text: string; section: number }
|
|
16
|
+
| { kind: "heading"; text: string; section: number }
|
|
17
|
+
| { kind: "list"; items: string[]; section: number }
|
|
18
|
+
| { kind: "table"; rows: string[][]; section: number };
|
|
19
|
+
|
|
20
|
+
export interface ArticleSection {
|
|
21
|
+
text: string;
|
|
22
|
+
/** Who or what the section is: a speaker, a filing section. Shown as its heading when it changes. */
|
|
23
|
+
heading?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ParseArticleOptions {
|
|
27
|
+
/** The headline, dropped where the page prints it again. */
|
|
28
|
+
title?: string;
|
|
29
|
+
/** The publisher or wire, dropped where the page prints it again. */
|
|
30
|
+
source?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Leave out web page chrome and wire boilerplate. For news; a transcript or
|
|
33
|
+
* a filing is kept as written.
|
|
34
|
+
*/
|
|
35
|
+
clean?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** About three lines at a reading measure: the most a paragraph should hold. */
|
|
39
|
+
const PARAGRAPH_TARGET_WORDS = 45;
|
|
40
|
+
/** How far into an article page furniture (bylines, datelines, share rows) is looked for. */
|
|
41
|
+
const HEADER_LINES = 10;
|
|
42
|
+
|
|
43
|
+
const WORD = /[\p{L}\p{N}][\p{L}\p{N}'’.,$%&/-]*/gu;
|
|
44
|
+
|
|
45
|
+
export function countWords(text: string): number {
|
|
46
|
+
return text.match(WORD)?.length ?? 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function normalizeKey(text: string): string {
|
|
50
|
+
return text.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Sentences
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Words that end in a period without ending the sentence. Lowercased, without
|
|
58
|
+
* the period. Initials (J.), dotted acronyms (U.S.) and months are covered by
|
|
59
|
+
* patterns below.
|
|
60
|
+
*/
|
|
61
|
+
const ABBREVIATIONS = new Set([
|
|
62
|
+
"mr", "mrs", "ms", "dr", "prof", "sr", "jr", "st", "mt", "ft", "ave", "blvd",
|
|
63
|
+
"inc", "corp", "co", "ltd", "plc", "llc", "lp", "bros", "dept", "no", "nos",
|
|
64
|
+
"vs", "etc", "approx", "est", "fig", "gov", "sen", "rep", "gen", "lt", "col",
|
|
65
|
+
"capt", "sgt", "rev", "hon", "pres", "vol", "op", "cf", "al",
|
|
66
|
+
"jan", "feb", "mar", "apr", "jun", "jul", "aug", "sep", "sept", "oct", "nov", "dec",
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
function endsWithAbbreviation(before: string): boolean {
|
|
70
|
+
const token = /(\S+)$/.exec(before)?.[1] ?? "";
|
|
71
|
+
const bare = token.replace(/^[("'“‘[]+/, "");
|
|
72
|
+
// "J." and "U.S." and "e.g.": a dot inside the word, or a single letter.
|
|
73
|
+
if (/^\p{L}$/u.test(bare)) return true;
|
|
74
|
+
if (/^(?:\p{L}\.)+\p{L}?$/u.test(bare)) return true;
|
|
75
|
+
return ABBREVIATIONS.has(bare.toLowerCase());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Splits text into sentences at a period, question or exclamation mark
|
|
80
|
+
* (with any closing quote or bracket) followed by a space and a capital,
|
|
81
|
+
* an opening quote or a bracket. Never after an abbreviation or an initial,
|
|
82
|
+
* and never before a digit, so "No. 5" and "Oct. 10" hold together. Unsure
|
|
83
|
+
* cases stay one sentence: a missed break costs nothing in a reader.
|
|
84
|
+
*/
|
|
85
|
+
export function splitSentences(text: string): string[] {
|
|
86
|
+
const sentences: string[] = [];
|
|
87
|
+
const boundary = /([.!?\u2026]+["'\u201d\u2019)\]]*)\s+(?=["'\u201c\u2018(\[]?\p{Lu})/gu;
|
|
88
|
+
let start = 0;
|
|
89
|
+
for (let match = boundary.exec(text); match; match = boundary.exec(text)) {
|
|
90
|
+
const punctuation = match[1]!;
|
|
91
|
+
// "Inc." or "U.S." before a name is part of the sentence; an ellipsis is not an abbreviation.
|
|
92
|
+
if (punctuation[0] === "." && !punctuation.startsWith("..") && endsWithAbbreviation(text.slice(start, match.index))) continue;
|
|
93
|
+
const sentence = text.slice(start, match.index + punctuation.length).trim();
|
|
94
|
+
if (sentence) sentences.push(sentence);
|
|
95
|
+
start = match.index + match[0].length;
|
|
96
|
+
}
|
|
97
|
+
const rest = text.slice(start).trim();
|
|
98
|
+
if (rest) sentences.push(rest);
|
|
99
|
+
return sentences;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Where to break `counts` (words per sentence) into `groups` runs so each run
|
|
104
|
+
* is as close to the same size as it can be: a linear partition, small enough
|
|
105
|
+
* to solve exactly for any paragraph a page holds.
|
|
106
|
+
*/
|
|
107
|
+
function balancedBreaks(counts: number[], groups: number): number[] {
|
|
108
|
+
const n = counts.length;
|
|
109
|
+
const prefix = [0];
|
|
110
|
+
for (const count of counts) prefix.push(prefix[prefix.length - 1]! + count);
|
|
111
|
+
const budget = prefix[n]! / groups;
|
|
112
|
+
const cost = (from: number, to: number) => (prefix[to]! - prefix[from]! - budget) ** 2;
|
|
113
|
+
// best[g][j]: the least cost of the first j sentences in g runs; from[g][j]: where its last run starts.
|
|
114
|
+
const best = Array.from({ length: groups + 1 }, () => new Array<number>(n + 1).fill(Infinity));
|
|
115
|
+
const from = Array.from({ length: groups + 1 }, () => new Array<number>(n + 1).fill(0));
|
|
116
|
+
best[0]![0] = 0;
|
|
117
|
+
for (let g = 1; g <= groups; g += 1) {
|
|
118
|
+
for (let j = g; j <= n; j += 1) {
|
|
119
|
+
for (let i = g - 1; i < j; i += 1) {
|
|
120
|
+
const value = best[g - 1]![i]! + cost(i, j);
|
|
121
|
+
if (value < best[g]![j]!) {
|
|
122
|
+
best[g]![j] = value;
|
|
123
|
+
from[g]![j] = i;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const breaks: number[] = [];
|
|
129
|
+
for (let g = groups, j = n; g > 0; g -= 1) {
|
|
130
|
+
j = from[g]![j]!;
|
|
131
|
+
breaks.unshift(j);
|
|
132
|
+
}
|
|
133
|
+
return breaks;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Splits a long paragraph between sentences into runs of about
|
|
138
|
+
* `targetWords`, as even as the sentences allow. A paragraph within a third
|
|
139
|
+
* of the target, or one long sentence, stays whole.
|
|
140
|
+
*/
|
|
141
|
+
export function splitParagraph(text: string, targetWords = PARAGRAPH_TARGET_WORDS): string[] {
|
|
142
|
+
const total = countWords(text);
|
|
143
|
+
if (total <= Math.round(targetWords * 4 / 3)) return [text];
|
|
144
|
+
const sentences = splitSentences(text);
|
|
145
|
+
if (sentences.length < 2) return [text];
|
|
146
|
+
const counts = sentences.map(countWords);
|
|
147
|
+
const groups = Math.min(sentences.length, Math.ceil(total / targetWords));
|
|
148
|
+
const breaks = balancedBreaks(counts, groups);
|
|
149
|
+
return breaks.map((start, index) => sentences.slice(start, breaks[index + 1] ?? sentences.length).join(" "));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Page furniture
|
|
154
|
+
|
|
155
|
+
const SHARE_TARGETS = "x|twitter|facebook|linkedin|email|e-mail|whatsapp|reddit|threads|bluesky|telegram|pinterest|mastodon";
|
|
156
|
+
|
|
157
|
+
/** Whole lines that are page chrome wherever they appear. Matched case-insensitively against the trimmed line. */
|
|
158
|
+
const CHROME_LINES: RegExp[] = [
|
|
159
|
+
/^share (?:this|the) (?:article|story|post|page)$/,
|
|
160
|
+
new RegExp(`^share (?:to|on|via|with) (?:${SHARE_TARGETS})$`),
|
|
161
|
+
new RegExp(`^(?:${SHARE_TARGETS})$`),
|
|
162
|
+
/^(?:share|tweet|print|copy link|copy url|save|bookmark|print this (?:page|article)|email this (?:page|article))$/,
|
|
163
|
+
/^(?:advertisement|sponsored(?: content)?|ad|story continues below(?: advertisement)?)$/,
|
|
164
|
+
/^(?:listen to (?:this )?(?:article|story)|\d+\s*min(?:ute)?s?\s+read)$/,
|
|
165
|
+
/^(?:accept|accept all|accept all cookies|accept cookies|reject all|manage (?:cookie )?preferences|cookie settings|cookie policy)$/,
|
|
166
|
+
/^view (?:the )?original content\b.*$/,
|
|
167
|
+
/^(?:skip to (?:main )?content|back to top|return to top)$/,
|
|
168
|
+
/^follow us on\b.{0,60}$/,
|
|
169
|
+
/^(?:related(?: articles| stories| news)?|recommended(?: for you)?|more from [\p{L}\s]{1,30}|trending(?: now)?|see also)\s*:?$/u,
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
/** Lines that are page chrome only when they are short: a full sentence that mentions cookies is not a banner. */
|
|
173
|
+
function isShortChrome(line: string, words: number): boolean {
|
|
174
|
+
const lower = line.toLowerCase();
|
|
175
|
+
if (words <= 40 && /\b(?:(?:we|this (?:site|website)|our (?:site|website)) uses? cookies|use of cookies|accept (?:all )?cookies|cookie (?:policy|preferences|settings|consent|notice))\b/.test(lower)) return true;
|
|
176
|
+
if (words <= 16 && /^(?:subscribe|sign up|join)\b/.test(lower) && /\b(?:newsletter|updates|alerts|inbox|our|free)\b/.test(lower)) return true;
|
|
177
|
+
if (words <= 12 && /^(?:click here|tap here)\b/.test(lower)) return true;
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const MONTH = "(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|june?|july?|aug(?:ust)?|sep(?:t(?:ember)?)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)";
|
|
182
|
+
const DATE_TEXT = `(?:(?:mon|tue|wed|thu|fri|sat|sun)[a-z]*,?\\s+)?(?:${MONTH}\\.?\\s+\\d{1,2}(?:st|nd|rd|th)?,?\\s+\\d{4}|\\d{1,2}\\s+${MONTH}\\.?,?\\s+\\d{4}|\\d{1,4}[/-]\\d{1,2}[/-]\\d{1,4})`;
|
|
183
|
+
const TIME_TEXT = "(?:,?\\s*(?:at\\s+)?\\d{1,2}(?::\\d{2})?\\s*(?:[ap]\\.?m\\.?)?(?:\\s*[a-z]{2,4})?)?";
|
|
184
|
+
/** A line that is only a date and maybe a time: the reader's header already says when. */
|
|
185
|
+
const DATE_LINE = new RegExp(`^(?:(?:updated|published|posted|last updated)(?: on)?:?\\s*)?${DATE_TEXT}${TIME_TEXT}$`, "i");
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The dateline a wire story opens with: a place in capitals, an optional
|
|
189
|
+
* date, then the wire's name, then a dash. "BOSTON, Oct. 9, 2026 /Wirefeed/ --",
|
|
190
|
+
* "NEW YORK, Oct. 9, 2026 (GLOBE NEWSWIRE) --", "SAN FRANCISCO--(BUSINESS WIRE)--".
|
|
191
|
+
* Only taken with the wire tag present, so an ordinary opening in capitals stays.
|
|
192
|
+
*/
|
|
193
|
+
const WIRE_DATELINE = new RegExp(
|
|
194
|
+
"^[A-Z][A-Z .,'’&-]{1,60}(?:,\\s*[A-Z][A-Za-z.]{1,15}\\.?)?\\s*,?\\s*"
|
|
195
|
+
+ `(?:${DATE_TEXT}\\s*)?`
|
|
196
|
+
+ "(?:/[^/\\n]{2,40}/|\\([A-Z][A-Z .&-]{2,40}\\)|--\\([A-Z][A-Z .&-]{2,40}\\))\\s*(?:--|—|–|-)\\s*",
|
|
197
|
+
"i",
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
function stripWireDateline(line: string): string {
|
|
201
|
+
const match = WIRE_DATELINE.exec(line);
|
|
202
|
+
if (!match) return line;
|
|
203
|
+
// The place has to be in capitals; the "i" flag only loosens the date.
|
|
204
|
+
const place = /^[^,/(-]+/.exec(match[0])?.[0] ?? "";
|
|
205
|
+
if (place !== place.toUpperCase()) return line;
|
|
206
|
+
const rest = line.slice(match[0].length).trim();
|
|
207
|
+
return rest.length > 0 ? rest : line;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
interface CleanContext {
|
|
211
|
+
title: string;
|
|
212
|
+
source: string;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Lines of the page with chrome removed. `inHeader` lines (the top of the
|
|
217
|
+
* article) also lose a repeated headline or source, a date standing alone,
|
|
218
|
+
* and the "News provided by" credit with the name under it.
|
|
219
|
+
*/
|
|
220
|
+
function cleanLines(lines: string[], context: CleanContext, startIndex: number): string[] {
|
|
221
|
+
const kept: string[] = [];
|
|
222
|
+
let skipNextName = false;
|
|
223
|
+
for (const [offset, raw] of lines.entries()) {
|
|
224
|
+
const line = raw.trim();
|
|
225
|
+
if (!line) {
|
|
226
|
+
kept.push("");
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const lower = line.toLowerCase();
|
|
230
|
+
const words = countWords(line);
|
|
231
|
+
const inHeader = startIndex + offset < HEADER_LINES;
|
|
232
|
+
if (skipNextName) {
|
|
233
|
+
skipNextName = false;
|
|
234
|
+
// The credited name: short, and no sentence in it ("Acme Inc." is a name).
|
|
235
|
+
if (words <= 6 && (!/[.!?]$/.test(line) || endsWithAbbreviation(line.slice(0, -1)))) continue;
|
|
236
|
+
}
|
|
237
|
+
if (/^(?:news|content|story) provided by\b:?$/i.test(line)) {
|
|
238
|
+
skipNextName = true;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (CHROME_LINES.some((pattern) => pattern.test(lower))) continue;
|
|
242
|
+
if (isShortChrome(line, words)) continue;
|
|
243
|
+
if (inHeader) {
|
|
244
|
+
const key = normalizeKey(line);
|
|
245
|
+
if (context.title && key === context.title) continue;
|
|
246
|
+
if (context.source && key === context.source) continue;
|
|
247
|
+
if (words <= 12 && DATE_LINE.test(line)) continue;
|
|
248
|
+
}
|
|
249
|
+
// "SOURCE Acme Inc." closes a wire release: who sent it, said again.
|
|
250
|
+
if (/^SOURCE\s+\S/.test(line) && words <= 8) continue;
|
|
251
|
+
kept.push(inHeader ? stripWireDateline(line) : line);
|
|
252
|
+
}
|
|
253
|
+
return kept;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// Blocks
|
|
258
|
+
|
|
259
|
+
const LIST_ITEM = /^(?:[•·▪●◦‣∙*]|[-–—](?=\s)|\d{1,2}[.)](?=\s))\s*(.+)$/u;
|
|
260
|
+
const TABLE_SPLIT = /\t+|\s{2,}|\s*\|\s*/;
|
|
261
|
+
const TERMINAL = /[.!?:;,"”’)\]…]$/u;
|
|
262
|
+
|
|
263
|
+
function tableCells(line: string): string[] | null {
|
|
264
|
+
const trimmed = line.trim().replace(/^\||\|$/g, "");
|
|
265
|
+
const cells = trimmed.split(TABLE_SPLIT).map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
266
|
+
return cells.length >= 2 ? cells : null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Collapses runs of spaces and tidies the gaps wire text leaves inside brackets. */
|
|
270
|
+
function tidy(text: string): string {
|
|
271
|
+
return text
|
|
272
|
+
.replace(/\s+/g, " ")
|
|
273
|
+
.replace(/([([])\s+/g, "$1")
|
|
274
|
+
.replace(/\s+([)\],;])/g, "$1")
|
|
275
|
+
.trim();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
type RawBlock =
|
|
279
|
+
| { kind: "text"; text: string }
|
|
280
|
+
| { kind: "list"; items: string[] }
|
|
281
|
+
| { kind: "table"; rows: string[][] };
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Groups cleaned lines into blocks. A blank line always ends a block. Where
|
|
285
|
+
* the source never uses blank lines, every line is its own block, except a
|
|
286
|
+
* line that plainly continues the one before (it starts in lowercase after a
|
|
287
|
+
* line with no closing punctuation). Where it does use them, single line
|
|
288
|
+
* breaks inside a block are soft wraps.
|
|
289
|
+
*/
|
|
290
|
+
function groupLines(lines: string[]): RawBlock[] {
|
|
291
|
+
const blankSeparated = lines.some((line, index) => line === "" && index > 0 && index < lines.length - 1);
|
|
292
|
+
const blocks: RawBlock[] = [];
|
|
293
|
+
let index = 0;
|
|
294
|
+
while (index < lines.length) {
|
|
295
|
+
const line = lines[index]!;
|
|
296
|
+
if (!line) {
|
|
297
|
+
index += 1;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
// A run of two or more lines that split into the same number of cells.
|
|
301
|
+
const cells = tableCells(line);
|
|
302
|
+
if (cells) {
|
|
303
|
+
const rows = [cells];
|
|
304
|
+
let next = index + 1;
|
|
305
|
+
while (next < lines.length) {
|
|
306
|
+
const nextCells = lines[next] ? tableCells(lines[next]!) : null;
|
|
307
|
+
if (!nextCells || nextCells.length !== cells.length) break;
|
|
308
|
+
rows.push(nextCells);
|
|
309
|
+
next += 1;
|
|
310
|
+
}
|
|
311
|
+
if (rows.length >= 2) {
|
|
312
|
+
blocks.push({ kind: "table", rows });
|
|
313
|
+
index = next;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const item = LIST_ITEM.exec(line);
|
|
318
|
+
if (item) {
|
|
319
|
+
const items = [tidy(item[1]!)];
|
|
320
|
+
let next = index + 1;
|
|
321
|
+
while (next < lines.length) {
|
|
322
|
+
const nextItem = lines[next] ? LIST_ITEM.exec(lines[next]!) : null;
|
|
323
|
+
if (!nextItem) break;
|
|
324
|
+
items.push(tidy(nextItem[1]!));
|
|
325
|
+
next += 1;
|
|
326
|
+
}
|
|
327
|
+
// One dash-led line is a sentence, not a list.
|
|
328
|
+
if (items.length >= 2 || !/^[-–—]/.test(line)) {
|
|
329
|
+
blocks.push({ kind: "list", items });
|
|
330
|
+
index = next;
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
let text = line;
|
|
335
|
+
let next = index + 1;
|
|
336
|
+
while (next < lines.length && lines[next]) {
|
|
337
|
+
const following = lines[next]!;
|
|
338
|
+
if (LIST_ITEM.test(following) || tableCells(following)) break;
|
|
339
|
+
const continues = blankSeparated || (!TERMINAL.test(text) && /^[\p{Ll}\d($€£¥%&,;]/u.test(following));
|
|
340
|
+
if (!continues) break;
|
|
341
|
+
text = `${text} ${following}`;
|
|
342
|
+
next += 1;
|
|
343
|
+
}
|
|
344
|
+
blocks.push({ kind: "text", text: tidy(text) });
|
|
345
|
+
index = next;
|
|
346
|
+
}
|
|
347
|
+
return blocks;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/** Bullets run together on one line: "Highlights: • Revenue up 8% • Margin 46%". */
|
|
351
|
+
function splitInlineBullets(text: string): { lead: string; items: string[] } | null {
|
|
352
|
+
const parts = text.split(/\s+[•▪●]\s+/u);
|
|
353
|
+
if (parts.length < 3) return null;
|
|
354
|
+
const [lead, ...items] = parts;
|
|
355
|
+
return { lead: lead!.replace(/^[•▪●]\s*/u, "").trim(), items: items.map(tidy).filter(Boolean) };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* A short line with no closing punctuation, followed by a paragraph, reads as
|
|
360
|
+
* the heading of what follows: a company name before its news, "Outlook"
|
|
361
|
+
* before the guidance.
|
|
362
|
+
*/
|
|
363
|
+
function isHeading(text: string, next: RawBlock | undefined): boolean {
|
|
364
|
+
if (!next || next.kind !== "text") return false;
|
|
365
|
+
if (TERMINAL.test(text) && !/\)$/.test(text)) return false;
|
|
366
|
+
if (text.length > 90 || countWords(text) > 12) return false;
|
|
367
|
+
if (!/^[\p{Lu}\d"“]/u.test(text)) return false;
|
|
368
|
+
return countWords(next.text) > countWords(text) * 2;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export function parseArticle(sections: ArticleSection[], options: ParseArticleOptions = {}): ArticleBlock[] {
|
|
372
|
+
const context: CleanContext = {
|
|
373
|
+
title: options.title ? normalizeKey(options.title) : "",
|
|
374
|
+
source: options.source ? normalizeKey(options.source) : "",
|
|
375
|
+
};
|
|
376
|
+
const blocks: ArticleBlock[] = [];
|
|
377
|
+
let lineIndex = 0;
|
|
378
|
+
let previousHeading: string | undefined;
|
|
379
|
+
for (const [section, entry] of sections.entries()) {
|
|
380
|
+
const heading = entry.heading?.trim();
|
|
381
|
+
if (heading && heading !== previousHeading) {
|
|
382
|
+
blocks.push({ kind: "heading", text: heading, section });
|
|
383
|
+
}
|
|
384
|
+
previousHeading = heading || previousHeading;
|
|
385
|
+
const rawLines = (entry.text ?? "").replace(/\r\n?/g, "\n").replace(/\u00a0/g, " ").split("\n");
|
|
386
|
+
const lines = options.clean ? cleanLines(rawLines, context, lineIndex) : rawLines.map((line) => line.trim());
|
|
387
|
+
lineIndex += rawLines.length;
|
|
388
|
+
const grouped = groupLines(lines);
|
|
389
|
+
for (const [index, raw] of grouped.entries()) {
|
|
390
|
+
if (raw.kind === "table") {
|
|
391
|
+
blocks.push({ kind: "table", rows: raw.rows, section });
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (raw.kind === "list") {
|
|
395
|
+
blocks.push({ kind: "list", items: raw.items, section });
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const inline = splitInlineBullets(raw.text);
|
|
399
|
+
if (inline) {
|
|
400
|
+
if (inline.lead) blocks.push({ kind: "paragraph", text: inline.lead, section });
|
|
401
|
+
blocks.push({ kind: "list", items: inline.items, section });
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (isHeading(raw.text, grouped[index + 1])) {
|
|
405
|
+
blocks.push({ kind: "heading", text: raw.text, section });
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
for (const paragraph of splitParagraph(raw.text)) {
|
|
409
|
+
blocks.push({ kind: "paragraph", text: paragraph, section });
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return blocks;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// ---------------------------------------------------------------------------
|
|
417
|
+
// Gist
|
|
418
|
+
|
|
419
|
+
export interface ArticleGist {
|
|
420
|
+
/** The opening paragraph, or the article's own summary. */
|
|
421
|
+
lead: string | null;
|
|
422
|
+
/** Up to three sentences of the article that each carry a figure and a move. */
|
|
423
|
+
facts: string[];
|
|
424
|
+
/** What follows the lead. */
|
|
425
|
+
body: ArticleBlock[];
|
|
426
|
+
words: number;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** Articles shorter than this are read whole; a facts list would only repeat them. */
|
|
430
|
+
const FACTS_MIN_WORDS = 250;
|
|
431
|
+
const MAX_FACTS = 3;
|
|
432
|
+
const FACT_FIGURE = /(?:[$€£¥]|\b[A-Z]{2,3}\$)\s?\d|\b\d[\d,]*(?:\.\d+)?\s?(?:%|percent\b|bps\b|basis points\b)/;
|
|
433
|
+
const FACT_MOVE = /\b(?:rose|rise[sn]?|fell|fall(?:s|en)?|gain(?:ed|s)?|lost|los(?:e|es|ing)|declin(?:ed|es|e)|increas(?:ed|es|e)|decreas(?:ed|es|e)|grew|grow(?:s|n)?|jump(?:ed|s)?|sl(?:id|ides?)|climb(?:ed|s)?|drop(?:ped|s)?|surg(?:ed|es)|plung(?:ed|es)|soar(?:ed|s)|tumbl(?:ed|es)|up|down|higher|lower|record|raised|cut|reported|guided)\b/i;
|
|
434
|
+
/** Openings that need the sentence before them to make sense. */
|
|
435
|
+
const DEPENDENT_OPENING = /^(?:it|its|they|their|this|that|these|those|he|she|his|her|we|our|but|and|so|also|however|meanwhile|the (?:company|stock|firm|group|index|shares))\b/i;
|
|
436
|
+
|
|
437
|
+
function isFact(sentence: string): boolean {
|
|
438
|
+
const words = countWords(sentence);
|
|
439
|
+
if (words < 6 || words > 30) return false;
|
|
440
|
+
if (!/[.!]$/.test(sentence)) return false;
|
|
441
|
+
if (DEPENDENT_OPENING.test(sentence)) return false;
|
|
442
|
+
// Someone or something named, past the first word.
|
|
443
|
+
if (!/\s\p{Lu}[\p{Ll}\p{Lu}]/u.test(sentence) && !/^\p{Lu}[\p{Ll}]+\s/u.test(sentence)) return false;
|
|
444
|
+
return FACT_FIGURE.test(sentence) && FACT_MOVE.test(sentence);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export function articleGist(blocks: ArticleBlock[], options: { summary?: string | null } = {}): ArticleGist {
|
|
448
|
+
const words = blocks.reduce((sum, block) => sum + blockWords(block), 0);
|
|
449
|
+
const summary = options.summary?.trim() ? tidy(options.summary) : null;
|
|
450
|
+
const firstIndex = blocks.findIndex((block) => block.kind === "paragraph");
|
|
451
|
+
const first = firstIndex >= 0 ? blocks[firstIndex] as Extract<ArticleBlock, { kind: "paragraph" }> : null;
|
|
452
|
+
// Only an opening paragraph leads: one that comes after a heading belongs to that heading.
|
|
453
|
+
const opensWithParagraph = first !== null && blocks.slice(0, firstIndex).every((block) => block.kind !== "heading");
|
|
454
|
+
|
|
455
|
+
let lead: string | null = null;
|
|
456
|
+
let body = blocks;
|
|
457
|
+
if (summary && (!first || normalizeKey(summary) !== normalizeKey(first.text))) {
|
|
458
|
+
lead = summary;
|
|
459
|
+
} else if (first && opensWithParagraph) {
|
|
460
|
+
lead = first.text;
|
|
461
|
+
body = blocks.filter((_, index) => index !== firstIndex);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const facts: string[] = [];
|
|
465
|
+
if (words >= FACTS_MIN_WORDS) {
|
|
466
|
+
const leadKey = lead ? normalizeKey(lead) : "";
|
|
467
|
+
for (const block of body) {
|
|
468
|
+
if (block.kind !== "paragraph") continue;
|
|
469
|
+
// One per paragraph, so the list spans the story instead of one passage.
|
|
470
|
+
const fact = splitSentences(block.text).find((sentence) => isFact(sentence) && !leadKey.includes(normalizeKey(sentence)));
|
|
471
|
+
if (fact) facts.push(fact);
|
|
472
|
+
if (facts.length === MAX_FACTS) break;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return { lead, facts: facts.length >= 2 ? facts : [], body, words };
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export function blockWords(block: ArticleBlock): number {
|
|
479
|
+
switch (block.kind) {
|
|
480
|
+
case "paragraph":
|
|
481
|
+
case "heading":
|
|
482
|
+
return countWords(block.text);
|
|
483
|
+
case "list":
|
|
484
|
+
return block.items.reduce((sum, item) => sum + countWords(item), 0);
|
|
485
|
+
case "table":
|
|
486
|
+
return block.rows.reduce((sum, row) => sum + row.reduce((cells, cell) => cells + countWords(cell), 0), 0);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ---------------------------------------------------------------------------
|
|
491
|
+
// Tickers
|
|
492
|
+
|
|
493
|
+
/** US venues only: a symbol from another exchange can name a different company here. */
|
|
494
|
+
const US_VENUE = /\b(?:NYSE American|NYSE Arca|NYSE MKT|NYSE|Nasdaq(?:GS|GM|CM)?|NASDAQ(?:GS|GM|CM)?|AMEX|Cboe BZX|OTCQX|OTCQB|OTC Pink|OTC)\s*:\s*([A-Z][A-Z0-9]{0,5}(?:\.[A-Z])?)\b/g;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Symbols a release names with their listing, "(NASDAQ: ABCD)", in the order
|
|
498
|
+
* they first appear. A bare capitalised word is never taken for a ticker.
|
|
499
|
+
*/
|
|
500
|
+
export function listedTickers(text: string): string[] {
|
|
501
|
+
const symbols: string[] = [];
|
|
502
|
+
for (const group of text.matchAll(/\(([^()]{3,80})\)/g)) {
|
|
503
|
+
for (const match of group[1]!.matchAll(US_VENUE)) {
|
|
504
|
+
const symbol = match[1]!;
|
|
505
|
+
if (!symbols.includes(symbol)) symbols.push(symbol);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return symbols;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// ---------------------------------------------------------------------------
|
|
512
|
+
// Search terms
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Splits text on the terms a search matched, case-insensitively, the longest
|
|
516
|
+
* term first so "free cash flow" is one mark rather than "cash" inside it.
|
|
517
|
+
*/
|
|
518
|
+
export function markTerms(text: string, terms: readonly string[]): Array<{ text: string; marked: boolean }> {
|
|
519
|
+
const usable = terms.map((term) => term.trim()).filter((term) => term.length > 0);
|
|
520
|
+
if (usable.length === 0) return [{ text, marked: false }];
|
|
521
|
+
const pattern = new RegExp(
|
|
522
|
+
`(${usable.map((term) => term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).sort((a, b) => b.length - a.length).join("|")})`,
|
|
523
|
+
"gi",
|
|
524
|
+
);
|
|
525
|
+
const keys = new Set(usable.map((term) => term.toLowerCase()));
|
|
526
|
+
return text.split(pattern).filter((part) => part.length > 0).map((part) => ({ text: part, marked: keys.has(part.toLowerCase()) }));
|
|
527
|
+
}
|
|
@@ -11,13 +11,13 @@ import { useState } from "react";
|
|
|
11
11
|
import { t } from "../i18n";
|
|
12
12
|
import { useAppLanguage } from "../i18n/react";
|
|
13
13
|
import { matchesKeyChord, parseKeyChord } from "../app/keybindings";
|
|
14
|
-
import { AuthForm, authFormTitle } from "../
|
|
15
|
-
import type { AccountMode } from "../
|
|
14
|
+
import { AuthForm, authFormTitle } from "../account/auth-form";
|
|
15
|
+
import type { AccountMode } from "../account/auth-model";
|
|
16
16
|
import {
|
|
17
17
|
DeviceSignInPanel,
|
|
18
18
|
isDeviceSignInRetryKey,
|
|
19
19
|
useDeviceSignIn,
|
|
20
|
-
} from "../
|
|
20
|
+
} from "../account/device-signin-dialog";
|
|
21
21
|
import { useShortcut, useViewport } from "../react/input";
|
|
22
22
|
import { useThemeColors } from "../theme/theme-context";
|
|
23
23
|
import { Box, Text } from "../ui";
|
|
@@ -29,10 +29,19 @@ import type { QuoteFlashDirection } from "../quote-flash";
|
|
|
29
29
|
import { objectVersion } from "../../utils/object-version";
|
|
30
30
|
import { getCompletedRegularSessionDisplay } from "../../market-data/market/status";
|
|
31
31
|
import { usePaneFooter } from "../layout/pane/footer";
|
|
32
|
+
import { Button } from "../ui/button";
|
|
33
|
+
import { PaneStatusBody } from "../ui/status";
|
|
32
34
|
|
|
33
35
|
export interface TickerTableCell {
|
|
34
36
|
text: string;
|
|
35
37
|
color?: string;
|
|
38
|
+
/** The full-precision number behind a rounded `text`, which exports and rendered-view reports keep. */
|
|
39
|
+
value?: number | null;
|
|
40
|
+
/**
|
|
41
|
+
* Makes the cell a link: a click selects the row and calls this instead of
|
|
42
|
+
* the row's own click. The pane gives the same action a key (its menu).
|
|
43
|
+
*/
|
|
44
|
+
onPress?: () => void;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
type ResolveTickerTableCell = (
|
|
@@ -83,6 +92,13 @@ export interface TickerListTableViewProps {
|
|
|
83
92
|
rowMenuAccelerators?: Readonly<Record<string, string>>;
|
|
84
93
|
emptyTitle?: string;
|
|
85
94
|
emptyHint?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Starts the pane's add-ticker flow. Given, the empty table offers a
|
|
97
|
+
* "+ ticker" button for it and says so before the key.
|
|
98
|
+
*/
|
|
99
|
+
onAddTicker?: () => void;
|
|
100
|
+
/** The pane's key for the same flow, named after the click. The command bar's key when absent. */
|
|
101
|
+
addTickerShortcut?: string;
|
|
86
102
|
virtualize?: boolean;
|
|
87
103
|
overscan?: number;
|
|
88
104
|
}
|
|
@@ -214,11 +230,24 @@ export function TickerListTableView({
|
|
|
214
230
|
rowMenuAccelerators,
|
|
215
231
|
emptyTitle = t("No tickers."),
|
|
216
232
|
emptyHint,
|
|
233
|
+
onAddTicker,
|
|
234
|
+
addTickerShortcut,
|
|
217
235
|
virtualize = true,
|
|
218
236
|
overscan = 4,
|
|
219
237
|
}: TickerListTableViewProps) {
|
|
220
238
|
const commandBarShortcut = useCommandBarShortcut();
|
|
221
|
-
const
|
|
239
|
+
const addLabel = `+ ${t("ticker")}`;
|
|
240
|
+
const resolvedEmptyHint = emptyHint ?? (onAddTicker
|
|
241
|
+
? tf("Click {button} to add one, or press {shortcut}.", { button: addLabel, shortcut: addTickerShortcut ?? commandBarShortcut })
|
|
242
|
+
: tf("Press {shortcut} to add one.", { shortcut: commandBarShortcut }));
|
|
243
|
+
const emptyContent = onAddTicker ? (
|
|
244
|
+
<PaneStatusBody
|
|
245
|
+
empty
|
|
246
|
+
emptyTitle={emptyTitle}
|
|
247
|
+
emptyMessage={resolvedEmptyHint}
|
|
248
|
+
actions={<Button label="Add ticker" displayLabel={addLabel} compact onPress={onAddTicker} />}
|
|
249
|
+
/>
|
|
250
|
+
) : undefined;
|
|
222
251
|
const renderer = useRendererHost();
|
|
223
252
|
const { showContextMenu } = useContextMenu();
|
|
224
253
|
const { nativeContextMenu } = useUiCapabilities();
|
|
@@ -242,6 +271,8 @@ export function TickerListTableView({
|
|
|
242
271
|
resolveCellRef.current = { resolve: resolveCell, epoch: resolveCellRef.current.epoch + 1 };
|
|
243
272
|
}
|
|
244
273
|
const resolveEpoch = resolveCellRef.current.epoch;
|
|
274
|
+
const setCursorSymbolRef = useRef(setCursorSymbol);
|
|
275
|
+
setCursorSymbolRef.current = setCursorSymbol;
|
|
245
276
|
|
|
246
277
|
const renderCell = useCallback((
|
|
247
278
|
ticker: TickerRecord,
|
|
@@ -257,13 +288,22 @@ export function TickerListTableView({
|
|
|
257
288
|
};
|
|
258
289
|
}
|
|
259
290
|
|
|
260
|
-
const { text, color } = resolveCellRef.current.resolve(column, ticker, financials);
|
|
291
|
+
const { text, color, onPress, value } = resolveCellRef.current.resolve(column, ticker, financials);
|
|
261
292
|
const shouldFlash = flashSymbolsRef.current.has(ticker.metadata.ticker)
|
|
262
293
|
&& flashesOnQuoteTick(column.id, financials?.quote);
|
|
263
294
|
return {
|
|
264
295
|
text,
|
|
296
|
+
...(value !== undefined ? { value } : {}),
|
|
265
297
|
color: color || (rowState.selected ? colors.selectedText : undefined),
|
|
266
298
|
attributes: shouldFlash ? TextAttributes.DIM : TextAttributes.NONE,
|
|
299
|
+
// Any other button falls through to the row, so a right click still opens its menu.
|
|
300
|
+
onMouseDown: onPress ? (event: TableMouseEvent) => {
|
|
301
|
+
if ((event.button ?? 0) !== 0) return;
|
|
302
|
+
event.preventDefault?.();
|
|
303
|
+
event.stopPropagation?.();
|
|
304
|
+
setCursorSymbolRef.current(ticker.metadata.ticker);
|
|
305
|
+
onPress();
|
|
306
|
+
} : undefined,
|
|
267
307
|
};
|
|
268
308
|
}, []);
|
|
269
309
|
|
|
@@ -349,6 +389,7 @@ export function TickerListTableView({
|
|
|
349
389
|
getRowVersion={getRowVersion}
|
|
350
390
|
emptyStateTitle={emptyTitle}
|
|
351
391
|
emptyStateHint={resolvedEmptyHint}
|
|
392
|
+
emptyContent={emptyContent}
|
|
352
393
|
virtualize={virtualize}
|
|
353
394
|
overscan={overscan}
|
|
354
395
|
rootBefore={rootBefore}
|
|
@@ -22,7 +22,8 @@ export function ActionRow({ label, children, expanded, active, disabled, fg, ...
|
|
|
22
22
|
const foreground = disabled ? colors.textMuted : fg ?? (active ? colors.textBright : colors.text);
|
|
23
23
|
return (
|
|
24
24
|
<Button {...props} label={label} active={active} disabled={disabled} expanded={expanded} variant="plain" compact flush stopPropagation>
|
|
25
|
-
|
|
25
|
+
{/* A label of two lines reads from the left; a desktop button would centre the shorter one. */}
|
|
26
|
+
<Box flexDirection="row" width="100%" alignItems="center" gap={1} style={{ textAlign: "left" }}>
|
|
26
27
|
{expanded !== undefined && <DisclosureMarker expanded={expanded} color={foreground} width={2} />}
|
|
27
28
|
<Text fg={foreground} attributes={active ? TextAttributes.BOLD : 0}>{t(label)}</Text>
|
|
28
29
|
{children}
|
|
@@ -28,6 +28,11 @@ export interface ButtonProps {
|
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
active?: boolean;
|
|
30
30
|
shortcut?: string;
|
|
31
|
+
/**
|
|
32
|
+
* The key that presses it, as a keycap on the desktop and the web only: for
|
|
33
|
+
* a dialog button whose key the terminal names in the footer line instead.
|
|
34
|
+
*/
|
|
35
|
+
desktopShortcut?: string;
|
|
31
36
|
/** Tooltip, when it should say more than the label. */
|
|
32
37
|
title?: string;
|
|
33
38
|
width?: number;
|
|
@@ -86,6 +91,7 @@ export function Button({
|
|
|
86
91
|
disabled = false,
|
|
87
92
|
active = false,
|
|
88
93
|
shortcut,
|
|
94
|
+
desktopShortcut,
|
|
89
95
|
width,
|
|
90
96
|
height,
|
|
91
97
|
compact = false,
|
|
@@ -120,7 +126,7 @@ export function Button({
|
|
|
120
126
|
variant={variant}
|
|
121
127
|
disabled={disabled}
|
|
122
128
|
active={active}
|
|
123
|
-
shortcut={shortcut}
|
|
129
|
+
shortcut={shortcut ?? desktopShortcut}
|
|
124
130
|
title={title}
|
|
125
131
|
width={width}
|
|
126
132
|
height={height}
|