gloomberb 0.16.3 → 0.16.5
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 +7 -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 +42 -17
- package/src/account/upgrade-personalization.ts +57 -0
- package/src/account/upgrade-tickers.ts +124 -0
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +58 -18
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +16 -1
- package/src/api-client/market-discovery.ts +10 -1
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +95 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +46 -10
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +74 -2
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +26 -2
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +61 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/chart-series.ts +11 -1
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +19 -4
- package/src/cli/commands/fred-series.ts +61 -0
- package/src/cli/commands/market.ts +744 -181
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +425 -0
- package/src/cli/commands/overview.ts +251 -40
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +109 -15
- package/src/cli/commands/system.ts +151 -24
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +149 -40
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +150 -17
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +22 -8
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/glossary.ts +429 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/history-rows.ts +48 -7
- package/src/cli/index-roots.ts +58 -0
- package/src/cli/index.ts +29 -12
- package/src/cli/known-gaps.ts +27 -0
- package/src/cli/listing-arg.ts +595 -26
- package/src/cli/not-a-ticker.ts +44 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/access-gate.ts +5 -0
- package/src/cli/pane-functions/capabilities.ts +11 -4
- package/src/cli/pane-functions/catalog.ts +48 -7
- package/src/cli/pane-functions/data.ts +48 -13
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +41 -19
- package/src/cli/pane-functions/freshness.ts +531 -32
- package/src/cli/pane-functions/function-help.ts +77 -25
- package/src/cli/pane-functions/headless.ts +50 -21
- package/src/cli/pane-functions/index.ts +66 -10
- package/src/cli/pane-functions/market-session.ts +147 -0
- package/src/cli/pane-functions/options.ts +77 -25
- package/src/cli/pane-functions/report-notices.ts +81 -0
- package/src/cli/pane-functions/report.ts +19 -8
- package/src/cli/pane-functions/resolver.ts +53 -18
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +199 -30
- package/src/cli/registry.ts +2 -1
- package/src/cli/report-tables.ts +3 -0
- package/src/cli/result.ts +53 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +9 -0
- package/src/cli/symbol-list.ts +172 -0
- package/src/cli/ticker-resolution.ts +223 -30
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +6 -2
- package/src/components/chart/composite/composite-chart.tsx +83 -10
- package/src/components/chart/composite/legend.tsx +88 -8
- package/src/components/chart/composite/panel-surface.tsx +44 -17
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -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/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- 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/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/command-bar/workflow/tickers.ts +23 -4
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/detached-pane-shell.tsx +9 -0
- package/src/components/layout/floating-pane.tsx +9 -2
- package/src/components/layout/header.tsx +20 -5
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +40 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/model.ts +35 -1
- package/src/components/layout/pane/header.tsx +26 -2
- package/src/components/layout/pane/index.tsx +12 -2
- package/src/components/layout/pane/sidebar.tsx +78 -10
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/drag/index.ts +43 -9
- package/src/components/layout/shell/drag/live.ts +87 -6
- package/src/components/layout/shell/drag/runtime.ts +62 -20
- package/src/components/layout/shell/index.tsx +71 -12
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +33 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +216 -28
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +69 -23
- package/src/components/metric-treemap/heat-surface.tsx +37 -9
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- 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-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +50 -41
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
- 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/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +24 -1
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +17 -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 +49 -0
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +20 -1
- package/src/components/ui/data-table/visible-range.ts +2 -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 +13 -2
- package/src/components/ui/index.ts +1 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +44 -5
- 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 +7416 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +75 -5
- package/src/i18n/ja.ts +75 -5
- package/src/i18n/ko.ts +75 -5
- package/src/i18n/zh-cn.ts +75 -5
- package/src/i18n/zh-tw.ts +75 -5
- package/src/layout/desks.ts +2 -3
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +2 -0
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/market-data/coordinator/quotes.ts +2 -2
- 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 +193 -30
- package/src/market-data/market/status.ts +59 -23
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +22 -2
- package/src/market-data/quotes/metadata.ts +8 -9
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +61 -9
- package/src/market-data/result-types.ts +2 -0
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +2 -56
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +37 -8
- package/src/plugins/builtin/account-management/password-dialog.tsx +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/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +41 -9
- package/src/plugins/builtin/alerts/pane.tsx +8 -0
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- 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 +4 -2
- package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +71 -12
- package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
- 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/index.tsx +2 -0
- package/src/plugins/builtin/awards/pane.tsx +3 -1
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +70 -13
- package/src/plugins/builtin/cds/headless.ts +116 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +193 -31
- package/src/plugins/builtin/cds/pane.tsx +56 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
- package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -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.ts +8 -3
- package/src/plugins/builtin/chart-composer/index.tsx +9 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- 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/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +50 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
- package/src/plugins/builtin/cloud/askg/model.ts +156 -78
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
- package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -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 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +19 -5
- 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/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +116 -67
- 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/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +23 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
- package/src/plugins/builtin/credit-conditions/series.ts +26 -0
- package/src/plugins/builtin/credit-documents/headless.ts +31 -1
- 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/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -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/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-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +70 -22
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/pane.tsx +3 -1
- package/src/plugins/builtin/fear-greed/index.tsx +4 -0
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- 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 +70 -9
- 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/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- 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 +64 -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 +114 -20
- 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/index.tsx +18 -8
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- 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 +62 -14
- 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 +42 -134
- package/src/plugins/builtin/holders/pane.tsx +14 -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 +27 -10
- 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/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +26 -6
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +27 -12
- package/src/plugins/builtin/iv-history/index.tsx +5 -3
- package/src/plugins/builtin/iv-history/model.ts +172 -20
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +28 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +68 -3
- package/src/plugins/builtin/macro-day/headless.ts +18 -12
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +66 -15
- package/src/plugins/builtin/macro-day/pane.tsx +34 -20
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +102 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +11 -3
- package/src/plugins/builtin/market-movers/model.ts +101 -17
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- 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 +7 -2
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +3 -6
- package/src/plugins/builtin/mna/headless.ts +15 -3
- 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/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +162 -13
- 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 +5 -2
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +75 -18
- package/src/plugins/builtin/options-scenario/headless.ts +72 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/client.ts +40 -6
- package/src/plugins/builtin/perps/equity-row.tsx +33 -8
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +45 -30
- package/src/plugins/builtin/perps/index.tsx +18 -1
- package/src/plugins/builtin/perps/model.ts +32 -6
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +90 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
- package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
- package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +6 -2
- package/src/plugins/builtin/power/headless.ts +71 -7
- package/src/plugins/builtin/power/index.tsx +4 -1
- package/src/plugins/builtin/power/model.ts +72 -1
- package/src/plugins/builtin/power/pane.tsx +32 -9
- package/src/plugins/builtin/rate-path/headless.ts +11 -3
- package/src/plugins/builtin/realized-vol/headless.ts +8 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- 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/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- 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/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/series-inventory.ts +91 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +69 -0
- 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/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +59 -2
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +21 -4
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/index.tsx +3 -10
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- 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/model.ts +1 -1
- package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
- 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/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- 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 +48 -4
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +1 -0
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
- package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +125 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +3 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- 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/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +129 -64
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +173 -28
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -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 +48 -1
- package/src/remote/app-host.tsx +25 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +126 -59
- package/src/remote/matching.ts +69 -0
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +63 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +32 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +3 -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 +27 -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 +21 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/box.tsx +4 -1
- package/src/renderers/dom/host/chart-surface.tsx +6 -2
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +14 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/size-observer.ts +26 -0
- package/src/renderers/dom/host/surface-3d.tsx +7 -2
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +74 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +6 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- 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 +107 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +145 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +26 -17
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
- package/src/sources/history-result.ts +1 -0
- package/src/sources/listing-symbols.ts +14 -5
- package/src/sources/provider-errors.ts +88 -3
- 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 +9 -5
- package/src/sources/provider-router/financial-routes.ts +12 -5
- package/src/sources/provider-router/financials.ts +55 -15
- package/src/sources/provider-router/history.ts +68 -34
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/provider-router/search.ts +1 -0
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +5 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +25 -0
- package/src/tickers/open-target.ts +3 -2
- package/src/tickers/search/index.ts +67 -9
- package/src/tickers/search/ranking.ts +78 -18
- package/src/tickers/search/types.ts +10 -2
- package/src/tickers/starter-symbols.ts +8 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/resolve.ts +96 -30
- package/src/time-series/types.ts +4 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +67 -1
- package/src/types/data-provider.ts +5 -0
- package/src/types/financials.ts +52 -1
- package/src/types/headless.ts +72 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +68 -3
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/host.tsx +26 -4
- package/src/ui/index.tsx +2 -0
- package/src/ui/live-resize.ts +81 -0
- package/src/ui/live-stretch.ts +121 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/pane-fill.ts +11 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/cli-output.ts +21 -2
- 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/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 +437 -52
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +120 -1
- package/src/utils/format.ts +17 -3
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +44 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +130 -40
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +178 -36
- package/src/utils/sec.ts +98 -40
- package/src/utils/throttled-fetch.ts +51 -22
- package/src/utils/utc-time.ts +51 -4
|
@@ -3,7 +3,7 @@ import { isAccessDenied } from "../../../api-client/errors";
|
|
|
3
3
|
import { SignInWall } from "../cloud/auth-actions";
|
|
4
4
|
import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
|
|
5
5
|
import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
|
|
6
|
-
import { useCallback } from "react";
|
|
6
|
+
import { useCallback, useMemo } from "react";
|
|
7
7
|
import { PaneStatusBody, usePaneFooter, usePaneNoticeFooter, usePaneStatusFooter, usePaneTabs } from "../../../components";
|
|
8
8
|
import { usePaneRefreshKey } from "../../../components/data-table/table-pane";
|
|
9
9
|
import { useAsyncResource, useAutoRefresh, usePaneSettingValue, usePluginAppActions, usePluginPaneState } from "../../../public/react";
|
|
@@ -11,11 +11,11 @@ import { usePaneInstance } from "../../../state/app/context";
|
|
|
11
11
|
import type { PaneProps } from "../../../types/plugin";
|
|
12
12
|
import { Box } from "../../../ui";
|
|
13
13
|
import { GpuBoard } from "./board";
|
|
14
|
-
import { getCachedGpuBoard, gpuCacheScope, GPU_NOT_AVAILABLE, loadGpuBoard } from "./client";
|
|
14
|
+
import { getCachedGpuBoard, gpuCacheScope, GPU_NOT_AVAILABLE, gpuPreviewModels, loadGpuBoard, loadGpuModelPreviews } from "./client";
|
|
15
15
|
import { GpuChanges } from "./changes";
|
|
16
16
|
import { GpuEquities } from "./equities";
|
|
17
17
|
import { GpuHistory } from "./history";
|
|
18
|
-
import { GPU_TABS, gpuTab, gpuTime } from "./model";
|
|
18
|
+
import { GPU_TABS, gpuEquityModels, gpuFamilies, gpuFamily, gpuNoMatch, gpuTab, gpuTime } from "./model";
|
|
19
19
|
|
|
20
20
|
export function GpuPane(props: PaneProps) {
|
|
21
21
|
usePlanAccess();
|
|
@@ -34,12 +34,28 @@ function GpuView({ width, height, focused }: PaneProps) {
|
|
|
34
34
|
const resource = useAsyncResource(loadGpuBoard, { initialData: getCachedGpuBoard, clearOnError: isAccessDenied });
|
|
35
35
|
const data = resource.data?.payload;
|
|
36
36
|
const { createPaneFromTemplate } = usePluginAppActions();
|
|
37
|
+
const locked = !!data?.access?.locked;
|
|
38
|
+
const families = useMemo(() => gpuFamilies(data?.rows ?? []), [data]);
|
|
39
|
+
// What was typed ("h-100", "H100 80GB SXM") reads as the GPU it names; a name that matches none stays as typed and says so.
|
|
40
|
+
const activeModel = model ? gpuFamily(model, families) ?? model : "";
|
|
41
|
+
const unknownModel = !!model && !families.includes(activeModel);
|
|
42
|
+
// The free board is one GPU's three rows; another GPU's free preview stands in for the rows it leaves out.
|
|
43
|
+
const previewKey = useMemo(() => data && !unknownModel ? gpuPreviewModels(data, tab === "equities" ? gpuEquityModels(activeModel || "H100")
|
|
44
|
+
: tab === "changes" ? [] : tab === "history" ? [activeModel || "H100"] : [activeModel]).join("\n") : "", [data, unknownModel, tab, activeModel]);
|
|
45
|
+
const previewLoader = useCallback((force: boolean) => loadGpuModelPreviews(previewKey.split("\n"), force), [previewKey]);
|
|
46
|
+
const preview = useAsyncResource(previewKey ? previewLoader : null);
|
|
47
|
+
const rows = useMemo(() => data ? [...data.rows, ...(previewKey ? preview.data ?? [] : [])] : [], [data, previewKey, preview.data]);
|
|
48
|
+
const models = useMemo(() => locked ? [...families].sort() : [...new Set(rows.map((row) => row.gpuModel))].sort(), [locked, families, rows]);
|
|
49
|
+
// A failed preview is the footer's error; the body does not repeat it.
|
|
50
|
+
const emptyTitle = unknownModel ? gpuNoMatch(model, families)
|
|
51
|
+
: preview.error ? `No ${activeModel} rental prices to show.` : `No ${activeModel} rental prices have been observed yet.`;
|
|
37
52
|
useAutoRefresh(resource.updatedAt, resource.load);
|
|
38
|
-
|
|
53
|
+
useAutoRefresh(preview.updatedAt, preview.load);
|
|
54
|
+
usePaneRefreshKey(() => { void resource.reload(); void preview.reload(); }, { focused: focused && (tab === "board" || !data) });
|
|
39
55
|
const signIn = !data && (session.needsVerification || isCloudSessionRequired(resource.error));
|
|
40
56
|
const notAvailable = !data && resource.error === GPU_NOT_AVAILABLE;
|
|
41
|
-
usePaneStatusFooter({ registrationId: "gpu", loading: resource.loading, error: notAvailable || signIn ? null : resource.error,
|
|
42
|
-
stale: !!data && (data.stale || resource.data?.stale), info: data?.asOf ? [{ id: "asof", parts: [{ text: `as of ${gpuTime(data.asOf)}`, tone: "muted" }] }] : [] });
|
|
57
|
+
usePaneStatusFooter({ registrationId: "gpu", loading: resource.loading || preview.loading, error: notAvailable || signIn ? null : resource.error ?? preview.error,
|
|
58
|
+
stale: !!data && (data.stale || resource.data?.stale), info: data?.asOf ? [{ id: "asof", asOf: true, parts: [{ text: `as of ${gpuTime(data.asOf)}`, tone: "muted" }] }] : [] });
|
|
43
59
|
usePaneNoticeFooter({ registrationId: "gpu:notices", focused,
|
|
44
60
|
notices: [...(data?.gaps ?? []), ...(resource.data?.refreshError ? [resource.data.refreshError] : [])] });
|
|
45
61
|
usePaneFooter("gpu:actions", () => ({ info: data?.access?.preview ? [{ id: "preview", parts: [{ text: "Free preview", tone: "muted" }] }] : [],
|
|
@@ -47,17 +63,17 @@ function GpuView({ width, height, focused }: PaneProps) {
|
|
|
47
63
|
onPress: () => createPaneFromTemplate("buildout-pane") }] }), [createPaneFromTemplate, data?.access, upgrade]);
|
|
48
64
|
const { strip, rows: tabRows } = usePaneTabs(data ? { tabs: [...GPU_TABS], activeValue: tab, onSelect: setTab, focused, dense: true } : null);
|
|
49
65
|
const body = { width, height: Math.max(3, height - tabRows), focused };
|
|
50
|
-
const reloadBoard = useCallback(() => { void resource.reload(); }, [resource.reload]);
|
|
66
|
+
const reloadBoard = useCallback(() => { void resource.reload(); void preview.reload(); }, [resource.reload, preview.reload]);
|
|
51
67
|
if (signIn) return <SignInWall placement="gpu" width={width} height={height} action="browse GPU rental prices" needsVerification={session.needsVerification} />;
|
|
52
68
|
return <Box width={width} height={height} flexDirection="column">
|
|
53
69
|
{strip}
|
|
54
|
-
<PaneStatusBody loading={resource.loading && !data} error={!data && !notAvailable ? resource.error : null}
|
|
70
|
+
<PaneStatusBody loading={(resource.loading && !data) || (!!previewKey && preview.loading && !preview.data)} error={!data && !notAvailable ? resource.error : null}
|
|
55
71
|
empty={notAvailable} emptyTitle={GPU_NOT_AVAILABLE} subject="GPU rental prices">
|
|
56
|
-
{data ? tab === "board" ? <GpuBoard rows={
|
|
72
|
+
{data ? tab === "board" ? <GpuBoard rows={rows} models={models} asOf={data.asOf} model={activeModel} setModel={setModel} selectedId={selectedId} emptyTitle={emptyTitle}
|
|
57
73
|
select={(row, open) => { setSelectedId(row.id); if (open) setTab("history"); }} {...body} />
|
|
58
|
-
: tab === "history" ? <GpuHistory rows={
|
|
59
|
-
: tab === "changes" ? <GpuChanges
|
|
60
|
-
: <GpuEquities board={
|
|
74
|
+
: tab === "history" ? <GpuHistory rows={rows} models={models} model={unknownModel ? "" : activeModel} setModel={setModel} selectedId={selectedId} onSelect={setSelectedId} reloadBoard={reloadBoard} {...body} />
|
|
75
|
+
: tab === "changes" ? <GpuChanges models={models} model={unknownModel ? "" : activeModel} setModel={setModel} reloadBoard={reloadBoard} {...body} />
|
|
76
|
+
: <GpuEquities board={rows} models={models} locked={locked} model={unknownModel ? "" : activeModel} setModel={setModel} reloadBoard={reloadBoard} {...body} /> : null}
|
|
61
77
|
</PaneStatusBody>
|
|
62
78
|
</Box>;
|
|
63
79
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SeriesDefinition } from "../../../series/types";
|
|
2
|
+
import { cachedSeriesWarning } from "../shared/series-warning";
|
|
3
|
+
import { loadGpuBoard, loadGpuHistory } from "./client";
|
|
4
|
+
import { GPU_MODELS, gpuListIndex } from "./model";
|
|
5
|
+
|
|
6
|
+
/** What the GPU pane says when the free preview leaves history out. */
|
|
7
|
+
const GPU_PRO_ONLY = "Full history is available with Pro.";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Each GPU's list index, the one the GPU pane's Equities tab reads shares
|
|
11
|
+
* against. The per-provider listings stay on the board and its History tab:
|
|
12
|
+
* the server lists them, and they come and go.
|
|
13
|
+
*/
|
|
14
|
+
export const GPU_SERIES: readonly SeriesDefinition[] = GPU_MODELS.map((model): SeriesDefinition => ({
|
|
15
|
+
id: `gpu:${model.toLowerCase().replaceAll(" ", "-")}-list-index`,
|
|
16
|
+
name: `${model} rental list index`,
|
|
17
|
+
unit: "USD/GPU-hour",
|
|
18
|
+
frequency: "intraday",
|
|
19
|
+
group: "Alternative data",
|
|
20
|
+
tags: ["GPU", "rental", "compute", "cloud", "list price", model],
|
|
21
|
+
description: `Median list price to rent one ${model} from neocloud providers (hyperscalers where none list it), chained so a change of providers causes no jump, as GPU charts it. Needs Pro.`,
|
|
22
|
+
style: "step",
|
|
23
|
+
load: async () => {
|
|
24
|
+
const board = await loadGpuBoard();
|
|
25
|
+
if (board.payload.access?.locked) throw new Error(GPU_PRO_ONLY);
|
|
26
|
+
const index = gpuListIndex(board.payload.rows, model);
|
|
27
|
+
if (!index) throw new Error(`No ${model} list index is listed yet.`);
|
|
28
|
+
const history = await loadGpuHistory(index.id);
|
|
29
|
+
if (history.payload.access?.locked) throw new Error(GPU_PRO_ONLY);
|
|
30
|
+
const warning = cachedSeriesWarning(history);
|
|
31
|
+
return {
|
|
32
|
+
points: history.payload.points
|
|
33
|
+
.filter((point) => `${point.source}:${point.skuKey}` === index.id)
|
|
34
|
+
.map((point) => ({ date: point.observedAt, value: point.pricePerGpuHr })),
|
|
35
|
+
...(warning ? { warning } : {}),
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
}));
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* The help card for one function, opened by `HELP <fn>` in the command bar
|
|
3
3
|
* and F1 on a focused pane: what it answers, how to type it, the keys that
|
|
4
4
|
* matter in its pane, how fresh its data is on each plan, its Bloomberg
|
|
5
|
-
* equivalent and its docs entry. Enter
|
|
6
|
-
*
|
|
5
|
+
* equivalent and its docs entry. Enter reads the entry in DOCS, inside the
|
|
6
|
+
* app; the link beside it is the same entry on gloom.sh, in the browser. A
|
|
7
|
+
* popped-out window cannot open a pane, so there Enter opens the link. Esc,
|
|
8
|
+
* the close button or a click outside closes it.
|
|
7
9
|
*
|
|
8
10
|
* `useFunctionHelpHost` is mounted with the app's global shortcuts for the
|
|
9
11
|
* life of the window and owns the dialog; `requestFunctionHelp` lets the
|
|
@@ -13,7 +15,9 @@ import { useEffect, useRef, type ReactNode } from "react";
|
|
|
13
15
|
import { usePlanAccess } from "../../../api-client/plan-access";
|
|
14
16
|
import { functionDocsUrl, type FunctionFreshness, type FunctionHelpKey } from "../../../cli/pane-functions/function-help";
|
|
15
17
|
import { requestFeedbackDialog } from "../../../components/feedback-dialog";
|
|
18
|
+
import { Button } from "../../../components/ui/button";
|
|
16
19
|
import { ExternalLink } from "../../../components/ui/external-link";
|
|
20
|
+
import { DOCS_PANE_TEMPLATE_ID } from "../../../docs/content";
|
|
17
21
|
import { DialogFrame } from "../../../components/ui/frame";
|
|
18
22
|
import { ShortcutHint } from "../../../components/ui/shortcut-hint";
|
|
19
23
|
import { t } from "../../../i18n";
|
|
@@ -21,10 +25,12 @@ import { useViewport } from "../../../react/input";
|
|
|
21
25
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
22
26
|
import { Box, Text, TextAttributes, useRendererHost } from "../../../ui";
|
|
23
27
|
import { useDialog, useDialogKeyboard, type AlertContext } from "../../../ui/dialog";
|
|
28
|
+
import { getSharedRegistry } from "../../registry";
|
|
24
29
|
import type { HelpFunction } from "./function-index";
|
|
25
30
|
|
|
26
31
|
export type FunctionHelpRequest =
|
|
27
|
-
|
|
32
|
+
/** `inAppDocs: false` where DOCS cannot open (a popped-out window). */
|
|
33
|
+
| { kind: "function"; fn: HelpFunction; inAppDocs?: boolean }
|
|
28
34
|
/** `HELP HELP`: the feedback dialog, which is how people reach us. */
|
|
29
35
|
| { kind: "support" };
|
|
30
36
|
|
|
@@ -103,9 +109,10 @@ function FreshnessRows({ data, pro }: { data: FunctionFreshness; pro: boolean })
|
|
|
103
109
|
);
|
|
104
110
|
}
|
|
105
111
|
|
|
106
|
-
function FunctionHelpCard({ fn, dismiss, dialogId, width, compact = false }: AlertContext & {
|
|
112
|
+
function FunctionHelpCard({ fn, dismiss, dialogId, width, compact = false, inAppDocs = true }: AlertContext & {
|
|
107
113
|
fn: HelpFunction;
|
|
108
114
|
width: number;
|
|
115
|
+
inAppDocs?: boolean;
|
|
109
116
|
/** A short terminal: no blank row between the summary and the rows. */
|
|
110
117
|
compact?: boolean;
|
|
111
118
|
}) {
|
|
@@ -117,6 +124,10 @@ function FunctionHelpCard({ fn, dismiss, dialogId, width, compact = false }: Ale
|
|
|
117
124
|
void rendererHost.openExternal(url);
|
|
118
125
|
dismiss();
|
|
119
126
|
};
|
|
127
|
+
const readInApp = () => {
|
|
128
|
+
getSharedRegistry()?.createPaneFromTemplate(DOCS_PANE_TEMPLATE_ID, { arg: fn.code });
|
|
129
|
+
dismiss();
|
|
130
|
+
};
|
|
120
131
|
|
|
121
132
|
useDialogKeyboard((event) => {
|
|
122
133
|
if (event.ctrl || event.alt || event.meta || event.super) return;
|
|
@@ -124,7 +135,8 @@ function FunctionHelpCard({ fn, dismiss, dialogId, width, compact = false }: Ale
|
|
|
124
135
|
if (name !== "enter" && name !== "return") return;
|
|
125
136
|
event.preventDefault();
|
|
126
137
|
event.stopPropagation();
|
|
127
|
-
|
|
138
|
+
if (inAppDocs) readInApp();
|
|
139
|
+
else openDocs();
|
|
128
140
|
}, { scope: dialogId });
|
|
129
141
|
|
|
130
142
|
const help = fn.help;
|
|
@@ -153,6 +165,11 @@ function FunctionHelpCard({ fn, dismiss, dialogId, width, compact = false }: Ale
|
|
|
153
165
|
</CardRow>
|
|
154
166
|
)}
|
|
155
167
|
<CardRow label="Docs">
|
|
168
|
+
{inAppDocs && (
|
|
169
|
+
<Box flexDirection="row">
|
|
170
|
+
<Button label="Read in Docs" shortcut="Enter" compact onPress={readInApp} stopPropagation />
|
|
171
|
+
</Box>
|
|
172
|
+
)}
|
|
156
173
|
<ExternalLink url={docsUrl} label={docsUrl.replace(/^https:\/\//, "")} onOpen={openDocs} />
|
|
157
174
|
</CardRow>
|
|
158
175
|
</Box>
|
|
@@ -189,7 +206,9 @@ export function useFunctionHelpHost({ closeCommandBar }: { closeCommandBar: () =
|
|
|
189
206
|
closeOnClickOutside: true,
|
|
190
207
|
// The terminal host defaults to 60 columns; the desktop sizes to the content.
|
|
191
208
|
style: { width: width + TERMINAL_DIALOG_CHROME, ...(compact ? { paddingY: 0 } : {}) },
|
|
192
|
-
content: (context: AlertContext) =>
|
|
209
|
+
content: (context: AlertContext) => (
|
|
210
|
+
<FunctionHelpCard {...context} fn={request.fn} width={width} compact={compact} inAppDocs={request.inAppDocs !== false} />
|
|
211
|
+
),
|
|
193
212
|
}).catch(() => {}).finally(() => {
|
|
194
213
|
openRef.current = false;
|
|
195
214
|
});
|
|
@@ -8,10 +8,11 @@ import { Box, ScrollBox, Text, useRendererHost, useUiHost } from "../../../ui";
|
|
|
8
8
|
import { detectShortcutPlatform, formatPrimaryShortcut, getShortcutDisplayMode } from "../../../utils/shortcut-labels";
|
|
9
9
|
import { getSharedRegistry } from "../../registry";
|
|
10
10
|
import { apiClient, type CloudPricing } from "../../../api-client";
|
|
11
|
-
import { trialDaysOf } from "
|
|
11
|
+
import { trialDaysOf } from "../../../account/billing";
|
|
12
12
|
import { usePluginAppActions, usePluginPaneState } from "../../runtime";
|
|
13
13
|
import type { PluginModule } from "../plugin-module";
|
|
14
14
|
import { requestFeedbackDialog } from "../../../components/feedback-dialog";
|
|
15
|
+
import { DOCS_PANE_TEMPLATE_ID } from "../../../docs/content";
|
|
15
16
|
import { FeedbackTab } from "./feedback-tab";
|
|
16
17
|
import { FunctionsTable } from "./functions-table";
|
|
17
18
|
import { KeybindingsEditor } from "./keybindings-editor";
|
|
@@ -36,7 +37,7 @@ function entry(id: string, badges: string[], description: string): ShortcutTable
|
|
|
36
37
|
|
|
37
38
|
function HelpPane({ focused, width, height }: PaneProps) {
|
|
38
39
|
const registry = getSharedRegistry();
|
|
39
|
-
const { openCommandBar, showPane } = usePluginAppActions();
|
|
40
|
+
const { openCommandBar, showPane, createPaneFromTemplate } = usePluginAppActions();
|
|
40
41
|
// A key capture requested from the command bar belongs to the Shortcuts
|
|
41
42
|
// tab, whether the pane is already open or is being opened for it.
|
|
42
43
|
const [activeTabId, setActiveTabId] = usePluginPaneState<HelpTabId>("activeTab", "basics");
|
|
@@ -100,6 +101,10 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
100
101
|
openCommandBar("PL ");
|
|
101
102
|
}, [openCommandBar]);
|
|
102
103
|
|
|
104
|
+
const openDocs = useCallback(() => {
|
|
105
|
+
createPaneFromTemplate(DOCS_PANE_TEMPLATE_ID);
|
|
106
|
+
}, [createPaneFromTemplate]);
|
|
107
|
+
|
|
103
108
|
const openIssues = useCallback(() => {
|
|
104
109
|
void rendererHost.openExternal(GLOOMBERB_ISSUES_URL);
|
|
105
110
|
}, [rendererHost]);
|
|
@@ -107,7 +112,10 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
107
112
|
// Each tab's actions. `l` moves between tabs, so layout actions take `a`.
|
|
108
113
|
const tabHints = useMemo<PaneHint[]>(() => {
|
|
109
114
|
if (activeTabId === "basics") {
|
|
110
|
-
return [
|
|
115
|
+
return [
|
|
116
|
+
{ id: "docs", key: "d", label: "ocs", title: "Open Docs", onPress: openDocs },
|
|
117
|
+
{ id: "layout-actions", key: "a", label: " layout actions", title: "Layout Actions", onPress: openLayoutActions },
|
|
118
|
+
];
|
|
111
119
|
}
|
|
112
120
|
if (activeTabId === "functions") {
|
|
113
121
|
return [{ id: "plugins", key: "p", label: "lugins", title: "Manage Plugins", onPress: openPluginManager }];
|
|
@@ -120,7 +128,7 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
120
128
|
];
|
|
121
129
|
}
|
|
122
130
|
return [];
|
|
123
|
-
}, [activeTabId, openDebugLog, openIssues, openLayoutActions, openPluginManager]);
|
|
131
|
+
}, [activeTabId, openDebugLog, openDocs, openIssues, openLayoutActions, openPluginManager]);
|
|
124
132
|
|
|
125
133
|
// The footer binds each hint's key; a search field keeps its typing.
|
|
126
134
|
usePaneFooter("help:tab", () => tabHints.length > 0 ? { hints: tabHints } : null, [tabHints]);
|
|
@@ -152,7 +160,9 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
152
160
|
: []),
|
|
153
161
|
entry("des", ["DES", "<ticker>"], "Open security details for a specific ticker."),
|
|
154
162
|
entry("help-card", ["HELP", "<function>"], "Open a function's help card: what it shows, its keys, how fresh its data is. HELP HELP reaches support."),
|
|
163
|
+
entry("docs", ["DOCS", "<function>"], "Read the docs and Academy lessons in the app. The ? on a pane opens its entry."),
|
|
155
164
|
entry("upgrade", ["UPGRADE"], tf("Go Pro for real-time data at gloom.sh/cloud, free for {days} days.", { days: trialDays })),
|
|
165
|
+
entry("mcp", ["MCP"], "Connect Claude Code, Codex, Cursor or any MCP client to Gloom's research tools."),
|
|
156
166
|
entry("move", ["Up/Down", "Ctrl+P/N"], "Move through command bar results."),
|
|
157
167
|
entry("page", ["PageUp/PageDown", "Ctrl+Home/End"], "Jump a page, or to the first or last result."),
|
|
158
168
|
entry("run", ["Enter", "Shift+Enter"], "Run the selected result or its secondary action."),
|
|
@@ -174,7 +184,7 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
174
184
|
entry("back", ["Esc", "Backspace"], "Go back from a detail view."),
|
|
175
185
|
entry("pane-menu", actionBadges("pane-menu"), "Open the focused pane's menu: every action in the pane with its key, sorting, filters, tabs, toggles and the pane actions."),
|
|
176
186
|
...(functionHelpBadges.length > 0
|
|
177
|
-
? [entry("function-help", functionHelpBadges, "Open the focused pane's help card
|
|
187
|
+
? [entry("function-help", functionHelpBadges, "Open the focused pane's help card; Enter reads its docs.")]
|
|
178
188
|
: []),
|
|
179
189
|
entry("search", ["/"], "Search in the focused pane."),
|
|
180
190
|
entry("warnings", ["!"], "Open the focused pane's data warnings."),
|
|
@@ -266,11 +276,11 @@ function HelpPane({ focused, width, height }: PaneProps) {
|
|
|
266
276
|
<SectionHeading title="How To Use Gloomberb" />
|
|
267
277
|
<Box flexDirection="column">
|
|
268
278
|
<Text fg={colors.textDim}>{t("Gloomberb is command-bar first.")}</Text>
|
|
269
|
-
<Text fg={colors.textDim}>{t("
|
|
279
|
+
<Text fg={colors.textDim} wrapText>{t("Click anything to use it; the keys shown beside actions are shortcuts.")}</Text>
|
|
270
280
|
<Text fg={colors.textDim} wrapText>
|
|
271
281
|
{commandBarBadges[0]
|
|
272
|
-
? tf("Not sure of a code?
|
|
273
|
-
: t("Not sure of a code?
|
|
282
|
+
? tf("Not sure of a code? Click the search bar at the top, or press {key}, and type what you want in plain words, like \"apple earnings\". The Functions tab lists everything.", { key: commandBarBadges[0] })
|
|
283
|
+
: t("Not sure of a code? Click the search bar at the top and type what you want in plain words, like \"apple earnings\". The Functions tab lists everything.")}
|
|
274
284
|
</Text>
|
|
275
285
|
</Box>
|
|
276
286
|
</Box>
|
|
@@ -7,7 +7,9 @@ import type {
|
|
|
7
7
|
BeneficialOwnersPayload,
|
|
8
8
|
} from "../../../api-client/beneficial-owners";
|
|
9
9
|
import { ApiRequestError, isAccessDenied } from "../../../api-client/errors";
|
|
10
|
+
import { listingAbroad, type IssuerListingParams } from "../../../api-client/paths";
|
|
10
11
|
import { createPluginCache } from "../../../data/plugin-cache";
|
|
12
|
+
import { secListingKey } from "../../../utils/sec";
|
|
11
13
|
import { finiteOrNull, recordOrNull } from "../../../utils/guards";
|
|
12
14
|
import { cachedCloudResource, loadCloudResource, type CloudResource } from "../shared/cloud-resource";
|
|
13
15
|
import { CLOUD_SESSION_REQUIRED } from "../shared/research-cloud-session";
|
|
@@ -28,6 +30,8 @@ export interface BeneficialOwnersRequest {
|
|
|
28
30
|
form?: BeneficialOwnersForm;
|
|
29
31
|
/** Every report instead of the latest per filer. */
|
|
30
32
|
history?: boolean;
|
|
33
|
+
/** The listing's venue and company, for a listing outside the US. */
|
|
34
|
+
listing?: IssuerListingParams;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
type BeneficialOwnersClient = Pick<typeof apiClient, "getCloudSecBeneficialOwners">;
|
|
@@ -142,7 +146,7 @@ function describeFailure(error: unknown, ticker: string): unknown {
|
|
|
142
146
|
*/
|
|
143
147
|
export async function fetchBeneficialOwners(
|
|
144
148
|
ticker: string,
|
|
145
|
-
{ form = "all", history = false }: BeneficialOwnersRequest = {},
|
|
149
|
+
{ form = "all", history = false, listing }: BeneficialOwnersRequest = {},
|
|
146
150
|
{ client = apiClient, signal }: { client?: BeneficialOwnersClient; signal?: AbortSignal } = {},
|
|
147
151
|
): Promise<BeneficialOwnersPayload> {
|
|
148
152
|
const symbol = ticker.trim().toUpperCase();
|
|
@@ -154,6 +158,8 @@ export async function fetchBeneficialOwners(
|
|
|
154
158
|
for (;;) {
|
|
155
159
|
const page = normalizeBeneficialOwnersPayload(await client.getCloudSecBeneficialOwners({
|
|
156
160
|
ticker: symbol,
|
|
161
|
+
exchange: listing?.exchange,
|
|
162
|
+
name: listing?.name,
|
|
157
163
|
form,
|
|
158
164
|
history,
|
|
159
165
|
limit: PAGE_SIZE,
|
|
@@ -178,10 +184,20 @@ export async function fetchBeneficialOwners(
|
|
|
178
184
|
offset = nextOffset;
|
|
179
185
|
}
|
|
180
186
|
} catch (error) {
|
|
187
|
+
// A listing abroad whose company the SEC does not know has no reports.
|
|
188
|
+
const abroad = listingAbroad(symbol, listing?.exchange);
|
|
189
|
+
if (abroad && error instanceof ApiRequestError && error.status === 404) return noReports(symbol, history);
|
|
181
190
|
throw describeFailure(error, symbol);
|
|
182
191
|
}
|
|
183
192
|
}
|
|
184
193
|
|
|
194
|
+
function noReports(ticker: string, history: boolean): BeneficialOwnersPayload {
|
|
195
|
+
return {
|
|
196
|
+
ticker, cik: "", companyName: "", asOf: null, owners: [], ...(history ? { filings: [] } : {}),
|
|
197
|
+
hasMore: false, nextOffset: null, coverage: null,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
185
201
|
/** Pages can overlap when a report lands between two requests. */
|
|
186
202
|
function dedupe(rows: BeneficialOwnerFiling[]): BeneficialOwnerFiling[] {
|
|
187
203
|
const seen = new Set<string>();
|
|
@@ -193,17 +209,23 @@ function dedupe(rows: BeneficialOwnerFiling[]): BeneficialOwnerFiling[] {
|
|
|
193
209
|
});
|
|
194
210
|
}
|
|
195
211
|
|
|
196
|
-
|
|
212
|
+
// SAN in Paris is not SAN in New York: a listing abroad is cached under its venue.
|
|
213
|
+
const cacheKey = (ticker: string, listing?: IssuerListingParams) => secListingKey(ticker, listing?.exchange);
|
|
197
214
|
|
|
198
|
-
export function cachedBeneficialOwners(ticker: string): CloudResource<BeneficialOwnersPayload> | null {
|
|
199
|
-
return cachedCloudResource(beneficialOwnersCache, cacheKey(ticker));
|
|
215
|
+
export function cachedBeneficialOwners(ticker: string, listing?: IssuerListingParams): CloudResource<BeneficialOwnersPayload> | null {
|
|
216
|
+
return cachedCloudResource(beneficialOwnersCache, cacheKey(ticker, listing));
|
|
200
217
|
}
|
|
201
218
|
|
|
202
219
|
/** The pane's list: the latest report per filer, both kinds, cached on disk. */
|
|
203
|
-
export async function loadBeneficialOwners(
|
|
220
|
+
export async function loadBeneficialOwners(
|
|
221
|
+
ticker: string,
|
|
222
|
+
force = false,
|
|
223
|
+
listing?: IssuerListingParams,
|
|
224
|
+
): Promise<CloudResource<BeneficialOwnersPayload>> {
|
|
225
|
+
const key = cacheKey(ticker, listing);
|
|
204
226
|
try {
|
|
205
|
-
return await loadCloudResource(beneficialOwnersCache,
|
|
227
|
+
return await loadCloudResource(beneficialOwnersCache, key, () => fetchBeneficialOwners(ticker, { listing }), { force });
|
|
206
228
|
} catch (error) {
|
|
207
|
-
throw describeFailure(error,
|
|
229
|
+
throw describeFailure(error, key);
|
|
208
230
|
}
|
|
209
231
|
}
|
|
@@ -30,9 +30,22 @@ export interface ThirteenFAction {
|
|
|
30
30
|
value: number;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/** The stake a report's shares make of today's count, where the report's own base differs. */
|
|
34
|
+
export interface StakeToday {
|
|
35
|
+
/** Percent of today's shares outstanding. */
|
|
36
|
+
percent: number;
|
|
37
|
+
sharesOutstanding: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
export interface BeneficialOwnerRow {
|
|
34
41
|
id: string;
|
|
35
42
|
filing: BeneficialOwnerFiling;
|
|
43
|
+
/** Who the row is: the reporting person whose stake it shows. */
|
|
44
|
+
holderName: string;
|
|
45
|
+
/** The other reporting persons on the same report: a group's members, a fund's adviser or principal. */
|
|
46
|
+
otherPersons: number;
|
|
47
|
+
/** The report's shares over today's count, when that count is no longer the report's base. */
|
|
48
|
+
today: StakeToday | null;
|
|
36
49
|
/** `13G/A`: the kind, and `/A` for an amendment. */
|
|
37
50
|
formLabel: string;
|
|
38
51
|
/** Percent points against the filer's report before this one. */
|
|
@@ -93,6 +106,71 @@ export function thirteenFAction(holder: HolderRecord | undefined): ThirteenFActi
|
|
|
93
106
|
return null;
|
|
94
107
|
}
|
|
95
108
|
|
|
109
|
+
const ALL_CAPS = /^[^a-z]*[A-Z][^a-z]*$/;
|
|
110
|
+
|
|
111
|
+
function sameEntity(left: string, right: string): boolean {
|
|
112
|
+
const key = (name: string) => name.toLowerCase().replace(/[^a-z0-9 ]+/g, " ")
|
|
113
|
+
.replace(/\b(the|inc|llc|ltd|lp|llp|corp|corporation|co|company|plc|n a|s a)\b/g, " ").replace(/\s+/g, " ").trim();
|
|
114
|
+
return key(left) === key(right);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The name a row goes by, one rule for every report: the reporting person
|
|
119
|
+
* whose stake the row shows (the highest percent, then shares, the filer's
|
|
120
|
+
* own entry on a tie), not the EDGAR filer, which only some reports name.
|
|
121
|
+
* When that person is the filer and the cover spells it in capitals, the
|
|
122
|
+
* filer's own spelling is kept (`SRS Investment Management, LLC`).
|
|
123
|
+
*/
|
|
124
|
+
export function beneficialHolderName(
|
|
125
|
+
filing: Pick<BeneficialOwnerFiling, "filerName" | "filerCik" | "reportingPersons">,
|
|
126
|
+
): string {
|
|
127
|
+
let best: BeneficialOwnerFiling["reportingPersons"][number] | null = null;
|
|
128
|
+
for (const person of filing.reportingPersons) {
|
|
129
|
+
if (!person.name.trim()) continue;
|
|
130
|
+
if (!best) { best = person; continue; }
|
|
131
|
+
const percent = person.percentOfClass ?? -1;
|
|
132
|
+
const bestPercent = best.percentOfClass ?? -1;
|
|
133
|
+
if (percent !== bestPercent) { if (percent > bestPercent) best = person; continue; }
|
|
134
|
+
const shares = person.shares ?? -1;
|
|
135
|
+
const bestShares = best.shares ?? -1;
|
|
136
|
+
if (shares !== bestShares) { if (shares > bestShares) best = person; continue; }
|
|
137
|
+
if (filing.filerCik && person.cik === filing.filerCik && best.cik !== filing.filerCik) best = person;
|
|
138
|
+
}
|
|
139
|
+
const name = best?.name.trim();
|
|
140
|
+
if (!name) return filing.filerName;
|
|
141
|
+
const isFiler = (!!filing.filerCik && best?.cik === filing.filerCik) || sameEntity(name, filing.filerName);
|
|
142
|
+
return isFiler && ALL_CAPS.test(name) && !ALL_CAPS.test(filing.filerName) ? filing.filerName : name;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Today's count against the report's own base outside this range is another class or unit, not the same shares. */
|
|
146
|
+
const BASE_RANGE = [2 / 3, 3 / 2] as const;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* The report's shares as a percent of today's shares outstanding, when the
|
|
150
|
+
* count the filer divided by (shares over the filed percent) is no longer
|
|
151
|
+
* today's. A filed percent is rounded, so a gap within that rounding (0.1
|
|
152
|
+
* point, or 2% of the stake) is not a new count. Null for an exit, a report
|
|
153
|
+
* without both figures, or a count that cannot be this class's.
|
|
154
|
+
*/
|
|
155
|
+
export function stakeToday(
|
|
156
|
+
filing: Pick<BeneficialOwnerFiling, "shares" | "percentOfClass">,
|
|
157
|
+
sharesOutstanding: number | null | undefined,
|
|
158
|
+
): StakeToday | null {
|
|
159
|
+
const { shares, percentOfClass: filed } = filing;
|
|
160
|
+
if (sharesOutstanding == null || !(sharesOutstanding > 0) || shares == null || !(shares > 0) || filed == null || !(filed > 0)) return null;
|
|
161
|
+
const base = shares / (filed / 100);
|
|
162
|
+
const ratio = base / sharesOutstanding;
|
|
163
|
+
if (ratio < BASE_RANGE[0] || ratio > BASE_RANGE[1]) return null;
|
|
164
|
+
const percent = (shares / sharesOutstanding) * 100;
|
|
165
|
+
if (Math.abs(percent - filed) < Math.max(0.1, filed * 0.02)) return null;
|
|
166
|
+
return { percent, sharesOutstanding };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** `about 49.4% on 35.26M sh today`. */
|
|
170
|
+
export function formatStakeToday(today: StakeToday): string {
|
|
171
|
+
return `about ${formatClassPercent(today.percent)} on ${formatCompact(today.sharesOutstanding)} sh today`;
|
|
172
|
+
}
|
|
173
|
+
|
|
96
174
|
function beneficialFormLabel(filing: Pick<BeneficialOwnerFiling, "kind" | "amendment">): string {
|
|
97
175
|
return `${filing.kind}${filing.amendment ? "/A" : ""}`;
|
|
98
176
|
}
|
|
@@ -110,10 +188,14 @@ export function buildBeneficialRows(
|
|
|
110
188
|
filings: readonly BeneficialOwnerFiling[],
|
|
111
189
|
holders: readonly JoinableHolder[] = [],
|
|
112
190
|
fundMatches: ReadonlyMap<string, Pick<Holder13FMatch, "cik">> = new Map(),
|
|
191
|
+
sharesOutstanding?: number | null,
|
|
113
192
|
): BeneficialOwnerRow[] {
|
|
114
193
|
return filings.map((filing) => ({
|
|
115
194
|
id: `${filing.accessionNumber}:${filing.filerCik ?? filing.filerName}`,
|
|
116
195
|
filing,
|
|
196
|
+
holderName: beneficialHolderName(filing),
|
|
197
|
+
otherPersons: Math.max(0, filing.reportingPersons.length - 1),
|
|
198
|
+
today: stakeToday(filing, sharesOutstanding),
|
|
117
199
|
formLabel: beneficialFormLabel(filing),
|
|
118
200
|
changePoints: pointChange(filing),
|
|
119
201
|
thirteenF: thirteenFAction(matchFilerToHolder(filing, holders, fundMatches)),
|
|
@@ -123,7 +205,7 @@ export function buildBeneficialRows(
|
|
|
123
205
|
|
|
124
206
|
function sortValue(row: BeneficialOwnerRow, columnId: BeneficialColumnId): string | number | null {
|
|
125
207
|
switch (columnId) {
|
|
126
|
-
case "filer": return row.
|
|
208
|
+
case "filer": return row.holderName;
|
|
127
209
|
case "form": return row.formLabel;
|
|
128
210
|
case "percentOfClass": return row.filing.percentOfClass;
|
|
129
211
|
case "change": return row.changePoints;
|
|
@@ -148,7 +230,7 @@ export function sortBeneficialRows(rows: readonly BeneficialOwnerRow[], preferen
|
|
|
148
230
|
return [...rows].sort((left, right) => stakeGroup(left) - stakeGroup(right)
|
|
149
231
|
|| compareSortValues(sortValue(left, preference.columnId), sortValue(right, preference.columnId), preference.direction)
|
|
150
232
|
|| right.filing.filingDate.localeCompare(left.filing.filingDate)
|
|
151
|
-
|| left.
|
|
233
|
+
|| left.holderName.localeCompare(right.holderName));
|
|
152
234
|
}
|
|
153
235
|
|
|
154
236
|
// Widths as the table draws them: never narrower than the header and its sort marker.
|
|
@@ -249,14 +331,19 @@ export function formatOwnerShares(value: number | null): string {
|
|
|
249
331
|
export function beneficialReportRow(row: BeneficialOwnerRow) {
|
|
250
332
|
const { filing } = row;
|
|
251
333
|
return {
|
|
252
|
-
filer:
|
|
334
|
+
filer: row.holderName,
|
|
335
|
+
/** The other reporting persons on the report, which text marks `+N` after the name. */
|
|
336
|
+
otherPersons: row.otherPersons,
|
|
253
337
|
filerCik: filing.filerCik,
|
|
254
338
|
form: row.formLabel,
|
|
255
339
|
formType: filing.form,
|
|
256
340
|
kind: filing.kind,
|
|
257
341
|
amendment: filing.amendment,
|
|
258
342
|
amendmentNo: filing.amendmentNo,
|
|
343
|
+
/** As filed: the filer's shares over the share count it used. */
|
|
259
344
|
percentOfClass: filing.percentOfClass,
|
|
345
|
+
/** The same shares over today's shares outstanding, only when that count is no longer the report's base. */
|
|
346
|
+
percentToday: row.today ? Number(row.today.percent.toFixed(2)) : null,
|
|
260
347
|
previousPercent: filing.previousPercent ?? null,
|
|
261
348
|
changePoints: row.changePoints,
|
|
262
349
|
shares: filing.shares,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
buildBeneficialRows,
|
|
6
6
|
DEFAULT_BENEFICIAL_SORT,
|
|
7
7
|
formatClassPercent,
|
|
8
|
+
formatFilerName,
|
|
8
9
|
formatOwnerShares,
|
|
9
10
|
formatPointChange,
|
|
10
11
|
stakeMarker,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
type BeneficialSortPreference,
|
|
14
15
|
} from "./beneficial-model";
|
|
15
16
|
import { buildRows } from "./table-model";
|
|
17
|
+
import { formatCompact } from "../../../utils/format";
|
|
16
18
|
|
|
17
19
|
/** What `holders --form` lists: the 13F table, or the 13D/13G beneficial owners. */
|
|
18
20
|
export type HolderForm = "13f" | "13d" | "13g" | "all";
|
|
@@ -27,9 +29,23 @@ export function beneficialRouteForm(form: Exclude<HolderForm, "13f">): Beneficia
|
|
|
27
29
|
return form === "13d" ? "13D" : form === "13g" ? "13G" : "all";
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
const num = (value: unknown) => (typeof value === "number" && Number.isFinite(value) ? value : null);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Columns for the 13D/13G rows. `textFormat` is what text prints (`holders
|
|
36
|
+
* --form` and `fn HDS --form`); `fn HDS --csv` reads `format`, and `holders
|
|
37
|
+
* --csv` and JSON keep the raw values. `% Class` is as filed; `% Today` is
|
|
38
|
+
* the same shares over today's count, only where that count is no longer the
|
|
39
|
+
* report's base.
|
|
40
|
+
*/
|
|
31
41
|
export const BENEFICIAL_REPORT_COLUMNS = [
|
|
32
|
-
{
|
|
42
|
+
{
|
|
43
|
+
key: "filer",
|
|
44
|
+
header: "Filer",
|
|
45
|
+
maxWidth: 32,
|
|
46
|
+
// `+N` counts the report's other reporting persons; a long name gives way before it does.
|
|
47
|
+
textFormat: (value: unknown, row: Record<string, unknown>) => formatFilerName(String(value ?? ""), num(row.otherPersons) ?? 0, 32),
|
|
48
|
+
},
|
|
33
49
|
{ key: "form", header: "Form" },
|
|
34
50
|
{
|
|
35
51
|
key: "percentOfClass",
|
|
@@ -41,6 +57,13 @@ export const BENEFICIAL_REPORT_COLUMNS = [
|
|
|
41
57
|
return marker ? `${formatClassPercent(value)} ${marker}` : formatClassPercent(value);
|
|
42
58
|
},
|
|
43
59
|
},
|
|
60
|
+
{
|
|
61
|
+
key: "percentToday",
|
|
62
|
+
header: "% Today",
|
|
63
|
+
align: "right" as const,
|
|
64
|
+
format: (value: unknown) => num(value) == null ? "" : `${num(value)!.toFixed(2)}%`,
|
|
65
|
+
textFormat: (value: unknown) => num(value) == null ? "" : `about ${formatClassPercent(num(value)!)}`,
|
|
66
|
+
},
|
|
44
67
|
{
|
|
45
68
|
key: "changePoints",
|
|
46
69
|
header: "Chg",
|
|
@@ -58,6 +81,28 @@ export const BENEFICIAL_REPORT_COLUMNS = [
|
|
|
58
81
|
{ key: "thirteenF", header: "13F", align: "right" as const, format: (value: unknown) => typeof value === "string" ? value : "-" },
|
|
59
82
|
];
|
|
60
83
|
|
|
84
|
+
/** The 13D/13G columns these rows fill: `% Today` only when a report's base is no longer today's count. */
|
|
85
|
+
export function beneficialReportColumns(rows: readonly BeneficialReportRow[]): typeof BENEFICIAL_REPORT_COLUMNS {
|
|
86
|
+
const today = rows.some((row) => row.percentToday != null);
|
|
87
|
+
return BENEFICIAL_REPORT_COLUMNS.filter((column) => today || column.key !== "percentToday");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The legend under the 13D/13G table, one line: the percent is as filed, what
|
|
92
|
+
* `% Today` divides by, and what `+N` after a name counts.
|
|
93
|
+
*/
|
|
94
|
+
export function beneficialReportLegend(
|
|
95
|
+
rows: readonly BeneficialReportRow[],
|
|
96
|
+
sharesOutstanding: number | null | undefined,
|
|
97
|
+
): string | null {
|
|
98
|
+
if (rows.length === 0) return null;
|
|
99
|
+
const today = sharesOutstanding != null && rows.some((row) => row.percentToday != null)
|
|
100
|
+
? `; % Today is the same shares over ${formatCompact(sharesOutstanding)} shares outstanding today`
|
|
101
|
+
: "";
|
|
102
|
+
const others = rows.some((row) => row.otherPersons > 0) ? " +N after a name: other reporting persons on the same report." : "";
|
|
103
|
+
return `% Class is as filed${today}.${others}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
61
106
|
const filings = (count: number) => `${count} ${count === 1 ? "filing" : "filings"}`;
|
|
62
107
|
|
|
63
108
|
/**
|
|
@@ -114,13 +159,20 @@ export function buildBeneficialReportRows(
|
|
|
114
159
|
history = false,
|
|
115
160
|
holders = null,
|
|
116
161
|
sort = DEFAULT_BENEFICIAL_SORT,
|
|
117
|
-
|
|
162
|
+
sharesOutstanding = null,
|
|
163
|
+
}: {
|
|
164
|
+
history?: boolean;
|
|
165
|
+
holders?: HolderData | null;
|
|
166
|
+
sort?: BeneficialSortPreference;
|
|
167
|
+
/** Today's shares outstanding in the class's own unit, for `percentToday`. */
|
|
168
|
+
sharesOutstanding?: number | null;
|
|
169
|
+
} = {},
|
|
118
170
|
): BeneficialReportRow[] {
|
|
119
171
|
const holderRows = buildRows(holders);
|
|
120
172
|
if (history) {
|
|
121
173
|
const filings = [...(payload.filings ?? payload.owners)]
|
|
122
174
|
.sort((left, right) => right.filingDate.localeCompare(left.filingDate));
|
|
123
|
-
return buildBeneficialRows(filings, holderRows).map(beneficialReportRow);
|
|
175
|
+
return buildBeneficialRows(filings, holderRows, undefined, sharesOutstanding).map(beneficialReportRow);
|
|
124
176
|
}
|
|
125
|
-
return sortBeneficialRows(buildBeneficialRows(payload.owners, holderRows), sort).map(beneficialReportRow);
|
|
177
|
+
return sortBeneficialRows(buildBeneficialRows(payload.owners, holderRows, undefined, sharesOutstanding), sort).map(beneficialReportRow);
|
|
126
178
|
}
|