gloomberb 0.16.0 → 0.16.2
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 +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +44 -11
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +5 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/members.ts +26 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +41 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +9 -1
- package/src/app/global-shortcuts.ts +14 -6
- package/src/app/keybindings/actions.ts +1 -1
- package/src/app/runtime/update.ts +38 -2
- package/src/app.tsx +10 -6
- package/src/brokers/account-cache.ts +24 -0
- package/src/cli/commands/command-utils.ts +8 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +414 -106
- package/src/cli/commands/overview.ts +77 -32
- package/src/cli/commands/ticker.ts +101 -43
- package/src/cli/desktop-pane-shot.ts +34 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +1 -0
- package/src/cli/helpers.ts +4 -8
- package/src/cli/index.ts +12 -2
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +20 -2
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +36 -22
- package/src/cli/pane-functions/headless.ts +39 -11
- package/src/cli/pane-functions/index.ts +15 -4
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +35 -7
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +7 -3
- package/src/cli/result.ts +41 -27
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/commands/collection.ts +5 -1
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/root/command-items.ts +9 -2
- package/src/components/command-bar/routes/root/plugin-install.ts +2 -2
- package/src/components/command-bar/routes/root/provider-search.ts +19 -5
- package/src/components/command-bar/routes/root/runtime.ts +14 -5
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +31 -5
- package/src/components/command-bar/routes/ticker-search/route.ts +2 -2
- package/src/components/command-bar/routing/actions.ts +2 -0
- package/src/components/command-bar/selection-runtime.ts +38 -0
- package/src/components/command-bar/surface/index.tsx +7 -2
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/view.tsx +29 -10
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/index.ts +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/floating-pane.tsx +6 -0
- package/src/components/layout/header.tsx +24 -7
- package/src/components/layout/missing-pane.tsx +2 -2
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +61 -28
- package/src/components/layout/pane/index.tsx +6 -0
- package/src/components/layout/pane/title.ts +31 -7
- package/src/components/layout/shell/drag/index.ts +6 -5
- package/src/components/layout/shell/drag/runtime.ts +3 -0
- package/src/components/layout/shell/index.tsx +6 -0
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +29 -10
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -3
- package/src/components/layout/shell/ticker-link-menu.ts +23 -9
- package/src/components/metric-treemap/heat-surface.tsx +745 -0
- package/src/components/metric-treemap/heat-tiles.ts +228 -0
- package/src/components/metric-treemap/index.tsx +2 -0
- package/src/components/metric-treemap/layout.ts +8 -0
- package/src/components/metric-treemap/scene.ts +432 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/toggle-list.tsx +38 -12
- package/src/components/ui/country-flag-art.tsx +449 -0
- package/src/components/ui/country-flag.tsx +41 -0
- package/src/components/ui/data-table/types.ts +13 -0
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/icon.tsx +2 -0
- package/src/components/ui/index.ts +4 -0
- package/src/components/ui/multi-select/dialog.tsx +108 -22
- package/src/components/ui/range-track.tsx +53 -0
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +11 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/core/state/app/types.ts +10 -1
- package/src/data/config/store/normalize.ts +17 -1
- package/src/i18n/es.ts +24 -4
- package/src/i18n/ja.ts +24 -4
- package/src/i18n/ko.ts +24 -4
- package/src/i18n/zh-cn.ts +24 -4
- package/src/i18n/zh-tw.ts +24 -4
- package/src/layout/ticker-navigation.ts +28 -2
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +78 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +8 -0
- package/src/market-data/quotes/freshness.ts +36 -0
- package/src/market-data/quotes/resolution.ts +24 -8
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/market-data/quotes/time.ts +16 -0
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/risk-client.ts +330 -79
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +61 -49
- package/src/plugins/builtin/analytics/risk-math.ts +33 -13
- package/src/plugins/builtin/analytics/risk-model.ts +282 -64
- package/src/plugins/builtin/analytics/risk-pane.tsx +62 -30
- package/src/plugins/builtin/analytics/risk-test-data.ts +206 -0
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +1 -1
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/cells.tsx +15 -12
- package/src/plugins/builtin/buildout/detail/company.tsx +3 -3
- package/src/plugins/builtin/buildout/detail/index.tsx +0 -1
- package/src/plugins/builtin/buildout/detail/intel.tsx +6 -6
- package/src/plugins/builtin/buildout/detail/site.tsx +4 -7
- package/src/plugins/builtin/buildout/detail/ui.tsx +0 -19
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/catalysts/index.tsx +2 -2
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/cds/index.tsx +1 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +1 -1
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/debt-maturities/wall-bar.tsx +14 -41
- package/src/plugins/builtin/dividend-yield/client.ts +4 -2
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/client.ts +2 -2
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/fx-matrix/direction.ts +81 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +71 -33
- package/src/plugins/builtin/fx-matrix/live-legs.ts +17 -0
- package/src/plugins/builtin/fx-matrix/pairs.ts +68 -14
- package/src/plugins/builtin/fx-matrix/settings.ts +62 -0
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/headless.ts +139 -5
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +20 -3
- package/src/plugins/builtin/holders/report-header.ts +95 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/jobs/index.tsx +1 -0
- package/src/plugins/builtin/jobs/share-bars.tsx +5 -28
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +30 -2
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +245 -81
- package/src/plugins/builtin/market-heatmap/live.ts +88 -0
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +50 -11
- package/src/plugins/builtin/market-movers/client.ts +3 -2
- package/src/plugins/builtin/market-movers/headless.ts +10 -1
- package/src/plugins/builtin/market-movers/screener.ts +18 -5
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +53 -0
- package/src/plugins/builtin/members/headless.ts +35 -0
- package/src/plugins/builtin/members/index.tsx +20 -0
- package/src/plugins/builtin/members/model.ts +68 -0
- package/src/plugins/builtin/members/pane.tsx +175 -0
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/mna/index.tsx +2 -1
- package/src/plugins/builtin/mna/pane.tsx +5 -2
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +2 -1
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +74 -2
- package/src/plugins/builtin/pe-band/headless.ts +26 -8
- package/src/plugins/builtin/pe-band/model.ts +102 -22
- package/src/plugins/builtin/pe-band/pane.tsx +34 -16
- package/src/plugins/builtin/pe-band/report-dates.ts +78 -0
- package/src/plugins/builtin/perps/client.ts +66 -5
- package/src/plugins/builtin/perps/equity-identity.ts +16 -0
- package/src/plugins/builtin/perps/equity-row.tsx +6 -4
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +248 -47
- package/src/plugins/builtin/plugin-marketplace/activation.ts +19 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -2
- package/src/plugins/builtin/plugin-marketplace/store.ts +2 -0
- package/src/plugins/builtin/portfolio-list/allocation.ts +245 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +33 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +230 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +98 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +47 -13
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +43 -2
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +48 -5
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +24 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +11 -3
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/scanner/hilo-bars.tsx +12 -70
- package/src/plugins/builtin/scanner/hilo-model.ts +0 -18
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/move-bar.tsx +10 -32
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/index.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/index.tsx +2 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +7 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +5 -60
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -2
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +26 -26
- package/src/plugins/builtin/ticker-detail/pane.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +7 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +20 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +2 -2
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/vol-surface/index.tsx +1 -1
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +157 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +214 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +447 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +67 -4
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +552 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +348 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +381 -45
- package/src/plugins/builtin/world-venue-map/model.ts +7 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +199 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +28 -43
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/catalog-browser.ts +2 -0
- package/src/plugins/catalog-manifest.ts +1 -0
- package/src/plugins/catalog-ui.ts +3 -1
- package/src/plugins/catalog.ts +1 -1
- package/src/plugins/host-link.ts +33 -1
- package/src/plugins/installer.ts +48 -12
- package/src/plugins/loader.ts +30 -3
- package/src/plugins/manager-node.ts +15 -5
- package/src/plugins/registry/index.ts +1 -1
- package/src/plugins/registry/pane-settings.ts +26 -7
- package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/row.tsx +52 -16
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/icons.tsx +1 -0
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +69 -26
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/tabs.tsx +37 -1
- package/src/renderers/dom/styles.css +41 -7
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +11 -6
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +181 -87
- package/src/renderers/electrobun/bun/index.ts +73 -6
- package/src/renderers/electrobun/bun/window/remembered-frame.ts +122 -0
- package/src/renderers/electrobun/shared/protocol.ts +3 -0
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -1
- package/src/renderers/electrobun/view/main.tsx +7 -1
- package/src/renderers/electrobun/view/renderer-window-error.ts +18 -0
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/update-host.ts +45 -21
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +36 -5
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financials.ts +11 -8
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/benign-window-error.ts +7 -0
- package/src/telemetry/crash-reports-dom.ts +2 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/daily-nav.ts +25 -0
- package/src/theme/heat-colors.ts +357 -2
- package/src/tickers/instrument-kind.ts +34 -7
- package/src/tickers/search/asset-classes.ts +24 -9
- package/src/tickers/search/index.ts +44 -11
- package/src/tickers/search/ranking.ts +23 -3
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +5 -0
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +38 -6
- package/src/types/ticker.ts +15 -0
- package/src/ui/context-menu.tsx +1 -0
- package/src/ui/host.tsx +16 -0
- package/src/updater/index.ts +38 -13
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +14 -0
- package/src/utils/depositary-receipt.ts +26 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { apiClient } from "../../../api-client";
|
|
2
|
+
import type {
|
|
3
|
+
BeneficialOwnerFiling,
|
|
4
|
+
BeneficialOwnerReportingPerson,
|
|
5
|
+
BeneficialOwnerStatus,
|
|
6
|
+
BeneficialOwnersForm,
|
|
7
|
+
BeneficialOwnersPayload,
|
|
8
|
+
} from "../../../api-client/beneficial-owners";
|
|
9
|
+
import { ApiRequestError, isAccessDenied } from "../../../api-client/errors";
|
|
10
|
+
import { createPluginCache } from "../../../data/plugin-cache";
|
|
11
|
+
import { finiteOrNull, recordOrNull } from "../../../utils/guards";
|
|
12
|
+
import { cachedCloudResource, loadCloudResource, type CloudResource } from "../shared/cloud-resource";
|
|
13
|
+
import { CLOUD_SESSION_REQUIRED } from "../shared/research-cloud-session";
|
|
14
|
+
|
|
15
|
+
/** One page of the route; the loader follows `nextOffset` until it has every report. */
|
|
16
|
+
const PAGE_SIZE = 100;
|
|
17
|
+
/** More than any issuer has filers; a history this long is cut and marked incomplete. */
|
|
18
|
+
const MAX_ROWS = 2_000;
|
|
19
|
+
|
|
20
|
+
export const beneficialOwnersCache = createPluginCache<BeneficialOwnersPayload>({
|
|
21
|
+
kind: "beneficial-owners",
|
|
22
|
+
source: "gloom-cloud",
|
|
23
|
+
schemaVersion: 1,
|
|
24
|
+
policy: { staleMs: 30 * 60_000, expireMs: 7 * 24 * 60 * 60_000 },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export interface BeneficialOwnersRequest {
|
|
28
|
+
form?: BeneficialOwnersForm;
|
|
29
|
+
/** Every report instead of the latest per filer. */
|
|
30
|
+
history?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type BeneficialOwnersClient = Pick<typeof apiClient, "getCloudSecBeneficialOwners">;
|
|
34
|
+
|
|
35
|
+
const text = (value: unknown): string | null => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
36
|
+
const isoDate = (value: unknown): string | null => {
|
|
37
|
+
const raw = text(value);
|
|
38
|
+
return raw && /^\d{4}-\d{2}-\d{2}/.test(raw) ? raw.slice(0, 10) : null;
|
|
39
|
+
};
|
|
40
|
+
const cikOrNull = (value: unknown): string | null => {
|
|
41
|
+
const raw = typeof value === "number" ? String(value) : text(value);
|
|
42
|
+
return raw && /\d/.test(raw) ? raw : null;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function normalizeReportingPerson(value: unknown): BeneficialOwnerReportingPerson | null {
|
|
46
|
+
const raw = recordOrNull(value);
|
|
47
|
+
const name = text(raw?.name);
|
|
48
|
+
if (!raw || !name) return null;
|
|
49
|
+
return { name, cik: cikOrNull(raw.cik), percentOfClass: finiteOrNull(raw.percentOfClass), shares: finiteOrNull(raw.shares) };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const STATUSES: readonly BeneficialOwnerStatus[] = ["holder", "below-threshold", "exited"];
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A report as the table can trust it. Fields the route adds later pass
|
|
56
|
+
* through; a report without a filer, accession or filing date is dropped,
|
|
57
|
+
* and a number that is not one stays null instead of being guessed. History
|
|
58
|
+
* reports carry no previous report or status, and none is made up for them.
|
|
59
|
+
*/
|
|
60
|
+
function normalizeBeneficialOwnerFiling(value: unknown): BeneficialOwnerFiling | null {
|
|
61
|
+
const raw = recordOrNull(value);
|
|
62
|
+
if (!raw) return null;
|
|
63
|
+
const filerName = text(raw.filerName);
|
|
64
|
+
const accessionNumber = text(raw.accessionNumber);
|
|
65
|
+
const filingDate = isoDate(raw.filingDate);
|
|
66
|
+
const form = text(raw.form) ?? "";
|
|
67
|
+
const kind = raw.kind === "13D" || raw.kind === "13G" ? raw.kind
|
|
68
|
+
: /13D/i.test(form) ? "13D" : /13G/i.test(form) ? "13G" : null;
|
|
69
|
+
if (!filerName || !accessionNumber || !filingDate || !kind) return null;
|
|
70
|
+
const source = raw.source === "xml" || raw.source === "text" ? raw.source : "index";
|
|
71
|
+
return {
|
|
72
|
+
...raw,
|
|
73
|
+
filerCik: cikOrNull(raw.filerCik),
|
|
74
|
+
filerName,
|
|
75
|
+
form: form || `SCHEDULE ${kind}`,
|
|
76
|
+
kind,
|
|
77
|
+
amendment: raw.amendment === true || /\/A\b/i.test(form),
|
|
78
|
+
amendmentNo: finiteOrNull(raw.amendmentNo),
|
|
79
|
+
percentOfClass: finiteOrNull(raw.percentOfClass),
|
|
80
|
+
shares: finiteOrNull(raw.shares),
|
|
81
|
+
classTitle: text(raw.classTitle),
|
|
82
|
+
cusip: text(raw.cusip),
|
|
83
|
+
eventDate: isoDate(raw.eventDate),
|
|
84
|
+
filingDate,
|
|
85
|
+
accessionNumber,
|
|
86
|
+
filingUrl: text(raw.filingUrl) ?? "",
|
|
87
|
+
previousPercent: "previousPercent" in raw ? finiteOrNull(raw.previousPercent) : undefined,
|
|
88
|
+
previousFilingDate: "previousFilingDate" in raw ? isoDate(raw.previousFilingDate) : undefined,
|
|
89
|
+
status: STATUSES.includes(raw.status as BeneficialOwnerStatus) ? raw.status as BeneficialOwnerStatus : undefined,
|
|
90
|
+
provisional: raw.provisional === true ? true : undefined,
|
|
91
|
+
source,
|
|
92
|
+
reportingPersons: Array.isArray(raw.reportingPersons)
|
|
93
|
+
? raw.reportingPersons.map(normalizeReportingPerson).filter((person) => person != null)
|
|
94
|
+
: [],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function normalizeFilings(value: unknown): BeneficialOwnerFiling[] {
|
|
99
|
+
return Array.isArray(value)
|
|
100
|
+
? value.map(normalizeBeneficialOwnerFiling).filter((filing) => filing != null)
|
|
101
|
+
: [];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function normalizeBeneficialOwnersPayload(value: unknown, ticker: string): BeneficialOwnersPayload {
|
|
105
|
+
const raw = recordOrNull(value);
|
|
106
|
+
if (!raw || !Array.isArray(raw.owners)) throw new Error("The server returned an invalid 13D/13G list");
|
|
107
|
+
const coverage = recordOrNull(raw.coverage);
|
|
108
|
+
const nextOffset = finiteOrNull(raw.nextOffset);
|
|
109
|
+
return {
|
|
110
|
+
...raw,
|
|
111
|
+
ticker: text(raw.ticker) ?? ticker,
|
|
112
|
+
cik: cikOrNull(raw.cik) ?? "",
|
|
113
|
+
companyName: text(raw.companyName) ?? "",
|
|
114
|
+
asOf: text(raw.asOf),
|
|
115
|
+
owners: normalizeFilings(raw.owners),
|
|
116
|
+
...(Array.isArray(raw.filings) ? { filings: normalizeFilings(raw.filings) } : {}),
|
|
117
|
+
hasMore: raw.hasMore === true && nextOffset != null,
|
|
118
|
+
nextOffset,
|
|
119
|
+
coverage: coverage ? {
|
|
120
|
+
...coverage,
|
|
121
|
+
from: isoDate(coverage.from),
|
|
122
|
+
filings: finiteOrNull(coverage.filings) ?? 0,
|
|
123
|
+
parsed: finiteOrNull(coverage.parsed) ?? 0,
|
|
124
|
+
unparsed: finiteOrNull(coverage.unparsed) ?? 0,
|
|
125
|
+
unavailable: finiteOrNull(coverage.unavailable) ?? 0,
|
|
126
|
+
} : null,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function describeFailure(error: unknown, ticker: string): unknown {
|
|
131
|
+
if (isAccessDenied(error)) return new Error(CLOUD_SESSION_REQUIRED);
|
|
132
|
+
// An unknown ticker, and a server that does not serve the route yet.
|
|
133
|
+
if (error instanceof ApiRequestError && error.status === 404) {
|
|
134
|
+
return new Error(`13D/13G filings are not available for ${ticker}.`);
|
|
135
|
+
}
|
|
136
|
+
return error;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Every page of the issuer's reports: the latest per filer, or with
|
|
141
|
+
* `history` every report. A list cut at the row cap keeps `hasMore`.
|
|
142
|
+
*/
|
|
143
|
+
export async function fetchBeneficialOwners(
|
|
144
|
+
ticker: string,
|
|
145
|
+
{ form = "all", history = false }: BeneficialOwnersRequest = {},
|
|
146
|
+
{ client = apiClient, signal }: { client?: BeneficialOwnersClient; signal?: AbortSignal } = {},
|
|
147
|
+
): Promise<BeneficialOwnersPayload> {
|
|
148
|
+
const symbol = ticker.trim().toUpperCase();
|
|
149
|
+
try {
|
|
150
|
+
let offset = 0;
|
|
151
|
+
let first: BeneficialOwnersPayload | null = null;
|
|
152
|
+
const owners: BeneficialOwnerFiling[] = [];
|
|
153
|
+
const filings: BeneficialOwnerFiling[] = [];
|
|
154
|
+
for (;;) {
|
|
155
|
+
const page = normalizeBeneficialOwnersPayload(await client.getCloudSecBeneficialOwners({
|
|
156
|
+
ticker: symbol,
|
|
157
|
+
form,
|
|
158
|
+
history,
|
|
159
|
+
limit: PAGE_SIZE,
|
|
160
|
+
offset,
|
|
161
|
+
}, { signal }), symbol);
|
|
162
|
+
first ??= page;
|
|
163
|
+
owners.push(...page.owners);
|
|
164
|
+
filings.push(...(page.filings ?? []));
|
|
165
|
+
const loaded = history ? filings.length : owners.length;
|
|
166
|
+
const nextOffset = page.nextOffset ?? 0;
|
|
167
|
+
if (!page.hasMore || nextOffset <= offset || loaded >= MAX_ROWS) {
|
|
168
|
+
return {
|
|
169
|
+
...first,
|
|
170
|
+
asOf: page.asOf ?? first.asOf,
|
|
171
|
+
coverage: page.coverage ?? first.coverage,
|
|
172
|
+
owners: dedupe(owners),
|
|
173
|
+
...(history ? { filings: dedupe(filings) } : {}),
|
|
174
|
+
hasMore: page.hasMore,
|
|
175
|
+
nextOffset: page.nextOffset,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
offset = nextOffset;
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
throw describeFailure(error, symbol);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Pages can overlap when a report lands between two requests. */
|
|
186
|
+
function dedupe(rows: BeneficialOwnerFiling[]): BeneficialOwnerFiling[] {
|
|
187
|
+
const seen = new Set<string>();
|
|
188
|
+
return rows.filter((row) => {
|
|
189
|
+
const key = `${row.accessionNumber}:${row.filerCik ?? row.filerName}`;
|
|
190
|
+
if (seen.has(key)) return false;
|
|
191
|
+
seen.add(key);
|
|
192
|
+
return true;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const cacheKey = (ticker: string) => ticker.trim().toUpperCase();
|
|
197
|
+
|
|
198
|
+
export function cachedBeneficialOwners(ticker: string): CloudResource<BeneficialOwnersPayload> | null {
|
|
199
|
+
return cachedCloudResource(beneficialOwnersCache, cacheKey(ticker));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The pane's list: the latest report per filer, both kinds, cached on disk. */
|
|
203
|
+
export async function loadBeneficialOwners(ticker: string, force = false): Promise<CloudResource<BeneficialOwnersPayload>> {
|
|
204
|
+
try {
|
|
205
|
+
return await loadCloudResource(beneficialOwnersCache, cacheKey(ticker), () => fetchBeneficialOwners(ticker), { force });
|
|
206
|
+
} catch (error) {
|
|
207
|
+
throw describeFailure(error, cacheKey(ticker));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import type { BeneficialOwnerFiling, BeneficialOwnerStatus } from "../../../api-client/beneficial-owners";
|
|
2
|
+
import type { DataTableColumn } from "../../../components";
|
|
3
|
+
import type { HolderRecord } from "../../../types/financials";
|
|
4
|
+
import { clipToDisplayWidth, displayWidth, formatCompact } from "../../../utils/format";
|
|
5
|
+
import { compareSortValues, type SortDirection } from "../../../utils/sort-values";
|
|
6
|
+
import { matchFilerToHolder, type Holder13FMatch } from "./thirteenf-match";
|
|
7
|
+
|
|
8
|
+
export type BeneficialColumnId =
|
|
9
|
+
| "filer"
|
|
10
|
+
| "form"
|
|
11
|
+
| "percentOfClass"
|
|
12
|
+
| "change"
|
|
13
|
+
| "shares"
|
|
14
|
+
| "eventDate"
|
|
15
|
+
| "filingDate"
|
|
16
|
+
| "thirteenF";
|
|
17
|
+
export type BeneficialColumn = DataTableColumn & { id: BeneficialColumnId };
|
|
18
|
+
|
|
19
|
+
export interface BeneficialSortPreference {
|
|
20
|
+
columnId: BeneficialColumnId;
|
|
21
|
+
direction: SortDirection;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const DEFAULT_BENEFICIAL_SORT: BeneficialSortPreference = { columnId: "percentOfClass", direction: "desc" };
|
|
25
|
+
|
|
26
|
+
/** What the filer did in its latest 13F against the quarter before. */
|
|
27
|
+
export interface ThirteenFAction {
|
|
28
|
+
label: string;
|
|
29
|
+
/** The share change as a fraction of the prior position: NEW sorts first, EXIT is -1. */
|
|
30
|
+
value: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface BeneficialOwnerRow {
|
|
34
|
+
id: string;
|
|
35
|
+
filing: BeneficialOwnerFiling;
|
|
36
|
+
/** `13G/A`: the kind, and `/A` for an amendment. */
|
|
37
|
+
formLabel: string;
|
|
38
|
+
/** Percent points against the filer's report before this one. */
|
|
39
|
+
changePoints: number | null;
|
|
40
|
+
thirteenF: ThirteenFAction | null;
|
|
41
|
+
/** The stake the report discloses; null when the report gives neither a percentage nor shares. */
|
|
42
|
+
stake: BeneficialOwnerStatus | null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Holder rows the 13F join reads: the Table tab's rows, keyed by their id. */
|
|
46
|
+
type JoinableHolder = HolderRecord & { id: string };
|
|
47
|
+
|
|
48
|
+
/** The Schedule 13D/13G reporting threshold, in percent of the class. */
|
|
49
|
+
const REPORTING_THRESHOLD = 5;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The stake a report discloses, from its own figures first, as the route
|
|
53
|
+
* reads them. A stake under 5% is still a stake; only a report whose figures
|
|
54
|
+
* are all zero (0% and zero shares, or one of them with the other missing)
|
|
55
|
+
* is an exit, and a contradictory one is not. A report with neither figure
|
|
56
|
+
* keeps the route's word for a stake under the threshold, but is never read
|
|
57
|
+
* as an exit.
|
|
58
|
+
*/
|
|
59
|
+
export function disclosedStake(
|
|
60
|
+
filing: Pick<BeneficialOwnerFiling, "percentOfClass" | "shares" | "status">,
|
|
61
|
+
): BeneficialOwnerStatus | null {
|
|
62
|
+
const { percentOfClass: percent, shares } = filing;
|
|
63
|
+
const reported = [percent, shares].filter((value) => value != null);
|
|
64
|
+
if (reported.length > 0 && reported.every((value) => value === 0)) return "exited";
|
|
65
|
+
if (percent != null) return percent < REPORTING_THRESHOLD ? "below-threshold" : "holder";
|
|
66
|
+
return filing.status === "holder" || filing.status === "below-threshold" ? filing.status : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function signedPercent(fraction: number): string {
|
|
70
|
+
const rounded = Math.round(fraction * 100);
|
|
71
|
+
return rounded > 0 ? `+${rounded}%` : rounded < 0 ? `${rounded}%` : "0%";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The quarter's action from a 13F holder row. A position that grew from
|
|
76
|
+
* nothing is NEW, one reported at zero shares after a sale EXIT; without a
|
|
77
|
+
* reported change it is unknown, never "no change".
|
|
78
|
+
*/
|
|
79
|
+
export function thirteenFAction(holder: HolderRecord | undefined): ThirteenFAction | null {
|
|
80
|
+
if (!holder) return null;
|
|
81
|
+
const { shares, changeShares, changePercent } = holder;
|
|
82
|
+
if (shares === 0 && changeShares != null && changeShares < 0) return { label: "EXIT", value: -1 };
|
|
83
|
+
if (shares != null && changeShares != null) {
|
|
84
|
+
const prior = shares - changeShares;
|
|
85
|
+
if (changeShares > 0 && prior === 0) return { label: "NEW", value: Number.POSITIVE_INFINITY };
|
|
86
|
+
if (prior > 0) return { label: signedPercent(changeShares / prior), value: changeShares / prior };
|
|
87
|
+
}
|
|
88
|
+
if (changePercent != null && Number.isFinite(changePercent)) {
|
|
89
|
+
// The Table tab reads a provider's change the same way: a fraction up to 1, percent points above.
|
|
90
|
+
const fraction = Math.abs(changePercent) <= 1 ? changePercent : changePercent / 100;
|
|
91
|
+
return { label: signedPercent(fraction), value: fraction };
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function beneficialFormLabel(filing: Pick<BeneficialOwnerFiling, "kind" | "amendment">): string {
|
|
97
|
+
return `${filing.kind}${filing.amendment ? "/A" : ""}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function pointChange(filing: BeneficialOwnerFiling): number | null {
|
|
101
|
+
if (filing.percentOfClass == null || filing.previousPercent == null) return null;
|
|
102
|
+
return Math.round((filing.percentOfClass - filing.previousPercent) * 100) / 100;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* One row per report, joined to the filer's 13F holder row (CIK first, then
|
|
107
|
+
* name) for the quarter's action.
|
|
108
|
+
*/
|
|
109
|
+
export function buildBeneficialRows(
|
|
110
|
+
filings: readonly BeneficialOwnerFiling[],
|
|
111
|
+
holders: readonly JoinableHolder[] = [],
|
|
112
|
+
fundMatches: ReadonlyMap<string, Pick<Holder13FMatch, "cik">> = new Map(),
|
|
113
|
+
): BeneficialOwnerRow[] {
|
|
114
|
+
return filings.map((filing) => ({
|
|
115
|
+
id: `${filing.accessionNumber}:${filing.filerCik ?? filing.filerName}`,
|
|
116
|
+
filing,
|
|
117
|
+
formLabel: beneficialFormLabel(filing),
|
|
118
|
+
changePoints: pointChange(filing),
|
|
119
|
+
thirteenF: thirteenFAction(matchFilerToHolder(filing, holders, fundMatches)),
|
|
120
|
+
stake: disclosedStake(filing),
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function sortValue(row: BeneficialOwnerRow, columnId: BeneficialColumnId): string | number | null {
|
|
125
|
+
switch (columnId) {
|
|
126
|
+
case "filer": return row.filing.filerName;
|
|
127
|
+
case "form": return row.formLabel;
|
|
128
|
+
case "percentOfClass": return row.filing.percentOfClass;
|
|
129
|
+
case "change": return row.changePoints;
|
|
130
|
+
case "shares": return row.filing.shares;
|
|
131
|
+
case "eventDate": return row.filing.eventDate;
|
|
132
|
+
case "filingDate": return row.filing.filingDate;
|
|
133
|
+
case "thirteenF": {
|
|
134
|
+
const value = row.thirteenF?.value;
|
|
135
|
+
// NEW leads a descending sort without leaving the finite range compareSortValues keeps.
|
|
136
|
+
return value == null ? null : value === Number.POSITIVE_INFINITY ? Number.MAX_SAFE_INTEGER : value;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Filers over the threshold (or not saying) first, then stakes under 5%, then exits. */
|
|
142
|
+
function stakeGroup(row: BeneficialOwnerRow): number {
|
|
143
|
+
return row.stake === "exited" ? 2 : row.stake === "below-threshold" ? 1 : 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Sorted by the column within each stake group, whatever the direction; ties newest filing first. */
|
|
147
|
+
export function sortBeneficialRows(rows: readonly BeneficialOwnerRow[], preference: BeneficialSortPreference): BeneficialOwnerRow[] {
|
|
148
|
+
return [...rows].sort((left, right) => stakeGroup(left) - stakeGroup(right)
|
|
149
|
+
|| compareSortValues(sortValue(left, preference.columnId), sortValue(right, preference.columnId), preference.direction)
|
|
150
|
+
|| right.filing.filingDate.localeCompare(left.filing.filingDate)
|
|
151
|
+
|| left.filing.filerName.localeCompare(right.filing.filerName));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Widths as the table draws them: never narrower than the header and its sort marker.
|
|
155
|
+
const FORM_WIDTH = 6;
|
|
156
|
+
/** `22.2%`, `4.9% <5%`, `0.0% EXIT`. */
|
|
157
|
+
const PERCENT_WIDTH = 9;
|
|
158
|
+
const CHANGE_WIDTH = 8;
|
|
159
|
+
const SHARES_WIDTH = 8;
|
|
160
|
+
const DATE_WIDTH = 10;
|
|
161
|
+
const THIRTEEN_F_WIDTH = 5;
|
|
162
|
+
const MIN_FILER_WIDTH = 14;
|
|
163
|
+
/** The longest filer names and a group count; a wider pane keeps the figures beside the names. */
|
|
164
|
+
const MAX_FILER_WIDTH = 56;
|
|
165
|
+
/** Below this the event date gives its room to the filer's name; the filing date stays. */
|
|
166
|
+
const EVENT_FILER_WIDTH = 20;
|
|
167
|
+
|
|
168
|
+
export function buildBeneficialColumns(width: number): BeneficialColumn[] {
|
|
169
|
+
const fixed = FORM_WIDTH + PERCENT_WIDTH + CHANGE_WIDTH + SHARES_WIDTH + DATE_WIDTH + THIRTEEN_F_WIDTH;
|
|
170
|
+
// Two cells of padding and one gap after every column.
|
|
171
|
+
const roomWithEvent = width - 2 - 8 - fixed - DATE_WIDTH;
|
|
172
|
+
const showEvent = roomWithEvent >= EVENT_FILER_WIDTH;
|
|
173
|
+
const filerWidth = Math.min(MAX_FILER_WIDTH, Math.max(MIN_FILER_WIDTH, showEvent ? roomWithEvent : roomWithEvent + DATE_WIDTH + 1));
|
|
174
|
+
return [
|
|
175
|
+
{ id: "filer", label: "FILER", width: filerWidth, align: "left" },
|
|
176
|
+
{ id: "form", label: "FORM", width: FORM_WIDTH, align: "left" },
|
|
177
|
+
{ id: "percentOfClass", label: "% CLASS", width: PERCENT_WIDTH, align: "right" },
|
|
178
|
+
{ id: "change", label: "CHG", width: CHANGE_WIDTH, align: "right" },
|
|
179
|
+
{ id: "shares", label: "SHARES", width: SHARES_WIDTH, align: "right" },
|
|
180
|
+
...(showEvent ? [{ id: "eventDate" as const, label: "EVENT", width: DATE_WIDTH, align: "right" as const }] : []),
|
|
181
|
+
{ id: "filingDate", label: "FILED", width: DATE_WIDTH, align: "right" },
|
|
182
|
+
{ id: "thirteenF", label: "13F", width: THIRTEEN_F_WIDTH, align: "right" },
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Entity suffixes a narrow column drops before it cuts into the name itself. */
|
|
187
|
+
const LEGAL_SUFFIX = /(?:[,\s]+(?:L\.?L\.?C|L\.?L\.?P|L\.?P|INC|LTD|LIMITED|CORP|CORPORATION|CO|PLC|N\.?A|S\.?A|AG|GMBH)\.?)+$/i;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The filer's name in `width` cells, with ` +N` for the other reporting
|
|
191
|
+
* persons of a group. The entity suffix goes first, then the name is cut
|
|
192
|
+
* behind an ellipsis; the count is never cut.
|
|
193
|
+
*/
|
|
194
|
+
export function formatFilerName(name: string, otherPersons: number, width: number): string {
|
|
195
|
+
const suffix = otherPersons > 0 ? ` +${otherPersons}` : "";
|
|
196
|
+
const room = Math.max(1, width - displayWidth(suffix));
|
|
197
|
+
if (displayWidth(name) <= room) return `${name}${suffix}`;
|
|
198
|
+
const short = name.replace(LEGAL_SUFFIX, "").trim() || name;
|
|
199
|
+
return `${clipToDisplayWidth(short, room)}${suffix}`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The marker after a stake that is not a 5% holding: under the threshold, or reported at zero. */
|
|
203
|
+
export function stakeMarker(stake: BeneficialOwnerStatus | null): string {
|
|
204
|
+
return stake === "below-threshold" ? "<5%" : stake === "exited" ? "EXIT" : "";
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* A percent of class to one decimal, or two when one would round a stake
|
|
209
|
+
* under 5% up to `5.0%`: 4.96 reads `4.96%`.
|
|
210
|
+
*/
|
|
211
|
+
export function formatClassPercent(value: number): string {
|
|
212
|
+
const short = value.toFixed(1);
|
|
213
|
+
if (value >= REPORTING_THRESHOLD || Number(short) < REPORTING_THRESHOLD) return `${short}%`;
|
|
214
|
+
return `${(Math.floor(value * 100) / 100).toFixed(2)}%`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The reported percent of class, as filed: `4.9%` stays `4.9%`. With
|
|
219
|
+
* `marker`, a stake under 5% reads `4.9% <5%` and a report of zero
|
|
220
|
+
* `0.0% EXIT`. A missing figure is a dash, or the bare marker when the
|
|
221
|
+
* route says which side of 5% the stake is on.
|
|
222
|
+
*/
|
|
223
|
+
export function formatPercentOfClass(
|
|
224
|
+
row: Pick<BeneficialOwnerRow, "stake" | "filing">,
|
|
225
|
+
{ marker = false }: { marker?: boolean } = {},
|
|
226
|
+
): string {
|
|
227
|
+
const value = row.filing.percentOfClass;
|
|
228
|
+
const mark = marker ? stakeMarker(row.stake) : "";
|
|
229
|
+
if (value == null) return mark || "-";
|
|
230
|
+
return mark ? `${formatClassPercent(value)} ${mark}` : formatClassPercent(value);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function formatPointChange(value: number | null): string {
|
|
234
|
+
if (value == null) return "";
|
|
235
|
+
const rounded = Math.round(value * 10) / 10;
|
|
236
|
+
if (rounded === 0) return "0.0 pt";
|
|
237
|
+
return `${rounded > 0 ? "+" : ""}${rounded.toFixed(1)} pt`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function formatOwnerShares(value: number | null): string {
|
|
241
|
+
return value == null ? "-" : formatCompact(value);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* A row as `holders --form` and `fn HDS --form` print it; the keys are the
|
|
246
|
+
* JSON contract. Numbers a report did not give stay null, and `status` is
|
|
247
|
+
* the disclosed stake, null when the report does not say.
|
|
248
|
+
*/
|
|
249
|
+
export function beneficialReportRow(row: BeneficialOwnerRow) {
|
|
250
|
+
const { filing } = row;
|
|
251
|
+
return {
|
|
252
|
+
filer: filing.filerName,
|
|
253
|
+
filerCik: filing.filerCik,
|
|
254
|
+
form: row.formLabel,
|
|
255
|
+
formType: filing.form,
|
|
256
|
+
kind: filing.kind,
|
|
257
|
+
amendment: filing.amendment,
|
|
258
|
+
amendmentNo: filing.amendmentNo,
|
|
259
|
+
percentOfClass: filing.percentOfClass,
|
|
260
|
+
previousPercent: filing.previousPercent ?? null,
|
|
261
|
+
changePoints: row.changePoints,
|
|
262
|
+
shares: filing.shares,
|
|
263
|
+
classTitle: filing.classTitle,
|
|
264
|
+
cusip: filing.cusip,
|
|
265
|
+
eventDate: filing.eventDate,
|
|
266
|
+
filingDate: filing.filingDate,
|
|
267
|
+
previousFilingDate: filing.previousFilingDate ?? null,
|
|
268
|
+
thirteenF: row.thirteenF?.label ?? null,
|
|
269
|
+
status: row.stake,
|
|
270
|
+
/** The route could not read every filing, so this may not be the filer's latest disclosure or its change may be off. */
|
|
271
|
+
provisional: filing.provisional === true,
|
|
272
|
+
parsedFrom: filing.source,
|
|
273
|
+
accessionNumber: filing.accessionNumber,
|
|
274
|
+
filingUrl: filing.filingUrl,
|
|
275
|
+
reportingPersons: filing.reportingPersons,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export type BeneficialReportRow = ReturnType<typeof beneficialReportRow>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { BeneficialOwnersCoverage, BeneficialOwnersForm, BeneficialOwnersPayload } from "../../../api-client/beneficial-owners";
|
|
2
|
+
import type { HolderData } from "../../../types/financials";
|
|
3
|
+
import {
|
|
4
|
+
beneficialReportRow,
|
|
5
|
+
buildBeneficialRows,
|
|
6
|
+
DEFAULT_BENEFICIAL_SORT,
|
|
7
|
+
formatClassPercent,
|
|
8
|
+
formatOwnerShares,
|
|
9
|
+
formatPointChange,
|
|
10
|
+
stakeMarker,
|
|
11
|
+
sortBeneficialRows,
|
|
12
|
+
type BeneficialReportRow,
|
|
13
|
+
type BeneficialSortPreference,
|
|
14
|
+
} from "./beneficial-model";
|
|
15
|
+
import { buildRows } from "./table-model";
|
|
16
|
+
|
|
17
|
+
/** What `holders --form` lists: the 13F table, or the 13D/13G beneficial owners. */
|
|
18
|
+
export type HolderForm = "13f" | "13d" | "13g" | "all";
|
|
19
|
+
export const HOLDER_FORMS: readonly HolderForm[] = ["13f", "13d", "13g", "all"];
|
|
20
|
+
|
|
21
|
+
export function parseHolderForm(value: unknown): HolderForm | null {
|
|
22
|
+
const form = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
23
|
+
return (HOLDER_FORMS as readonly string[]).includes(form) ? form as HolderForm : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function beneficialRouteForm(form: Exclude<HolderForm, "13f">): BeneficialOwnersForm {
|
|
27
|
+
return form === "13d" ? "13D" : form === "13g" ? "13G" : "all";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Text columns for the 13D/13G rows; CSV and JSON keep the raw values. */
|
|
31
|
+
export const BENEFICIAL_REPORT_COLUMNS = [
|
|
32
|
+
{ key: "filer", header: "Filer", maxWidth: 32 },
|
|
33
|
+
{ key: "form", header: "Form" },
|
|
34
|
+
{
|
|
35
|
+
key: "percentOfClass",
|
|
36
|
+
header: "% Class",
|
|
37
|
+
align: "right" as const,
|
|
38
|
+
format: (value: unknown, row: Record<string, unknown>) => {
|
|
39
|
+
const marker = stakeMarker(row.status === "below-threshold" || row.status === "exited" ? row.status : null);
|
|
40
|
+
if (typeof value !== "number") return marker || "-";
|
|
41
|
+
return marker ? `${formatClassPercent(value)} ${marker}` : formatClassPercent(value);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: "changePoints",
|
|
46
|
+
header: "Chg",
|
|
47
|
+
align: "right" as const,
|
|
48
|
+
format: (value: unknown) => formatPointChange(typeof value === "number" ? value : null),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: "shares",
|
|
52
|
+
header: "Shares",
|
|
53
|
+
align: "right" as const,
|
|
54
|
+
format: (value: unknown) => formatOwnerShares(typeof value === "number" ? value : null),
|
|
55
|
+
},
|
|
56
|
+
{ key: "eventDate", header: "Event", format: (value: unknown) => typeof value === "string" ? value : "-" },
|
|
57
|
+
{ key: "filingDate", header: "Filed" },
|
|
58
|
+
{ key: "thirteenF", header: "13F", align: "right" as const, format: (value: unknown) => typeof value === "string" ? value : "-" },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const filings = (count: number) => `${count} ${count === 1 ? "filing" : "filings"}`;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* What the list leaves out, a sentence each: reports that could not be read
|
|
65
|
+
* this time, and reports known only from the EDGAR index whose figures are
|
|
66
|
+
* blank.
|
|
67
|
+
*/
|
|
68
|
+
export function beneficialCoverageNotices(coverage: BeneficialOwnersCoverage | null | undefined): string[] {
|
|
69
|
+
if (!coverage) return [];
|
|
70
|
+
const notices: string[] = [];
|
|
71
|
+
if (coverage.unavailable) {
|
|
72
|
+
notices.push(`${coverage.unavailable} of ${filings(coverage.filings)} could not be read this time and are left out, so a filer's row may not be its latest report; a refresh retries them.`);
|
|
73
|
+
}
|
|
74
|
+
// Reports that could not be read count as unparsed too.
|
|
75
|
+
const indexOnly = Math.max(0, coverage.unparsed - (coverage.unavailable ?? 0));
|
|
76
|
+
if (indexOnly) {
|
|
77
|
+
notices.push(`Percent of class and shares are blank for ${filings(indexOnly)} known only from the EDGAR index.`);
|
|
78
|
+
}
|
|
79
|
+
return notices;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** What the list covers, for the line above it: `13D/13G filings since 2022-10-09`, `11 filers`. */
|
|
83
|
+
export function beneficialListFacts(
|
|
84
|
+
payload: Pick<BeneficialOwnersPayload, "coverage">,
|
|
85
|
+
form: Exclude<HolderForm, "13f">,
|
|
86
|
+
rows: number,
|
|
87
|
+
history: boolean,
|
|
88
|
+
): string[] {
|
|
89
|
+
const kind = form === "all" ? "13D/13G" : form.toUpperCase();
|
|
90
|
+
const since = payload.coverage?.from ? `${kind} filings since ${payload.coverage.from}` : `${kind} filings`;
|
|
91
|
+
const count = history ? `${rows} ${rows === 1 ? "report" : "reports"}` : `${rows} ${rows === 1 ? "filer" : "filers"}`;
|
|
92
|
+
return [since, count];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Every page loaded and every filing in the window read. */
|
|
96
|
+
export function beneficialListComplete(payload: Pick<BeneficialOwnersPayload, "hasMore" | "coverage">): boolean {
|
|
97
|
+
return !payload.hasMore && !payload.coverage?.unavailable && payload.coverage?.complete !== false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** No rows although filings are listed: they could not be read, which is not the same as none filed. */
|
|
101
|
+
export function beneficialListUnreadable(payload: Pick<BeneficialOwnersPayload, "owners" | "coverage">): boolean {
|
|
102
|
+
return payload.owners.length === 0 && (payload.coverage?.filings ?? 0) > 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The rows `--form 13d|13g|all` prints: the latest report per filer by
|
|
107
|
+
* percent of class, stakes under 5% and exits after the 5% holders, or with `history` every report
|
|
108
|
+
* newest first. The 13F action joins by name to the 13F holders when they
|
|
109
|
+
* loaded; a report without one shows none.
|
|
110
|
+
*/
|
|
111
|
+
export function buildBeneficialReportRows(
|
|
112
|
+
payload: BeneficialOwnersPayload,
|
|
113
|
+
{
|
|
114
|
+
history = false,
|
|
115
|
+
holders = null,
|
|
116
|
+
sort = DEFAULT_BENEFICIAL_SORT,
|
|
117
|
+
}: { history?: boolean; holders?: HolderData | null; sort?: BeneficialSortPreference } = {},
|
|
118
|
+
): BeneficialReportRow[] {
|
|
119
|
+
const holderRows = buildRows(holders);
|
|
120
|
+
if (history) {
|
|
121
|
+
const filings = [...(payload.filings ?? payload.owners)]
|
|
122
|
+
.sort((left, right) => right.filingDate.localeCompare(left.filingDate));
|
|
123
|
+
return buildBeneficialRows(filings, holderRows).map(beneficialReportRow);
|
|
124
|
+
}
|
|
125
|
+
return sortBeneficialRows(buildBeneficialRows(payload.owners, holderRows), sort).map(beneficialReportRow);
|
|
126
|
+
}
|