@luxalgo/vela 0.5.1 → 0.5.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/dist/{DataProvider-DGesjOJT.d.ts → DataProvider-DTOEXKTI.d.ts} +1 -1
- package/dist/{DataProvider-BBQ3Hr21.d.cts → DataProvider-gnzv-dgc.d.cts} +1 -1
- package/dist/{chunk-ULIX6AE2.js → chunk-ATPU5CI6.js} +1 -1
- package/dist/{chunk-S6F6SQ2L.js → chunk-B5TIKQJ5.js} +60 -7
- package/dist/{chunk-EP6NDJYK.js → chunk-LJLZR44Y.js} +4 -2
- package/dist/{chunk-AIW3EJUE.js → chunk-P556H6EA.js} +329 -10
- package/dist/{chunk-FNOMKHEZ.js → chunk-RRFGWZNJ.js} +1321 -363
- package/dist/{chunk-5SE4PL3H.js → chunk-Y7TK4ZWK.js} +1363 -48
- package/dist/{contributions-BlV3kb0O.d.cts → contributions-Ci_i3IN2.d.cts} +33 -2
- package/dist/{contributions-6N0rbrPC.d.ts → contributions-b6AVrqqG.d.ts} +33 -2
- package/dist/{history-DX3Zne3a.d.cts → history-Cf1lVsap.d.cts} +15 -3
- package/dist/{history-BTd52YMA.d.ts → history-Ci3M0xLV.d.ts} +15 -3
- package/dist/index.cjs +1374 -366
- package/dist/index.d.cts +52 -19
- package/dist/index.d.ts +52 -19
- package/dist/index.js +4 -4
- package/dist/{options-DbQholFV.d.cts → options-XTBpbx0s.d.cts} +47 -1
- package/dist/{options-DbQholFV.d.ts → options-XTBpbx0s.d.ts} +47 -1
- package/dist/{plugin-TN3n-9YN.d.ts → plugin-CnNd7cuF.d.ts} +172 -25
- package/dist/{plugin-O34MbXf-.d.cts → plugin-DfH4Y-Om.d.cts} +172 -25
- package/dist/plugin.cjs +53 -7
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/plugin.js +2 -2
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/ui.cjs +332 -9
- package/dist/ui.d.cts +64 -2
- package/dist/ui.d.ts +64 -2
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +1374 -366
- package/dist/vela.global.min.js +84 -34
- package/dist/widget.cjs +3348 -550
- package/dist/widget.d.cts +65 -7
- package/dist/widget.d.ts +65 -7
- package/dist/widget.js +169 -18
- package/dist/workspace.cjs +4251 -1400
- package/dist/workspace.d.cts +45 -9
- package/dist/workspace.d.ts +45 -9
- package/dist/workspace.js +226 -22
- package/package.json +1 -1
package/dist/workspace.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { O as OHLCV, V as VisibleRangePreset, a as VisibleRange, b as VelaOptions, c as VelaTheme, N as NativeBackend } from './options-
|
|
2
|
-
import { S as SyncSetting, V as VelaStorage, C as CellState, W as WidgetHistory, R as ResolvedIndicator, a as RangePreset, T as TrackSizes, b as VelaShellOptions, c as SyncOptions, d as SyncKind, e as WorkspaceState } from './history-
|
|
3
|
-
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-
|
|
1
|
+
import { O as OHLCV, V as VisibleRangePreset, a as VisibleRange, b as VelaOptions, c as VelaTheme, N as NativeBackend } from './options-XTBpbx0s.cjs';
|
|
2
|
+
import { S as SyncSetting, V as VelaStorage, C as CellState, W as WidgetHistory, R as ResolvedIndicator, a as RangePreset, T as TrackSizes, b as VelaShellOptions, c as SyncOptions, d as SyncKind, e as WorkspaceState } from './history-Cf1lVsap.cjs';
|
|
3
|
+
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-Cf1lVsap.cjs';
|
|
4
4
|
import { K as KeymapManager } from './keymap-CGOz5F5f.cjs';
|
|
5
|
-
import { I as IndicatorHandle, S as ScriptingEngine, W as WidgetContext, V as Vela, a as ScriptRun } from './contributions-
|
|
6
|
-
import { M as MarketDataFeed } from './DataProvider-
|
|
5
|
+
import { I as IndicatorHandle, S as ScriptingEngine, W as WidgetContext, V as Vela, a as ScriptRun } from './contributions-Ci_i3IN2.cjs';
|
|
6
|
+
import { M as MarketDataFeed } from './DataProvider-gnzv-dgc.cjs';
|
|
7
7
|
|
|
8
8
|
/** The cells that follow `originId` under `setting` — PURE (never includes the origin). */
|
|
9
9
|
declare function syncTargets(originId: string, setting: SyncSetting | undefined, cellIds: readonly string[]): string[];
|
|
@@ -146,12 +146,16 @@ declare class ChartCell {
|
|
|
146
146
|
private watermarkOn;
|
|
147
147
|
/** Indicator titles (this cell's in-chart legend rows) shown. */
|
|
148
148
|
private indicatorTitlesOn;
|
|
149
|
+
/** Plot values beside this cell's legend titles shown. */
|
|
150
|
+
private indicatorValuesOn;
|
|
149
151
|
private destroyed;
|
|
150
152
|
constructor(id: string, gridHost: HTMLElement, seed: CellBoot, deps: CellDeps);
|
|
151
153
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
152
154
|
setWatermarkVisible(visible: boolean): void;
|
|
153
155
|
/** Show/hide this cell's indicator titles — the in-chart legend rows (persisted per cell). */
|
|
154
156
|
setIndicatorTitlesVisible(visible: boolean): void;
|
|
157
|
+
/** Show/hide the plot values beside this cell's legend titles (persisted per cell). */
|
|
158
|
+
setIndicatorValuesVisible(visible: boolean): void;
|
|
155
159
|
/** The LIVE chart of this cell — never cache it across a layout change (the cell's
|
|
156
160
|
* identity is what endures; the chart dies with the cell). */
|
|
157
161
|
get chart(): Vela;
|
|
@@ -169,6 +173,9 @@ declare class ChartCell {
|
|
|
169
173
|
* colors and direction rule (candle bodies by close-vs-open, baseline by position
|
|
170
174
|
* against the live baseline price, …) instead of the fixed theme tokens. */
|
|
171
175
|
private syncStatuslineColors;
|
|
176
|
+
/** Multi-cell grids keep the status line on one row and hide what doesn't fit —
|
|
177
|
+
* the workspace flips this with the layout (see Statusline.setFitMode). */
|
|
178
|
+
setStatuslineFit(on: boolean): void;
|
|
172
179
|
/** The workspace shell keeps the app theme; the cell host's tokens re-derive from
|
|
173
180
|
* the LIVE plot surface (see {@link applyPlotOverlayTokens}). */
|
|
174
181
|
private syncPlotOverlayTokens;
|
|
@@ -411,6 +418,7 @@ declare class VelaWorkspace {
|
|
|
411
418
|
/** The side-panel column, shared by the whole grid. */
|
|
412
419
|
private readonly dock;
|
|
413
420
|
private readonly symbolPicker;
|
|
421
|
+
/** Null when the host disabled it (`indicatorPicker: false`). */
|
|
414
422
|
private readonly indicatorPicker;
|
|
415
423
|
private readonly tfQuick;
|
|
416
424
|
private shortcutsHelp;
|
|
@@ -453,6 +461,17 @@ declare class VelaWorkspace {
|
|
|
453
461
|
private openDialogs;
|
|
454
462
|
private alerts;
|
|
455
463
|
private alertsMenu;
|
|
464
|
+
/** Writes `data-layout` on the root and pushes mode flips into every cell's renderer. */
|
|
465
|
+
private layoutCtl;
|
|
466
|
+
private readonly mobileBar;
|
|
467
|
+
private readonly drawingPill;
|
|
468
|
+
private tfDrawer;
|
|
469
|
+
private drawingsDrawer;
|
|
470
|
+
private moreDrawer;
|
|
471
|
+
private timezoneDrawer;
|
|
472
|
+
private priceScaleDrawer;
|
|
473
|
+
/** Plot-local y of the last price-axis long-press (targets the pane under the finger). */
|
|
474
|
+
private priceScalePressY;
|
|
456
475
|
private readonly attachmentDisposers;
|
|
457
476
|
/** The single grid-wide attribution mark — re-inked on a live theme swap. */
|
|
458
477
|
private attributionMark;
|
|
@@ -551,10 +570,13 @@ declare class VelaWorkspace {
|
|
|
551
570
|
private applySyncSetting;
|
|
552
571
|
/**
|
|
553
572
|
* Mirror an origin cell's pointer time onto its same-group followers as GHOST
|
|
554
|
-
* crosshairs (`renderer.setExternalCrosshair`).
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
573
|
+
* crosshairs (`renderer.setExternalCrosshair`). The horizontal price level rides
|
|
574
|
+
* along ONLY to followers showing the same ticker — price scales are comparable
|
|
575
|
+
* there, while an origin's price painted on another market's pane would be noise.
|
|
576
|
+
* Leaving the origin propagates `null` (the event already carries it) and clears
|
|
577
|
+
* every ghost. No busy guard needed: an external crosshair never re-emits
|
|
578
|
+
* `onCrosshairMove` — the flow is one-way by port contract, so no echo loop can
|
|
579
|
+
* exist.
|
|
558
580
|
*/
|
|
559
581
|
private propagateCrosshair;
|
|
560
582
|
/**
|
|
@@ -599,6 +621,20 @@ declare class VelaWorkspace {
|
|
|
599
621
|
private onCellIndicatorsChanged;
|
|
600
622
|
/** Timeframe changes routed from the topbar menu / quick entry (chip state follows). */
|
|
601
623
|
private setActiveTimeframe;
|
|
624
|
+
/** The mode flipped (container resized across the breakpoint, or a coarse-pointer
|
|
625
|
+
* change). Close the open surfaces — a desktop card must not linger over the
|
|
626
|
+
* mobile chrome (and vice versa) — and re-present every cell's own chrome. */
|
|
627
|
+
private onLayoutModeChange;
|
|
628
|
+
/** Push the layout-shape-dependent chrome onto every cell: multi-cell grids keep
|
|
629
|
+
* the status line on one row (segments that don't fit hide), and on MOBILE their
|
|
630
|
+
* legends' fold chip routes to the object tree instead of unfolding in place —
|
|
631
|
+
* per-indicator controls live there (the legend rows have no room in a grid cell). */
|
|
632
|
+
private syncCellPresentation;
|
|
633
|
+
private openTimeframeDrawer;
|
|
634
|
+
private openDrawingsDrawer;
|
|
635
|
+
private openMoreDrawer;
|
|
636
|
+
private openTimezoneDrawer;
|
|
637
|
+
private openPriceScaleDrawer;
|
|
602
638
|
/** The aggregated alerts bell — entries carry their cell; selecting one activates it. */
|
|
603
639
|
private openAlertsMenu;
|
|
604
640
|
/** Mount registered attachments not yet mounted on this workspace (idempotent per id). */
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { O as OHLCV, V as VisibleRangePreset, a as VisibleRange, b as VelaOptions, c as VelaTheme, N as NativeBackend } from './options-
|
|
2
|
-
import { S as SyncSetting, V as VelaStorage, C as CellState, W as WidgetHistory, R as ResolvedIndicator, a as RangePreset, T as TrackSizes, b as VelaShellOptions, c as SyncOptions, d as SyncKind, e as WorkspaceState } from './history-
|
|
3
|
-
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-
|
|
1
|
+
import { O as OHLCV, V as VisibleRangePreset, a as VisibleRange, b as VelaOptions, c as VelaTheme, N as NativeBackend } from './options-XTBpbx0s.js';
|
|
2
|
+
import { S as SyncSetting, V as VelaStorage, C as CellState, W as WidgetHistory, R as ResolvedIndicator, a as RangePreset, T as TrackSizes, b as VelaShellOptions, c as SyncOptions, d as SyncKind, e as WorkspaceState } from './history-Ci3M0xLV.js';
|
|
3
|
+
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-Ci3M0xLV.js';
|
|
4
4
|
import { K as KeymapManager } from './keymap-CGOz5F5f.js';
|
|
5
|
-
import { I as IndicatorHandle, S as ScriptingEngine, W as WidgetContext, V as Vela, a as ScriptRun } from './contributions-
|
|
6
|
-
import { M as MarketDataFeed } from './DataProvider-
|
|
5
|
+
import { I as IndicatorHandle, S as ScriptingEngine, W as WidgetContext, V as Vela, a as ScriptRun } from './contributions-b6AVrqqG.js';
|
|
6
|
+
import { M as MarketDataFeed } from './DataProvider-DTOEXKTI.js';
|
|
7
7
|
|
|
8
8
|
/** The cells that follow `originId` under `setting` — PURE (never includes the origin). */
|
|
9
9
|
declare function syncTargets(originId: string, setting: SyncSetting | undefined, cellIds: readonly string[]): string[];
|
|
@@ -146,12 +146,16 @@ declare class ChartCell {
|
|
|
146
146
|
private watermarkOn;
|
|
147
147
|
/** Indicator titles (this cell's in-chart legend rows) shown. */
|
|
148
148
|
private indicatorTitlesOn;
|
|
149
|
+
/** Plot values beside this cell's legend titles shown. */
|
|
150
|
+
private indicatorValuesOn;
|
|
149
151
|
private destroyed;
|
|
150
152
|
constructor(id: string, gridHost: HTMLElement, seed: CellBoot, deps: CellDeps);
|
|
151
153
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
152
154
|
setWatermarkVisible(visible: boolean): void;
|
|
153
155
|
/** Show/hide this cell's indicator titles — the in-chart legend rows (persisted per cell). */
|
|
154
156
|
setIndicatorTitlesVisible(visible: boolean): void;
|
|
157
|
+
/** Show/hide the plot values beside this cell's legend titles (persisted per cell). */
|
|
158
|
+
setIndicatorValuesVisible(visible: boolean): void;
|
|
155
159
|
/** The LIVE chart of this cell — never cache it across a layout change (the cell's
|
|
156
160
|
* identity is what endures; the chart dies with the cell). */
|
|
157
161
|
get chart(): Vela;
|
|
@@ -169,6 +173,9 @@ declare class ChartCell {
|
|
|
169
173
|
* colors and direction rule (candle bodies by close-vs-open, baseline by position
|
|
170
174
|
* against the live baseline price, …) instead of the fixed theme tokens. */
|
|
171
175
|
private syncStatuslineColors;
|
|
176
|
+
/** Multi-cell grids keep the status line on one row and hide what doesn't fit —
|
|
177
|
+
* the workspace flips this with the layout (see Statusline.setFitMode). */
|
|
178
|
+
setStatuslineFit(on: boolean): void;
|
|
172
179
|
/** The workspace shell keeps the app theme; the cell host's tokens re-derive from
|
|
173
180
|
* the LIVE plot surface (see {@link applyPlotOverlayTokens}). */
|
|
174
181
|
private syncPlotOverlayTokens;
|
|
@@ -411,6 +418,7 @@ declare class VelaWorkspace {
|
|
|
411
418
|
/** The side-panel column, shared by the whole grid. */
|
|
412
419
|
private readonly dock;
|
|
413
420
|
private readonly symbolPicker;
|
|
421
|
+
/** Null when the host disabled it (`indicatorPicker: false`). */
|
|
414
422
|
private readonly indicatorPicker;
|
|
415
423
|
private readonly tfQuick;
|
|
416
424
|
private shortcutsHelp;
|
|
@@ -453,6 +461,17 @@ declare class VelaWorkspace {
|
|
|
453
461
|
private openDialogs;
|
|
454
462
|
private alerts;
|
|
455
463
|
private alertsMenu;
|
|
464
|
+
/** Writes `data-layout` on the root and pushes mode flips into every cell's renderer. */
|
|
465
|
+
private layoutCtl;
|
|
466
|
+
private readonly mobileBar;
|
|
467
|
+
private readonly drawingPill;
|
|
468
|
+
private tfDrawer;
|
|
469
|
+
private drawingsDrawer;
|
|
470
|
+
private moreDrawer;
|
|
471
|
+
private timezoneDrawer;
|
|
472
|
+
private priceScaleDrawer;
|
|
473
|
+
/** Plot-local y of the last price-axis long-press (targets the pane under the finger). */
|
|
474
|
+
private priceScalePressY;
|
|
456
475
|
private readonly attachmentDisposers;
|
|
457
476
|
/** The single grid-wide attribution mark — re-inked on a live theme swap. */
|
|
458
477
|
private attributionMark;
|
|
@@ -551,10 +570,13 @@ declare class VelaWorkspace {
|
|
|
551
570
|
private applySyncSetting;
|
|
552
571
|
/**
|
|
553
572
|
* Mirror an origin cell's pointer time onto its same-group followers as GHOST
|
|
554
|
-
* crosshairs (`renderer.setExternalCrosshair`).
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
573
|
+
* crosshairs (`renderer.setExternalCrosshair`). The horizontal price level rides
|
|
574
|
+
* along ONLY to followers showing the same ticker — price scales are comparable
|
|
575
|
+
* there, while an origin's price painted on another market's pane would be noise.
|
|
576
|
+
* Leaving the origin propagates `null` (the event already carries it) and clears
|
|
577
|
+
* every ghost. No busy guard needed: an external crosshair never re-emits
|
|
578
|
+
* `onCrosshairMove` — the flow is one-way by port contract, so no echo loop can
|
|
579
|
+
* exist.
|
|
558
580
|
*/
|
|
559
581
|
private propagateCrosshair;
|
|
560
582
|
/**
|
|
@@ -599,6 +621,20 @@ declare class VelaWorkspace {
|
|
|
599
621
|
private onCellIndicatorsChanged;
|
|
600
622
|
/** Timeframe changes routed from the topbar menu / quick entry (chip state follows). */
|
|
601
623
|
private setActiveTimeframe;
|
|
624
|
+
/** The mode flipped (container resized across the breakpoint, or a coarse-pointer
|
|
625
|
+
* change). Close the open surfaces — a desktop card must not linger over the
|
|
626
|
+
* mobile chrome (and vice versa) — and re-present every cell's own chrome. */
|
|
627
|
+
private onLayoutModeChange;
|
|
628
|
+
/** Push the layout-shape-dependent chrome onto every cell: multi-cell grids keep
|
|
629
|
+
* the status line on one row (segments that don't fit hide), and on MOBILE their
|
|
630
|
+
* legends' fold chip routes to the object tree instead of unfolding in place —
|
|
631
|
+
* per-indicator controls live there (the legend rows have no room in a grid cell). */
|
|
632
|
+
private syncCellPresentation;
|
|
633
|
+
private openTimeframeDrawer;
|
|
634
|
+
private openDrawingsDrawer;
|
|
635
|
+
private openMoreDrawer;
|
|
636
|
+
private openTimezoneDrawer;
|
|
637
|
+
private openPriceScaleDrawer;
|
|
602
638
|
/** The aggregated alerts bell — entries carry their cell; selecting one activates it. */
|
|
603
639
|
private openAlertsMenu;
|
|
604
640
|
/** Mount registered attachments not yet mounted on this workspace (idempotent per id). */
|
package/dist/workspace.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { WidgetHistory, prefixedSymbol, Watermark, Statusline, ChartContextMenu, statuslineInkOf, indicatorLedger, Glider, localStorageAdapter, decodeState, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, Toast, Bottombar, toolShortcutHints, resolveIndicators, sanitizeState, encodeState, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp } from './chunk-
|
|
2
|
-
export { decodeState, encodeState, sanitizeState } from './chunk-
|
|
3
|
-
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-
|
|
4
|
-
import { resolveEngines, legendActionsProviderFor, rendererDefaults, widgetAttachments } from './chunk-
|
|
5
|
-
import { applyPlotOverlayTokens, ensureUIHost, KeymapManager, Menu, isEditableTarget } from './chunk-
|
|
6
|
-
import './chunk-
|
|
7
|
-
import { registerIcon, svg16, injectStyles } from './chunk-
|
|
1
|
+
import { WidgetHistory, prefixedSymbol, Watermark, Statusline, ChartContextMenu, statuslineInkOf, indicatorLedger, Glider, localStorageAdapter, decodeState, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, Toast, Bottombar, MobileBar, DrawingPill, LayoutModeController, toolShortcutHints, resolveIndicators, sanitizeState, encodeState, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp } from './chunk-Y7TK4ZWK.js';
|
|
2
|
+
export { decodeState, encodeState, sanitizeState } from './chunk-Y7TK4ZWK.js';
|
|
3
|
+
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs, priceStyleIds } from './chunk-RRFGWZNJ.js';
|
|
4
|
+
import { resolveEngines, legendActionsProviderFor, rendererDefaults, widgetActions, widgetAttachments } from './chunk-B5TIKQJ5.js';
|
|
5
|
+
import { applyPlotOverlayTokens, ensureUIHost, KeymapManager, Menu, isEditableTarget } from './chunk-P556H6EA.js';
|
|
6
|
+
import './chunk-ATPU5CI6.js';
|
|
7
|
+
import { registerIcon, svg16, injectStyles } from './chunk-LJLZR44Y.js';
|
|
8
8
|
|
|
9
9
|
// src/workspace/sync.ts
|
|
10
10
|
function syncTargets(originId, setting, cellIds) {
|
|
@@ -81,6 +81,8 @@ var ChartCell = class {
|
|
|
81
81
|
this.pendingRange = null;
|
|
82
82
|
/** Indicator titles (this cell's in-chart legend rows) shown. */
|
|
83
83
|
this.indicatorTitlesOn = true;
|
|
84
|
+
/** Plot values beside this cell's legend titles shown. */
|
|
85
|
+
this.indicatorValuesOn = true;
|
|
84
86
|
this.destroyed = false;
|
|
85
87
|
this.appTheme = deps.theme;
|
|
86
88
|
const symbol = prefixedSymbol(seed);
|
|
@@ -145,10 +147,14 @@ var ChartCell = class {
|
|
|
145
147
|
this.inner.on("load:end", () => {
|
|
146
148
|
this.volumeMayBePending = false;
|
|
147
149
|
});
|
|
150
|
+
this.inner.on("load:start", () => this.watermark?.setLoading(true));
|
|
151
|
+
this.inner.on("load:end", () => this.watermark?.setLoading(false));
|
|
148
152
|
const tz = deps.timezone();
|
|
149
153
|
if (tz !== "Etc/UTC") this.inner.renderer.set("timezone", tz);
|
|
150
154
|
this.indicatorTitlesOn = seed.indicatorTitles ?? true;
|
|
151
155
|
if (!this.indicatorTitlesOn) this.inner.renderer.set("indicatorTitles", false);
|
|
156
|
+
this.indicatorValuesOn = seed.indicatorValues ?? true;
|
|
157
|
+
if (!this.indicatorValuesOn) this.inner.renderer.set("indicatorValues", false);
|
|
152
158
|
this.watermarkOn = seed.watermark ?? deps.watermark;
|
|
153
159
|
this.watermark = deps.watermark ? new Watermark(this.host, symbol ?? "", seed.timeframe ?? "60") : null;
|
|
154
160
|
if (!this.watermarkOn) this.watermark?.setVisible(false);
|
|
@@ -256,6 +262,12 @@ var ChartCell = class {
|
|
|
256
262
|
label: "Titles",
|
|
257
263
|
get: () => this.indicatorTitlesOn,
|
|
258
264
|
set: (v) => this.setIndicatorTitlesVisible(v)
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
kind: "toggle",
|
|
268
|
+
label: "Values",
|
|
269
|
+
get: () => this.indicatorValuesOn,
|
|
270
|
+
set: (v) => this.setIndicatorValuesVisible(v)
|
|
259
271
|
}
|
|
260
272
|
]
|
|
261
273
|
},
|
|
@@ -289,6 +301,12 @@ var ChartCell = class {
|
|
|
289
301
|
this.inner?.renderer.set("indicatorTitles", visible);
|
|
290
302
|
this.deps.onStateDirty();
|
|
291
303
|
}
|
|
304
|
+
/** Show/hide the plot values beside this cell's legend titles (persisted per cell). */
|
|
305
|
+
setIndicatorValuesVisible(visible) {
|
|
306
|
+
this.indicatorValuesOn = visible;
|
|
307
|
+
this.inner?.renderer.set("indicatorValues", visible);
|
|
308
|
+
this.deps.onStateDirty();
|
|
309
|
+
}
|
|
292
310
|
/** The LIVE chart of this cell — never cache it across a layout change (the cell's
|
|
293
311
|
* identity is what endures; the chart dies with the cell). */
|
|
294
312
|
get chart() {
|
|
@@ -333,6 +351,11 @@ var ChartCell = class {
|
|
|
333
351
|
if (!this.statusline || !this.inner) return;
|
|
334
352
|
this.statusline.setDirectionColors(...statuslineInkOf(this.inner.renderer, this.priceStyle));
|
|
335
353
|
}
|
|
354
|
+
/** Multi-cell grids keep the status line on one row and hide what doesn't fit —
|
|
355
|
+
* the workspace flips this with the layout (see Statusline.setFitMode). */
|
|
356
|
+
setStatuslineFit(on) {
|
|
357
|
+
this.statusline?.setFitMode(on);
|
|
358
|
+
}
|
|
336
359
|
/** The workspace shell keeps the app theme; the cell host's tokens re-derive from
|
|
337
360
|
* the LIVE plot surface (see {@link applyPlotOverlayTokens}). */
|
|
338
361
|
syncPlotOverlayTokens() {
|
|
@@ -521,6 +544,7 @@ var ChartCell = class {
|
|
|
521
544
|
priceStyle: this.priceStyle,
|
|
522
545
|
watermark: this.watermarkOn,
|
|
523
546
|
indicatorTitles: this.indicatorTitlesOn,
|
|
547
|
+
indicatorValues: this.indicatorValuesOn,
|
|
524
548
|
rendererConfig: this.inner?.renderer.getConfig() ?? void 0,
|
|
525
549
|
drawings: this.inner ? this.inner.drawings.toJSON() : void 0,
|
|
526
550
|
// Natives from the chart's SYNC registry read — an async catalog mirror here
|
|
@@ -850,6 +874,9 @@ var CSS = `
|
|
|
850
874
|
.vela-ws-splitter:hover::after { content: ''; position: absolute; background: var(--vela-separator-hover-line); }
|
|
851
875
|
.vela-ws-splitter[data-axis='cols']:hover::after { left: calc(50% - 1px); top: 0; width: 2px; height: 100%; }
|
|
852
876
|
.vela-ws-splitter[data-axis='rows']:hover::after { top: calc(50% - 1px); left: 0; height: 2px; width: 100%; }
|
|
877
|
+
/* Mobile: the docked drawing-toolbar column would eat a phone-width grid \u2014 the shell's
|
|
878
|
+
drawings drawer + on-chart pill replace it (same policy as the widget's in-chart bar). */
|
|
879
|
+
[data-layout='mobile'] .vela-ws-toolbar { display: none; }
|
|
853
880
|
`;
|
|
854
881
|
registerIcon("layout", svg16('<rect x="1.5" y="1.5" width="13" height="13" rx="1.5"/><path d="M8 1.5v13M1.5 8h13"/>'));
|
|
855
882
|
function declaredOrder(cells) {
|
|
@@ -916,6 +943,13 @@ var VelaWorkspace = class {
|
|
|
916
943
|
this.openDialogs = 0;
|
|
917
944
|
this.alerts = [];
|
|
918
945
|
this.alertsMenu = null;
|
|
946
|
+
this.tfDrawer = null;
|
|
947
|
+
this.drawingsDrawer = null;
|
|
948
|
+
this.moreDrawer = null;
|
|
949
|
+
this.timezoneDrawer = null;
|
|
950
|
+
this.priceScaleDrawer = null;
|
|
951
|
+
/** Plot-local y of the last price-axis long-press (targets the pane under the finger). */
|
|
952
|
+
this.priceScalePressY = 0;
|
|
919
953
|
this.attachmentDisposers = /* @__PURE__ */ new Map();
|
|
920
954
|
/** The single grid-wide attribution mark — re-inked on a live theme swap. */
|
|
921
955
|
this.attributionMark = null;
|
|
@@ -976,14 +1010,18 @@ var VelaWorkspace = class {
|
|
|
976
1010
|
}
|
|
977
1011
|
});
|
|
978
1012
|
this.symbolPicker.setSource(() => this.feed.symbols());
|
|
979
|
-
this.indicatorPicker = new IndicatorPicker({
|
|
1013
|
+
this.indicatorPicker = opts.indicatorPicker !== false ? new IndicatorPicker({
|
|
980
1014
|
host: this.root,
|
|
981
1015
|
library: () => this.active.libraryRows(),
|
|
982
1016
|
onChart: () => this.active.onChartRows(),
|
|
983
1017
|
onAdd: (i) => this.active.addFromLibrary(i),
|
|
984
1018
|
onRemove: (i) => this.active.removeFromChart(i),
|
|
985
|
-
onOpenChange: (open) =>
|
|
986
|
-
|
|
1019
|
+
onOpenChange: (open) => {
|
|
1020
|
+
if (open) for (const cell of this.cells()) cell.chart.renderer.closeDialogs();
|
|
1021
|
+
this.trackDialog(open);
|
|
1022
|
+
}
|
|
1023
|
+
}) : null;
|
|
1024
|
+
const picker = this.indicatorPicker;
|
|
987
1025
|
this.tfQuick = new TimeframeQuick({
|
|
988
1026
|
host: this.root,
|
|
989
1027
|
onApply: (tf) => this.setActiveTimeframe(tf),
|
|
@@ -992,7 +1030,7 @@ var VelaWorkspace = class {
|
|
|
992
1030
|
this.topbar = new Topbar(this.root, {
|
|
993
1031
|
symbol: "",
|
|
994
1032
|
onSymbolClick: () => this.symbolPicker.open(),
|
|
995
|
-
onIndicatorsClick: () =>
|
|
1033
|
+
...picker ? { onIndicatorsClick: () => picker.open() } : {},
|
|
996
1034
|
onUndoClick: () => this.active.history.undo(),
|
|
997
1035
|
onRedoClick: () => this.active.history.redo(),
|
|
998
1036
|
onScreenshotClick: () => this.active.downloadScreenshot(),
|
|
@@ -1105,7 +1143,21 @@ var VelaWorkspace = class {
|
|
|
1105
1143
|
onTimezone: (zone) => this.setTimezone(zone),
|
|
1106
1144
|
onSettingsClick: () => this.active.chart.renderer.openSettings()
|
|
1107
1145
|
}) : null;
|
|
1146
|
+
this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
|
|
1147
|
+
symbol: "",
|
|
1148
|
+
timeframe: "60",
|
|
1149
|
+
onSymbolClick: () => this.symbolPicker.open(),
|
|
1150
|
+
onTimeframeClick: () => this.openTimeframeDrawer(),
|
|
1151
|
+
...picker ? { onIndicatorsClick: () => picker.open() } : {},
|
|
1152
|
+
getContext: () => this.context(),
|
|
1153
|
+
onDrawingsClick: () => this.openDrawingsDrawer(),
|
|
1154
|
+
onMoreClick: () => this.openMoreDrawer(),
|
|
1155
|
+
onSettingsClick: () => this.active.chart.renderer.openSettings()
|
|
1156
|
+
}) : null;
|
|
1157
|
+
this.drawingPill = new DrawingPill(this.gridEl);
|
|
1108
1158
|
hostEl.appendChild(this.root);
|
|
1159
|
+
this.layoutCtl = new LayoutModeController(this.root, opts.layoutMode ?? "auto");
|
|
1160
|
+
this.layoutCtl.onChange((mode) => this.onLayoutModeChange(mode));
|
|
1109
1161
|
this.splitters = new SplitterLayer(this.gridEl, {
|
|
1110
1162
|
tracks: () => this.currentTracks(),
|
|
1111
1163
|
grid: () => occupancyGrid(this.def),
|
|
@@ -1126,6 +1178,7 @@ var VelaWorkspace = class {
|
|
|
1126
1178
|
this.cellBackend = this.backendFor(this.def);
|
|
1127
1179
|
this.applyGrid();
|
|
1128
1180
|
this.buildCells();
|
|
1181
|
+
this.syncCellPresentation();
|
|
1129
1182
|
this.setActiveCell(bootActive != null && this.cellsById.has(bootActive) ? bootActive : this.order[0] ?? null);
|
|
1130
1183
|
if (opts.autofocus) this.refocusActive();
|
|
1131
1184
|
if (opts.indicators !== void 0) {
|
|
@@ -1208,6 +1261,7 @@ var VelaWorkspace = class {
|
|
|
1208
1261
|
refreshActions() {
|
|
1209
1262
|
this.mountAttachments();
|
|
1210
1263
|
this.topbar.renderActions();
|
|
1264
|
+
this.mobileBar?.renderActions();
|
|
1211
1265
|
this.dock.refresh();
|
|
1212
1266
|
for (const cell of this.cells()) cell.chart.renderer.setLegendActions(legendActionsProviderFor(cell.chart, () => this.context()));
|
|
1213
1267
|
}
|
|
@@ -1273,6 +1327,7 @@ var VelaWorkspace = class {
|
|
|
1273
1327
|
this.cellBackend = this.backendFor(this.def);
|
|
1274
1328
|
this.applyGrid();
|
|
1275
1329
|
this.buildCells();
|
|
1330
|
+
this.syncCellPresentation();
|
|
1276
1331
|
this.topbar.setLayout(this.def.id);
|
|
1277
1332
|
const nextActive = st.activeCellId && this.cellsById.has(st.activeCellId) ? st.activeCellId : this.order[0] ?? null;
|
|
1278
1333
|
if (nextActive === this.activeId) this.projectActiveCell();
|
|
@@ -1333,6 +1388,7 @@ var VelaWorkspace = class {
|
|
|
1333
1388
|
this.cellBackend = nextBackend;
|
|
1334
1389
|
this.applyGrid();
|
|
1335
1390
|
this.buildCells();
|
|
1391
|
+
this.syncCellPresentation();
|
|
1336
1392
|
this.topbar.setLayout(next.id);
|
|
1337
1393
|
const nextActive = activeAfterLayout(this.activeId, this.order.slice(0, next.cells.length));
|
|
1338
1394
|
if (nextActive === this.activeId) this.projectActiveCell();
|
|
@@ -1368,11 +1424,19 @@ var VelaWorkspace = class {
|
|
|
1368
1424
|
this.drawToolbar?.destroy();
|
|
1369
1425
|
this.topbar.destroy();
|
|
1370
1426
|
this.bottombar?.destroy();
|
|
1427
|
+
this.mobileBar?.destroy();
|
|
1428
|
+
this.drawingPill.destroy();
|
|
1429
|
+
this.tfDrawer?.destroy();
|
|
1430
|
+
this.drawingsDrawer?.destroy();
|
|
1431
|
+
this.moreDrawer?.destroy();
|
|
1432
|
+
this.timezoneDrawer?.destroy();
|
|
1433
|
+
this.priceScaleDrawer?.destroy();
|
|
1434
|
+
this.layoutCtl.destroy();
|
|
1371
1435
|
this.dock.destroy();
|
|
1372
1436
|
this.objectTree.destroy();
|
|
1373
1437
|
this.dataWindow.destroy();
|
|
1374
1438
|
this.symbolPicker.destroy();
|
|
1375
|
-
this.indicatorPicker
|
|
1439
|
+
this.indicatorPicker?.destroy();
|
|
1376
1440
|
this.tfQuick.destroy();
|
|
1377
1441
|
this.shortcutsHelp?.destroy();
|
|
1378
1442
|
this.toast.destroy();
|
|
@@ -1393,6 +1457,10 @@ var VelaWorkspace = class {
|
|
|
1393
1457
|
this.topbar.setPriceStyle(cell.priceStyle);
|
|
1394
1458
|
this.topbar.setIndicatorCount(cell.indicatorCount);
|
|
1395
1459
|
this.topbar.renderActions();
|
|
1460
|
+
this.mobileBar?.renderActions();
|
|
1461
|
+
this.mobileBar?.setSymbol(cell.symbol);
|
|
1462
|
+
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
1463
|
+
this.drawingPill.onChart(cell.chart);
|
|
1396
1464
|
const pushHistory = () => this.topbar.setHistoryState(cell.history.canUndo, cell.history.canRedo);
|
|
1397
1465
|
this.historyUnsub?.();
|
|
1398
1466
|
this.historyUnsub = cell.history.onChange(pushHistory);
|
|
@@ -1400,7 +1468,7 @@ var VelaWorkspace = class {
|
|
|
1400
1468
|
this.objectTree.setSymbol(cell.symbol);
|
|
1401
1469
|
this.dock.onChart(cell.chart);
|
|
1402
1470
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
1403
|
-
this.indicatorPicker
|
|
1471
|
+
this.indicatorPicker?.sync();
|
|
1404
1472
|
this.glider.stop();
|
|
1405
1473
|
const d = cell.chart.drawings;
|
|
1406
1474
|
if (d.getTool() !== this.globalTool) d.setTool(this.globalTool);
|
|
@@ -1522,6 +1590,7 @@ var VelaWorkspace = class {
|
|
|
1522
1590
|
this.cellsById.set(id, cell);
|
|
1523
1591
|
if (id === this.activeId) cell.host.dataset.active = "1";
|
|
1524
1592
|
this.wireCell(cell);
|
|
1593
|
+
cell.chart.renderer.setLayoutMode(this.layoutCtl.current);
|
|
1525
1594
|
if (this.favs.length > 0) cell.chart.drawings.setFavorites(this.favs);
|
|
1526
1595
|
cell.setManifest(this.manifest, pooled?.indicators == null);
|
|
1527
1596
|
this.events.emit("cell:created", { id });
|
|
@@ -1551,7 +1620,7 @@ var VelaWorkspace = class {
|
|
|
1551
1620
|
this.drawToolbar?.setFavorites(favorites);
|
|
1552
1621
|
this.markStateDirty();
|
|
1553
1622
|
});
|
|
1554
|
-
chart.renderer.onCrosshairMove((e) => this.propagateCrosshair(cell.id, e.time));
|
|
1623
|
+
chart.renderer.onCrosshairMove((e) => this.propagateCrosshair(cell.id, e.time, e.paneKind === "price" ? e.price : null));
|
|
1555
1624
|
chart.on("drawing:created", ({ id }) => {
|
|
1556
1625
|
this.propagateDrawing(cell.id, id);
|
|
1557
1626
|
this.markStateDirty();
|
|
@@ -1587,6 +1656,11 @@ var VelaWorkspace = class {
|
|
|
1587
1656
|
});
|
|
1588
1657
|
chart.on("viewport:changed", (range) => this.propagateViewport(cell.id, range));
|
|
1589
1658
|
chart.on("theme:changed", (t) => this.setTheme(t));
|
|
1659
|
+
chart.renderer.onAxisLongPress((e) => {
|
|
1660
|
+
if (this.layoutCtl.current !== "mobile") return;
|
|
1661
|
+
if (e.axis === "time") this.openTimezoneDrawer();
|
|
1662
|
+
else this.openPriceScaleDrawer(e.y);
|
|
1663
|
+
});
|
|
1590
1664
|
}
|
|
1591
1665
|
// ── sync links ──────────────────────────────────────────────
|
|
1592
1666
|
applySyncSetting(kind, setting, align = false) {
|
|
@@ -1620,17 +1694,24 @@ var VelaWorkspace = class {
|
|
|
1620
1694
|
}
|
|
1621
1695
|
/**
|
|
1622
1696
|
* Mirror an origin cell's pointer time onto its same-group followers as GHOST
|
|
1623
|
-
* crosshairs (`renderer.setExternalCrosshair`).
|
|
1624
|
-
*
|
|
1625
|
-
*
|
|
1626
|
-
*
|
|
1697
|
+
* crosshairs (`renderer.setExternalCrosshair`). The horizontal price level rides
|
|
1698
|
+
* along ONLY to followers showing the same ticker — price scales are comparable
|
|
1699
|
+
* there, while an origin's price painted on another market's pane would be noise.
|
|
1700
|
+
* Leaving the origin propagates `null` (the event already carries it) and clears
|
|
1701
|
+
* every ghost. No busy guard needed: an external crosshair never re-emits
|
|
1702
|
+
* `onCrosshairMove` — the flow is one-way by port contract, so no echo loop can
|
|
1703
|
+
* exist.
|
|
1627
1704
|
*/
|
|
1628
|
-
propagateCrosshair(originId, time) {
|
|
1705
|
+
propagateCrosshair(originId, time, price = null) {
|
|
1629
1706
|
if (this.destroyed) return;
|
|
1630
1707
|
const setting = this.syncOpts.crosshair;
|
|
1631
1708
|
if (!setting) return;
|
|
1709
|
+
const originTicker = parseSymbol(this.cellsById.get(originId)?.symbol ?? "").ticker;
|
|
1632
1710
|
for (const id of syncTargets(originId, setting, [...this.cellsById.keys()])) {
|
|
1633
|
-
this.cellsById.get(id)
|
|
1711
|
+
const follower = this.cellsById.get(id);
|
|
1712
|
+
if (!follower) continue;
|
|
1713
|
+
const comparable = originTicker !== "" && parseSymbol(follower.symbol).ticker === originTicker;
|
|
1714
|
+
follower.chart.renderer.setExternalCrosshair(time, comparable ? price : null);
|
|
1634
1715
|
}
|
|
1635
1716
|
}
|
|
1636
1717
|
/**
|
|
@@ -1785,6 +1866,8 @@ var VelaWorkspace = class {
|
|
|
1785
1866
|
if (!cell) return;
|
|
1786
1867
|
this.topbar.setSymbol(cell.symbol);
|
|
1787
1868
|
this.topbar.setTimeframe(cell.timeframe);
|
|
1869
|
+
this.mobileBar?.setSymbol(cell.symbol);
|
|
1870
|
+
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
1788
1871
|
this.objectTree.setSymbol(cell.symbol);
|
|
1789
1872
|
}
|
|
1790
1873
|
/** Trigger ② — a cell's indicator ledger changed: count + picker only if active. */
|
|
@@ -1794,13 +1877,132 @@ var VelaWorkspace = class {
|
|
|
1794
1877
|
const cell = this.cellsById.get(id);
|
|
1795
1878
|
if (!cell) return;
|
|
1796
1879
|
this.topbar.setIndicatorCount(cell.indicatorCount);
|
|
1797
|
-
this.indicatorPicker
|
|
1880
|
+
this.indicatorPicker?.sync();
|
|
1798
1881
|
}
|
|
1799
1882
|
/** Timeframe changes routed from the topbar menu / quick entry (chip state follows). */
|
|
1800
1883
|
setActiveTimeframe(tf) {
|
|
1801
1884
|
this.bottombar?.setActiveRange(null);
|
|
1802
1885
|
this.active.setTimeframe(tf);
|
|
1803
1886
|
}
|
|
1887
|
+
/** The mode flipped (container resized across the breakpoint, or a coarse-pointer
|
|
1888
|
+
* change). Close the open surfaces — a desktop card must not linger over the
|
|
1889
|
+
* mobile chrome (and vice versa) — and re-present every cell's own chrome. */
|
|
1890
|
+
onLayoutModeChange(mode) {
|
|
1891
|
+
this.symbolPicker.close();
|
|
1892
|
+
this.indicatorPicker?.close();
|
|
1893
|
+
this.tfDrawer?.close();
|
|
1894
|
+
this.drawingsDrawer?.close();
|
|
1895
|
+
this.moreDrawer?.close();
|
|
1896
|
+
this.timezoneDrawer?.close();
|
|
1897
|
+
this.priceScaleDrawer?.close();
|
|
1898
|
+
this.alertsMenu?.destroy();
|
|
1899
|
+
this.alertsMenu = null;
|
|
1900
|
+
for (const cell of this.cellsById.values()) {
|
|
1901
|
+
cell.chart.renderer.closeDialogs();
|
|
1902
|
+
cell.chart.renderer.setLayoutMode(mode);
|
|
1903
|
+
}
|
|
1904
|
+
this.syncCellPresentation();
|
|
1905
|
+
}
|
|
1906
|
+
/** Push the layout-shape-dependent chrome onto every cell: multi-cell grids keep
|
|
1907
|
+
* the status line on one row (segments that don't fit hide), and on MOBILE their
|
|
1908
|
+
* legends' fold chip routes to the object tree instead of unfolding in place —
|
|
1909
|
+
* per-indicator controls live there (the legend rows have no room in a grid cell). */
|
|
1910
|
+
syncCellPresentation() {
|
|
1911
|
+
const multi = this.def.cells.length > 1;
|
|
1912
|
+
const overview = multi && this.layoutCtl.current === "mobile" ? () => this.dock.toggle("objects", true) : null;
|
|
1913
|
+
for (const cell of this.cellsById.values()) {
|
|
1914
|
+
cell.setStatuslineFit(multi);
|
|
1915
|
+
cell.chart.renderer.setLegendOverviewAction(overview);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
// ── mobile drawers (built on first open; every read is live and hits the ACTIVE cell) ──
|
|
1919
|
+
openTimeframeDrawer() {
|
|
1920
|
+
this.tfDrawer ?? (this.tfDrawer = new TimeframeDrawer({
|
|
1921
|
+
host: this.root,
|
|
1922
|
+
timeframes: this.opts.timeframes ?? DEFAULT_TIMEFRAMES,
|
|
1923
|
+
ranges: RANGE_PRESETS,
|
|
1924
|
+
currentTimeframe: () => this.active.timeframe,
|
|
1925
|
+
activeRange: () => this.active.activeRangeId,
|
|
1926
|
+
onTimeframe: (tf) => this.setActiveTimeframe(tf),
|
|
1927
|
+
onRange: (preset) => {
|
|
1928
|
+
this.active.applyRange(preset);
|
|
1929
|
+
this.bottombar?.setActiveRange(preset.id);
|
|
1930
|
+
},
|
|
1931
|
+
onOpenChange: (open) => this.trackDialog(open)
|
|
1932
|
+
}));
|
|
1933
|
+
this.tfDrawer.open();
|
|
1934
|
+
}
|
|
1935
|
+
openDrawingsDrawer() {
|
|
1936
|
+
this.drawingsDrawer ?? (this.drawingsDrawer = new DrawingsDrawer({
|
|
1937
|
+
host: this.root,
|
|
1938
|
+
toolbar: () => defaultToolbar(),
|
|
1939
|
+
// the shared static toolbar's definition (see constructor)
|
|
1940
|
+
currentTool: () => this.active.chart.drawings.getTool(),
|
|
1941
|
+
isFavorite: (type) => this.active.chart.drawings.isFavorite(type),
|
|
1942
|
+
onFavorite: (type, on) => this.active.chart.drawings.setFavorite(type, on),
|
|
1943
|
+
onSelect: (type) => this.active.chart.drawings.setTool(type),
|
|
1944
|
+
onOpenChange: (open) => this.trackDialog(open)
|
|
1945
|
+
}));
|
|
1946
|
+
this.drawingsDrawer.open();
|
|
1947
|
+
}
|
|
1948
|
+
openMoreDrawer() {
|
|
1949
|
+
this.moreDrawer ?? (this.moreDrawer = new MoreDrawer({
|
|
1950
|
+
host: this.root,
|
|
1951
|
+
onUndo: () => this.active.history.undo(),
|
|
1952
|
+
onRedo: () => this.active.history.redo(),
|
|
1953
|
+
onScreenshot: () => this.active.downloadScreenshot(),
|
|
1954
|
+
canUndo: () => this.active.history.canUndo,
|
|
1955
|
+
canRedo: () => this.active.history.canRedo,
|
|
1956
|
+
priceStyles: () => priceStyleIds().map((id) => ({ id, label: priceStyleLabel(id), icon: priceStyleIcon(id) })),
|
|
1957
|
+
priceStyle: () => this.active.priceStyle,
|
|
1958
|
+
onPriceStyle: (id) => this.active.setPriceStyle(id),
|
|
1959
|
+
panels: () => [...this.dock.list()],
|
|
1960
|
+
onTogglePanel: (id) => this.dock.toggle(id),
|
|
1961
|
+
alerts: () => this.alerts.map((a) => ({ title: `[${a.cellId} \xB7 ${a.symbol}] ${a.title}`, message: a.message, time: a.time })),
|
|
1962
|
+
// Left-aligned actions have their own bottom-bar stop — only the rest
|
|
1963
|
+
// lands in the drawer, or every left action would appear twice.
|
|
1964
|
+
actions: () => widgetActions("topbar", this.context()).filter((a) => a.align !== "left").map((a) => ({ label: a.label, icon: a.icon, run: () => a.run(this.context()) })),
|
|
1965
|
+
// The desktop layout dropdown's whole surface — the grid canvas, the
|
|
1966
|
+
// non-canvas presets and the sync switches — relocated into the kebab
|
|
1967
|
+
// drawer (the topbar is hidden on mobile). Same reads as the topbar block.
|
|
1968
|
+
layout: {
|
|
1969
|
+
shape: () => layoutShape(this.def),
|
|
1970
|
+
presets: () => layouts().filter((l) => layoutShape(l) === null).map((l) => ({ id: l.id, label: l.label, checked: l.id === this.def.id })),
|
|
1971
|
+
onSelectGrid: (rows, cols) => this.setLayout(layoutForGrid(rows, cols)),
|
|
1972
|
+
onSelectPreset: (id) => this.setLayout(id),
|
|
1973
|
+
syncs: () => [
|
|
1974
|
+
{ id: "symbol", label: "Symbol", checked: this.syncOpts.symbol === true },
|
|
1975
|
+
{ id: "timeframe", label: "Interval", checked: this.syncOpts.timeframe === true },
|
|
1976
|
+
{ id: "crosshair", label: "Crosshair", checked: this.syncOpts.crosshair === true }
|
|
1977
|
+
],
|
|
1978
|
+
onToggleSync: (id) => {
|
|
1979
|
+
const kind = id;
|
|
1980
|
+
this.sync.set(kind, this.syncOpts[kind] ? false : true);
|
|
1981
|
+
}
|
|
1982
|
+
},
|
|
1983
|
+
onOpenChange: (open) => this.trackDialog(open)
|
|
1984
|
+
}));
|
|
1985
|
+
this.moreDrawer.open();
|
|
1986
|
+
}
|
|
1987
|
+
openTimezoneDrawer() {
|
|
1988
|
+
this.timezoneDrawer ?? (this.timezoneDrawer = new TimezoneDrawer({
|
|
1989
|
+
host: this.root,
|
|
1990
|
+
timezone: () => this.timezone,
|
|
1991
|
+
onTimezone: (zone) => this.setTimezone(zone),
|
|
1992
|
+
onOpenChange: (open) => this.trackDialog(open)
|
|
1993
|
+
}));
|
|
1994
|
+
this.timezoneDrawer.open();
|
|
1995
|
+
}
|
|
1996
|
+
openPriceScaleDrawer(y) {
|
|
1997
|
+
this.priceScalePressY = y;
|
|
1998
|
+
this.priceScaleDrawer ?? (this.priceScaleDrawer = new PriceScaleDrawer({
|
|
1999
|
+
host: this.root,
|
|
2000
|
+
chart: () => this.activeId ? this.cellsById.get(this.activeId)?.chart ?? null : null,
|
|
2001
|
+
pressY: () => this.priceScalePressY,
|
|
2002
|
+
onOpenChange: (open) => this.trackDialog(open)
|
|
2003
|
+
}));
|
|
2004
|
+
this.priceScaleDrawer.open();
|
|
2005
|
+
}
|
|
1804
2006
|
/** The aggregated alerts bell — entries carry their cell; selecting one activates it. */
|
|
1805
2007
|
openAlertsMenu(anchor) {
|
|
1806
2008
|
this.alertsMenu?.destroy();
|
|
@@ -1872,7 +2074,9 @@ var VelaWorkspace = class {
|
|
|
1872
2074
|
this.keymap.register({ id: "view.zoom-out", keys: "mod+arrowdown", label: "Zoom out", category: "Chart", run: () => this.glider.zoom(ZOOM_OUT) });
|
|
1873
2075
|
this.keymap.register({ id: "view.pan-left", keys: "mod+arrowleft", label: "Pan toward history", category: "Chart", run: () => this.active.chart.panBy(-PAN_FAST) });
|
|
1874
2076
|
this.keymap.register({ id: "view.pan-right", keys: "mod+arrowright", label: "Pan toward now", category: "Chart", run: () => this.active.chart.panBy(PAN_FAST) });
|
|
1875
|
-
|
|
2077
|
+
if (this.indicatorPicker) {
|
|
2078
|
+
this.keymap.register({ id: "indicators.open", keys: "/", label: "Open the indicator picker", category: "Indicators", run: () => this.indicatorPicker?.open() });
|
|
2079
|
+
}
|
|
1876
2080
|
this.keymap.register({
|
|
1877
2081
|
id: "help.shortcuts",
|
|
1878
2082
|
keys: "?",
|