gloomberb 0.7.2 → 0.7.4
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 +79 -132
- package/package.json +1 -1
- package/src/app.tsx +73 -67
- package/src/components/chart/chart-data.ts +7 -2
- package/src/components/chart/chart-pane-settings.ts +7 -4
- package/src/components/chart/chart-renderer.ts +158 -47
- package/src/components/chart/chart-types.ts +20 -2
- package/src/components/chart/chart.test.ts +179 -13
- package/src/components/chart/comparison-chart-renderer.test.ts +14 -30
- package/src/components/chart/comparison-chart-renderer.ts +50 -11
- package/src/components/chart/comparison-stock-chart.tsx +129 -129
- package/src/components/chart/market-session.ts +187 -0
- package/src/components/chart/native/chart-rasterizer.ts +108 -19
- package/src/components/chart/price-axis-labels.tsx +25 -9
- package/src/components/chart/stock-chart-renderer-switch.test.tsx +97 -1
- package/src/components/chart/stock-chart.tsx +95 -49
- package/src/components/chart/time-axis-label.tsx +56 -2
- package/src/components/command-bar/command-bar.test.tsx +446 -120
- package/src/components/command-bar/command-bar.tsx +535 -384
- package/src/components/command-bar/command-registry.ts +16 -6
- package/src/components/command-bar/list-model.ts +8 -4
- package/src/components/command-bar/root-shortcuts.ts +4 -5
- package/src/components/command-bar/view-model.test.ts +21 -0
- package/src/components/command-bar/view-model.ts +17 -4
- package/src/components/command-bar/workflow-ops.ts +11 -32
- package/src/components/data-table-view.test.tsx +24 -1
- package/src/components/data-table-view.tsx +3 -2
- package/src/components/feed-data-table-stack-view.tsx +3 -2
- package/src/components/layout/detached-pane-shell.tsx +2 -2
- package/src/components/layout/floating-pane.tsx +9 -2
- package/src/components/layout/pane-footer.tsx +1 -1
- package/src/components/layout/pane-header.tsx +4 -2
- package/src/components/layout/pane-sizing.ts +12 -0
- package/src/components/layout/pane.tsx +24 -2
- package/src/components/layout/shell.tsx +24 -10
- package/src/components/layout/status-bar.test.tsx +4 -1
- package/src/components/layout/status-bar.tsx +4 -24
- package/src/components/markdown-text.tsx +53 -8
- package/src/components/onboarding/onboarding-wizard.tsx +7 -6
- package/src/components/pane-settings-dialog.tsx +9 -6
- package/src/components/pane-template-wizard.tsx +3 -2
- package/src/components/price-selector-dialog.tsx +3 -2
- package/src/components/price-sparkline-view.tsx +463 -0
- package/src/components/price-sparkline.ts +46 -0
- package/src/components/table-view-shared.tsx +21 -3
- package/src/components/ticker-list-table-view.tsx +3 -2
- package/src/components/ticker-list-table.tsx +15 -66
- package/src/components/toggle-list.tsx +3 -3
- package/src/components/ui/choice-dialog.tsx +3 -2
- package/src/components/ui/multi-select-dialog.tsx +3 -2
- package/src/components/ui/native-select.tsx +3 -3
- package/src/core/state/app-state.ts +210 -80
- package/src/core/state/session-persistence.ts +25 -0
- package/src/data/config-store-node.ts +113 -25
- package/src/data/config-store.test.ts +65 -3
- package/src/data/plugin-state-store.ts +39 -13
- package/src/data/sqlite-cache.test.ts +13 -0
- package/src/market-data/coordinator-subscriptions.test.ts +102 -18
- package/src/market-data/coordinator.test.ts +122 -2
- package/src/market-data/coordinator.ts +200 -56
- package/src/market-data/hooks.test.tsx +31 -0
- package/src/market-data/hooks.tsx +1 -0
- package/src/news/aggregator.test.ts +41 -0
- package/src/news/aggregator.ts +61 -9
- package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +25 -6
- package/src/plugins/builtin/ai/screener-pane.tsx +3 -0
- package/src/plugins/builtin/ai/settings.ts +3 -0
- package/src/plugins/builtin/broker-manager/index.tsx +4 -3
- package/src/plugins/builtin/chat-controller.test.ts +398 -17
- package/src/plugins/builtin/chat-controller.ts +263 -48
- package/src/plugins/builtin/chat.test.tsx +312 -6
- package/src/plugins/builtin/chat.tsx +245 -66
- package/src/plugins/builtin/comparison-chart.test.tsx +117 -3
- package/src/plugins/builtin/correlation/colors.test.ts +39 -0
- package/src/plugins/builtin/correlation/colors.ts +87 -0
- package/src/plugins/builtin/correlation/index.test.tsx +151 -0
- package/src/plugins/builtin/correlation/index.tsx +92 -21
- package/src/plugins/builtin/debug.tsx +4 -3
- package/src/plugins/builtin/econ/index.tsx +3 -2
- package/src/plugins/builtin/help.test.tsx +2 -2
- package/src/plugins/builtin/holders/index.tsx +25 -13
- package/src/plugins/builtin/layout-manager.tsx +1 -7
- package/src/plugins/builtin/market-movers/index.tsx +72 -40
- package/src/plugins/builtin/news-wire/breaking-pane.test.tsx +156 -0
- package/src/plugins/builtin/news-wire/breaking-pane.tsx +0 -90
- package/src/plugins/builtin/news-wire/index.tsx +1 -3
- package/src/plugins/builtin/news-wire/news-detail-view.tsx +3 -2
- package/src/plugins/builtin/news-wire/news-preset-pane.tsx +4 -1
- package/src/plugins/builtin/news-wire/persisted-articles.ts +7 -1
- package/src/plugins/builtin/options.tsx +9 -17
- package/src/plugins/builtin/portfolio-list/cli/commands.ts +6 -10
- package/src/plugins/builtin/portfolio-list/metrics.ts +13 -2
- package/src/plugins/builtin/portfolio-list/mutations.ts +17 -0
- package/src/plugins/builtin/portfolio-list/pane.tsx +139 -23
- package/src/plugins/builtin/portfolio-list/quick-add.tsx +422 -0
- package/src/plugins/builtin/portfolio-list/settings.ts +20 -12
- package/src/plugins/builtin/portfolio-list/table.tsx +3 -3
- package/src/plugins/builtin/portfolio-list.test.tsx +311 -9
- package/src/plugins/builtin/quote-monitor.test.tsx +158 -25
- package/src/plugins/builtin/sectors/index.tsx +275 -43
- package/src/plugins/builtin/sectors/sector-data.ts +41 -1
- package/src/plugins/builtin/ticker-detail/chart-tab.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/index.tsx +30 -9
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +25 -15
- package/src/plugins/builtin/ticker-detail/pane.tsx +18 -7
- package/src/plugins/builtin/ticker-detail/quote-monitor.tsx +445 -63
- package/src/plugins/builtin/ticker-detail/settings.ts +84 -3
- package/src/plugins/builtin/ticker-detail.test.tsx +2 -2
- package/src/plugins/builtin/world-indices/index.tsx +58 -19
- package/src/plugins/ibkr/trading-pane.tsx +3 -2
- package/src/plugins/plugin-runtime.tsx +2 -2
- package/src/plugins/prediction-markets/settings.ts +4 -0
- package/src/plugins/registry.test.ts +55 -0
- package/src/plugins/registry.ts +11 -4
- package/src/plugins/ticker-navigation.test.ts +35 -5
- package/src/plugins/ticker-navigation.ts +16 -22
- package/src/renderers/electrobun/bun/application-menu-click.test.ts +9 -0
- package/src/renderers/electrobun/bun/application-menu-click.ts +7 -4
- package/src/renderers/electrobun/bun/application-menu.ts +6 -1
- package/src/renderers/electrobun/bun/desktop-workspace.ts +47 -29
- package/src/renderers/electrobun/bun/index.ts +52 -13
- package/src/renderers/electrobun/view/app-services.ts +51 -9
- package/src/renderers/electrobun/view/backend-rpc.ts +5 -8
- package/src/renderers/electrobun/view/desktop-controls.tsx +4 -4
- package/src/renderers/electrobun/view/main.tsx +0 -16
- package/src/renderers/electrobun/view/styles.css +23 -21
- package/src/renderers/electrobun/view/ui-host.tsx +6 -4
- package/src/renderers/opentui/host.tsx +2 -1
- package/src/renderers/opentui/start.tsx +1 -1
- package/src/renderers/opentui/test-utils.tsx +6 -5
- package/src/sources/gloomberb-cloud.test.ts +55 -2
- package/src/sources/gloomberb-cloud.ts +180 -29
- package/src/sources/provider-router.test.ts +567 -10
- package/src/sources/provider-router.ts +323 -93
- package/src/sources/yahoo-finance.test.ts +37 -0
- package/src/sources/yahoo-finance.ts +48 -2
- package/src/state/app-bootstrap.test.ts +50 -23
- package/src/state/app-bootstrap.ts +29 -13
- package/src/state/app-context.test.ts +113 -0
- package/src/state/app-context.tsx +8 -4
- package/src/state/session-persistence.test.ts +5 -3
- package/src/state/use-inline-tickers.ts +3 -0
- package/src/state/use-quote-streaming.ts +11 -0
- package/src/theme/colors.ts +13 -14
- package/src/types/config.ts +9 -4
- package/src/types/data-provider.ts +5 -1
- package/src/types/financials.ts +1 -0
- package/src/types/plugin.ts +8 -1
- package/src/ui/context-menu.tsx +4 -4
- package/src/utils/api-client.test.ts +248 -0
- package/src/utils/api-client.ts +178 -26
- package/src/utils/exchanges.test.ts +16 -0
- package/src/utils/exchanges.ts +33 -0
- package/src/utils/fuzzy-search.ts +12 -1
- package/src/utils/keyboard.ts +31 -0
- package/src/utils/options.ts +1 -1
- package/src/utils/price-history.test.ts +28 -1
- package/src/utils/price-history.ts +16 -0
- package/src/utils/quote-freshness.test.ts +150 -0
- package/src/utils/quote-freshness.ts +42 -1
- package/src/utils/quote-resolution.ts +2 -0
- package/src/utils/quote-time.test.ts +34 -0
- package/src/utils/quote-time.ts +18 -5
- package/src/utils/ticker-search.test.ts +2 -2
- package/src/utils/ticker-search.ts +48 -1
- package/src/version.ts +1 -1
- package/src/plugins/builtin/news-wire/digest-store.ts +0 -44
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box, ScrollBox, Text } from "../../../ui";
|
|
1
|
+
import { Box, ScrollBox, Text, useUiCapabilities } from "../../../ui";
|
|
2
2
|
import { TextAttributes } from "../../../ui";
|
|
3
3
|
import { useViewport } from "../../../react/input";
|
|
4
4
|
import { useFxRatesMap } from "../../../market-data/hooks";
|
|
@@ -32,7 +32,6 @@ const STAT_COLUMN_GAP = 2;
|
|
|
32
32
|
const STAT_LABEL_WIDTH = 12;
|
|
33
33
|
const BOOK_LABEL_WIDTH = 4;
|
|
34
34
|
const RANGE_ENDPOINT_WIDTH = 11;
|
|
35
|
-
const RANGE_MAX_WIDTH = 42;
|
|
36
35
|
const POSITION_COLUMN_GAP = 1;
|
|
37
36
|
|
|
38
37
|
function CompactRangeBar({
|
|
@@ -71,21 +70,23 @@ function CompactRangeBar({
|
|
|
71
70
|
return (
|
|
72
71
|
<Box flexDirection="column" width={width} flexShrink={0}>
|
|
73
72
|
<Box flexDirection="row" height={1}>
|
|
74
|
-
<
|
|
73
|
+
<Box width={labelWidth} overflow="hidden">
|
|
74
|
+
<Text fg={colors.textDim}>{label}</Text>
|
|
75
|
+
</Box>
|
|
75
76
|
<Text fg={markerColor}>{pctLabel}</Text>
|
|
76
77
|
</Box>
|
|
77
78
|
<Box flexDirection="row" height={1}>
|
|
78
|
-
<
|
|
79
|
-
{
|
|
80
|
-
</
|
|
79
|
+
<Box width={endpointWidth} overflow="hidden">
|
|
80
|
+
<Text fg={colors.textDim}>{lowText}</Text>
|
|
81
|
+
</Box>
|
|
81
82
|
<Box marginLeft={1} marginRight={1} width={barWidth} flexDirection="row">
|
|
82
83
|
<Text fg={colors.border}>{"─".repeat(markerIndex)}</Text>
|
|
83
84
|
<Text fg={markerColor}>{"●"}</Text>
|
|
84
85
|
<Text fg={colors.border}>{"─".repeat(Math.max(0, barWidth - markerIndex - 1))}</Text>
|
|
85
86
|
</Box>
|
|
86
|
-
<
|
|
87
|
-
{
|
|
88
|
-
</
|
|
87
|
+
<Box flexDirection="row" width={endpointWidth} justifyContent="flex-end" overflow="hidden">
|
|
88
|
+
<Text fg={colors.textDim}>{highText}</Text>
|
|
89
|
+
</Box>
|
|
89
90
|
</Box>
|
|
90
91
|
</Box>
|
|
91
92
|
);
|
|
@@ -164,7 +165,10 @@ interface PositionColumn {
|
|
|
164
165
|
|
|
165
166
|
function StatGrid({ fields, width }: { fields: StatField[]; width: number }) {
|
|
166
167
|
const columnCount = width >= 58 ? 2 : 1;
|
|
167
|
-
const
|
|
168
|
+
const availableWidth = width - STAT_COLUMN_GAP * (columnCount - 1);
|
|
169
|
+
const baseColWidth = Math.floor(availableWidth / columnCount);
|
|
170
|
+
const extraWidth = availableWidth - baseColWidth * columnCount;
|
|
171
|
+
const colWidths = Array.from({ length: columnCount }, (_, index) => baseColWidth + (index === columnCount - 1 ? extraWidth : 0));
|
|
168
172
|
const rows: Array<Array<StatField | null>> = [];
|
|
169
173
|
for (let i = 0; i < fields.length; i += columnCount) {
|
|
170
174
|
rows.push(Array.from({ length: columnCount }, (_, offset) => fields[i + offset] ?? null));
|
|
@@ -175,6 +179,7 @@ function StatGrid({ fields, width }: { fields: StatField[]; width: number }) {
|
|
|
175
179
|
{rows.map((row, i) => (
|
|
176
180
|
<Box key={i} flexDirection="row" height={1}>
|
|
177
181
|
{row.map((field, j) => {
|
|
182
|
+
const colWidth = colWidths[j] ?? baseColWidth;
|
|
178
183
|
if (!field) {
|
|
179
184
|
return (
|
|
180
185
|
<Box key={j} flexDirection="row">
|
|
@@ -189,8 +194,12 @@ function StatGrid({ fields, width }: { fields: StatField[]; width: number }) {
|
|
|
189
194
|
<Box key={j} flexDirection="row">
|
|
190
195
|
{j > 0 && <Box width={STAT_COLUMN_GAP} />}
|
|
191
196
|
<Box width={colWidth} flexDirection="row">
|
|
192
|
-
<
|
|
193
|
-
|
|
197
|
+
<Box width={labelWidth} overflow="hidden">
|
|
198
|
+
<Text fg={colors.textDim}>{field.label}</Text>
|
|
199
|
+
</Box>
|
|
200
|
+
<Box flexDirection="row" width={valueWidth} justifyContent="flex-end" overflow="hidden">
|
|
201
|
+
<Text fg={field.valueColor ?? colors.text}>{field.value}</Text>
|
|
202
|
+
</Box>
|
|
194
203
|
</Box>
|
|
195
204
|
</Box>
|
|
196
205
|
);
|
|
@@ -300,6 +309,7 @@ export function OverviewTab({
|
|
|
300
309
|
const baseCurrency = useAppSelector((state) => state.config.baseCurrency);
|
|
301
310
|
const exchangeRatesState = useAppSelector((state) => state.exchangeRates);
|
|
302
311
|
const { width: termWidth } = useViewport();
|
|
312
|
+
const { fractionalViewport = false } = useUiCapabilities();
|
|
303
313
|
|
|
304
314
|
if (!ticker) return <EmptyState title="No ticker selected." />;
|
|
305
315
|
|
|
@@ -336,7 +346,7 @@ export function OverviewTab({
|
|
|
336
346
|
routingVenue && routingVenue !== listingVenue ? `route ${routingVenue}` : "",
|
|
337
347
|
].filter((part) => part.length > 0);
|
|
338
348
|
|
|
339
|
-
const contentWidth = Math.max((width || Math.floor(termWidth * 0.5)) - 4, 20);
|
|
349
|
+
const contentWidth = Math.max((width || Math.floor(termWidth * 0.5)) - (fractionalViewport ? 2 : 4), 20);
|
|
340
350
|
const chartWidth = contentWidth;
|
|
341
351
|
const hasHistory = (financials?.priceHistory?.length ?? 0) > 2;
|
|
342
352
|
const hasBidAsk = quote?.bid != null || quote?.ask != null;
|
|
@@ -347,8 +357,8 @@ export function OverviewTab({
|
|
|
347
357
|
const hasYearRange = quote?.low52w != null && quote?.high52w != null && quote.high52w > quote.low52w;
|
|
348
358
|
const rangeInline = contentWidth >= 70 && hasDayRange && hasYearRange;
|
|
349
359
|
const rangeWidth = rangeInline
|
|
350
|
-
? Math.
|
|
351
|
-
:
|
|
360
|
+
? Math.floor((contentWidth - 2) / 2)
|
|
361
|
+
: contentWidth;
|
|
352
362
|
const rangeMarkerColor = quote ? priceColor(quote.change) : colors.textDim;
|
|
353
363
|
|
|
354
364
|
const stats: StatField[] = [];
|
|
@@ -62,7 +62,24 @@ export function TickerDetailPane({ focused, width, height }: PaneProps) {
|
|
|
62
62
|
const paneInstance = usePaneInstance();
|
|
63
63
|
const { symbol, ticker, financials } = usePaneTicker();
|
|
64
64
|
const streamingTarget = quoteSubscriptionTargetFromTicker(ticker, ticker?.metadata.ticker, "provider");
|
|
65
|
-
const streamingTargets = useMemo(() => (
|
|
65
|
+
const streamingTargets = useMemo(() => (
|
|
66
|
+
streamingTarget
|
|
67
|
+
? [{
|
|
68
|
+
...streamingTarget,
|
|
69
|
+
surface: "detail" as const,
|
|
70
|
+
visible: true,
|
|
71
|
+
selected: true,
|
|
72
|
+
weight: 100,
|
|
73
|
+
}]
|
|
74
|
+
: []
|
|
75
|
+
), [
|
|
76
|
+
streamingTarget?.symbol,
|
|
77
|
+
streamingTarget?.exchange,
|
|
78
|
+
streamingTarget?.route,
|
|
79
|
+
streamingTarget?.context?.brokerId,
|
|
80
|
+
streamingTarget?.context?.brokerInstanceId,
|
|
81
|
+
streamingTarget?.context?.instrument,
|
|
82
|
+
]);
|
|
66
83
|
useQuoteStreaming(streamingTargets);
|
|
67
84
|
|
|
68
85
|
const { collectionId } = usePaneCollection();
|
|
@@ -154,12 +171,6 @@ export function TickerDetailPane({ focused, width, height }: PaneProps) {
|
|
|
154
171
|
});
|
|
155
172
|
}, [resolvedTabId, visibleTabIds]);
|
|
156
173
|
|
|
157
|
-
useEffect(() => {
|
|
158
|
-
if (resolvedTabId !== activeTabId) {
|
|
159
|
-
setActiveTabId(resolvedTabId);
|
|
160
|
-
}
|
|
161
|
-
}, [activeTabId, resolvedTabId, setActiveTabId]);
|
|
162
|
-
|
|
163
174
|
const handleKeyboard = useCallback((event: { name?: string }) => {
|
|
164
175
|
const currentState = stateRef.current;
|
|
165
176
|
if (!currentState.focused || currentState.pluginCaptured) return;
|