@luxalgo/vela 0.7.6 → 0.7.8
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/NOTICE +28 -28
- package/dist/{chunk-EMB53WNQ.js → chunk-M6GP7DAX.js} +123 -36
- package/dist/{chunk-JSVCWYBF.js → chunk-N4ZZYLMP.js} +2409 -896
- package/dist/{chunk-ZADTVRUO.js → chunk-PVGWNF7V.js} +1 -1
- package/dist/{chunk-BKHSQ4YM.js → chunk-WTWGEB7K.js} +23 -9
- package/dist/{contributions-D6p1RB38.d.cts → contributions-DF_Ea07m.d.cts} +17 -0
- package/dist/{contributions-C7Wsm_S9.d.ts → contributions-nKOSeLy8.d.ts} +17 -0
- package/dist/index.cjs +2416 -902
- package/dist/index.d.cts +37 -6
- package/dist/index.d.ts +37 -6
- package/dist/index.js +2 -2
- package/dist/{plugin-CxWfg6vK.d.cts → plugin-6F04gjQe.d.cts} +23 -23
- package/dist/{plugin-SodaQhjQ.d.ts → plugin-BLsNipkc.d.ts} +23 -23
- package/dist/plugin.d.cts +2 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/{statusline-model-gWHrsOy3.d.cts → statusline-model-BoWJ3cWQ.d.cts} +16 -3
- package/dist/{statusline-model-xBiVsKoE.d.ts → statusline-model-DAFyqVmR.d.ts} +16 -3
- package/dist/ui.cjs +23 -9
- package/dist/ui.d.cts +19 -2
- package/dist/ui.d.ts +19 -2
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +2420 -906
- package/dist/vela.global.min.js +65 -55
- package/dist/widget.cjs +2549 -935
- package/dist/widget.d.cts +5 -5
- package/dist/widget.d.ts +5 -5
- package/dist/widget.js +5 -5
- package/dist/workspace.cjs +2549 -935
- package/dist/workspace.d.cts +35 -6
- package/dist/workspace.d.ts +35 -6
- package/dist/workspace.js +4 -4
- package/package.json +21 -1
package/NOTICE
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
Vela
|
|
2
|
-
Copyright (c) 2026 LuxAlgo
|
|
3
|
-
https://luxalgo.com/vela
|
|
4
|
-
|
|
5
|
-
This product includes the Vela charting library, developed by LuxAlgo.
|
|
6
|
-
|
|
7
|
-
ATTRIBUTION REQUIREMENT
|
|
8
|
-
|
|
9
|
-
Any product, website, or application that displays charts rendered by this
|
|
10
|
-
software must show a visible attribution to the Vela project on every page or
|
|
11
|
-
screen where such a chart is displayed.
|
|
12
|
-
|
|
13
|
-
The library satisfies this requirement automatically: it renders an attribution
|
|
14
|
-
mark (the project logomark linking to the Vela project page) on the chart
|
|
15
|
-
itself, enabled by default. You may restyle or reposition this mark to fit your
|
|
16
|
-
design.
|
|
17
|
-
|
|
18
|
-
You may disable the built-in mark (renderer feature `attribution`) ONLY if you
|
|
19
|
-
display an equivalent visible attribution — the name "Vela" together with a
|
|
20
|
-
link to the project page above — elsewhere on the same page or screen, in a
|
|
21
|
-
place available to your users.
|
|
22
|
-
|
|
23
|
-
Removing, hiding, or obscuring the attribution without providing the
|
|
24
|
-
equivalent notice described above is not permitted.
|
|
25
|
-
|
|
26
|
-
This file constitutes the NOTICE file described in Section 4(d) of the Apache
|
|
27
|
-
License, Version 2.0: redistributions of this software, in source or binary
|
|
28
|
-
form, must include a readable copy of these attribution notices.
|
|
1
|
+
Vela
|
|
2
|
+
Copyright (c) 2026 LuxAlgo
|
|
3
|
+
https://luxalgo.com/vela
|
|
4
|
+
|
|
5
|
+
This product includes the Vela charting library, developed by LuxAlgo.
|
|
6
|
+
|
|
7
|
+
ATTRIBUTION REQUIREMENT
|
|
8
|
+
|
|
9
|
+
Any product, website, or application that displays charts rendered by this
|
|
10
|
+
software must show a visible attribution to the Vela project on every page or
|
|
11
|
+
screen where such a chart is displayed.
|
|
12
|
+
|
|
13
|
+
The library satisfies this requirement automatically: it renders an attribution
|
|
14
|
+
mark (the project logomark linking to the Vela project page) on the chart
|
|
15
|
+
itself, enabled by default. You may restyle or reposition this mark to fit your
|
|
16
|
+
design.
|
|
17
|
+
|
|
18
|
+
You may disable the built-in mark (renderer feature `attribution`) ONLY if you
|
|
19
|
+
display an equivalent visible attribution — the name "Vela" together with a
|
|
20
|
+
link to the project page above — elsewhere on the same page or screen, in a
|
|
21
|
+
place available to your users.
|
|
22
|
+
|
|
23
|
+
Removing, hiding, or obscuring the attribution without providing the
|
|
24
|
+
equivalent notice described above is not permitted.
|
|
25
|
+
|
|
26
|
+
This file constitutes the NOTICE file described in Section 4(d) of the Apache
|
|
27
|
+
License, Version 2.0: redistributions of this software, in source or binary
|
|
28
|
+
form, must include a readable copy of these attribution notices.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock,
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-N4ZZYLMP.js';
|
|
2
2
|
import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, widgetAttachments, getDrawingType, inputDeltas } from './chunk-BFA32GOU.js';
|
|
3
|
-
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-
|
|
4
|
-
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-
|
|
3
|
+
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-PVGWNF7V.js';
|
|
4
|
+
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-WTWGEB7K.js';
|
|
5
5
|
import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-CAFCLMPF.js';
|
|
6
6
|
import { baseOf } from './chunk-W4EJWLEO.js';
|
|
7
7
|
|
|
@@ -1087,6 +1087,7 @@ var Bottombar = class {
|
|
|
1087
1087
|
this.sessionButtons = /* @__PURE__ */ new Map();
|
|
1088
1088
|
this.sessionEl = null;
|
|
1089
1089
|
this.timezone = opts.timezone;
|
|
1090
|
+
this.exchangeTimezone = opts.exchangeTimezone;
|
|
1090
1091
|
const doc = host.ownerDocument;
|
|
1091
1092
|
injectStyles(STYLE_ID3, CSS3, doc);
|
|
1092
1093
|
this.el = doc.createElement("div");
|
|
@@ -1110,7 +1111,7 @@ var Bottombar = class {
|
|
|
1110
1111
|
this.clockEl = doc.createElement("span");
|
|
1111
1112
|
this.clockEl.className = "vela-bb-clock";
|
|
1112
1113
|
this.tzLabelEl = doc.createElement("span");
|
|
1113
|
-
this.tzLabelEl.textContent = tzButtonLabel(this.
|
|
1114
|
+
this.tzLabelEl.textContent = tzButtonLabel(this.displayZone);
|
|
1114
1115
|
this.tzButton.append(this.clockEl, this.tzLabelEl);
|
|
1115
1116
|
const session = doc.createElement("span");
|
|
1116
1117
|
session.className = "vela-bb-session";
|
|
@@ -1145,19 +1146,32 @@ var Bottombar = class {
|
|
|
1145
1146
|
placement: "top-end",
|
|
1146
1147
|
items: this.tzItems(),
|
|
1147
1148
|
onSelect: (zone) => {
|
|
1148
|
-
this.setTimezone(zone);
|
|
1149
|
+
this.setTimezone(zone, this.exchangeTimezone);
|
|
1149
1150
|
opts.onTimezone(zone);
|
|
1150
1151
|
}
|
|
1151
1152
|
});
|
|
1152
1153
|
this.tick();
|
|
1153
1154
|
this.unsubClock = (opts.clock ?? new SecondClock()).onTick(() => this.tick());
|
|
1154
1155
|
}
|
|
1155
|
-
|
|
1156
|
+
/**
|
|
1157
|
+
* Reflect the stored choice AND the active chart's market zone. The clock and the
|
|
1158
|
+
* offset label read the RESOLVED zone, so a workspace on the exchange rule re-labels
|
|
1159
|
+
* when the active cell (or its symbol) changes market — the host re-projects on
|
|
1160
|
+
* both. Idempotent: unchanged inputs leave the menu alone.
|
|
1161
|
+
*/
|
|
1162
|
+
setTimezone(zone, exchangeTimezone) {
|
|
1163
|
+
if (zone === this.timezone && exchangeTimezone === this.exchangeTimezone) return;
|
|
1164
|
+
const choiceChanged = zone !== this.timezone;
|
|
1156
1165
|
this.timezone = zone;
|
|
1157
|
-
this.
|
|
1158
|
-
this.
|
|
1166
|
+
this.exchangeTimezone = exchangeTimezone;
|
|
1167
|
+
this.tzLabelEl.textContent = tzButtonLabel(this.displayZone);
|
|
1168
|
+
if (choiceChanged) this.tzMenu.setItems(this.tzItems());
|
|
1159
1169
|
this.tick();
|
|
1160
1170
|
}
|
|
1171
|
+
/** The zone the bar's clock and label render in. */
|
|
1172
|
+
get displayZone() {
|
|
1173
|
+
return resolveTimezone(this.timezone, this.exchangeTimezone);
|
|
1174
|
+
}
|
|
1161
1175
|
/** Highlight (or clear with null) the active range chip — cleared on manual tf changes. */
|
|
1162
1176
|
setActiveRange(id) {
|
|
1163
1177
|
for (const [key, b] of this.rangeButtons) {
|
|
@@ -1185,11 +1199,7 @@ var Bottombar = class {
|
|
|
1185
1199
|
this.el.remove();
|
|
1186
1200
|
}
|
|
1187
1201
|
tzItems() {
|
|
1188
|
-
return
|
|
1189
|
-
id: t.value,
|
|
1190
|
-
label: tzMenuLabel(t.value, t.label),
|
|
1191
|
-
checked: t.value === normalizeTimezone(this.timezone)
|
|
1192
|
-
}));
|
|
1202
|
+
return timezoneMenuRows(this.timezone).map((r) => ({ id: r.value, label: r.label, checked: r.checked }));
|
|
1193
1203
|
}
|
|
1194
1204
|
tick() {
|
|
1195
1205
|
try {
|
|
@@ -1198,7 +1208,7 @@ var Bottombar = class {
|
|
|
1198
1208
|
minute: "2-digit",
|
|
1199
1209
|
second: "2-digit",
|
|
1200
1210
|
hour12: false,
|
|
1201
|
-
timeZone: this.
|
|
1211
|
+
timeZone: this.displayZone
|
|
1202
1212
|
}).format(/* @__PURE__ */ new Date());
|
|
1203
1213
|
} catch {
|
|
1204
1214
|
this.clockEl.textContent = "";
|
|
@@ -4756,12 +4766,11 @@ function priceAxisItems(s) {
|
|
|
4756
4766
|
];
|
|
4757
4767
|
}
|
|
4758
4768
|
function timeAxisItems(timezone) {
|
|
4759
|
-
const active = timezone === "UTC" ? "Etc/UTC" : timezone;
|
|
4760
4769
|
return [
|
|
4761
4770
|
{
|
|
4762
4771
|
id: "timezone",
|
|
4763
4772
|
label: "Time zone",
|
|
4764
|
-
submenu:
|
|
4773
|
+
submenu: timezoneMenuRows(timezone).map((r) => ({ id: `tz:${r.value}`, label: r.label, checked: r.checked }))
|
|
4765
4774
|
},
|
|
4766
4775
|
settingsItem("time-axis", "More settings\u2026")
|
|
4767
4776
|
];
|
|
@@ -4882,7 +4891,7 @@ var ChartContextMenu = class {
|
|
|
4882
4891
|
} else if (id.startsWith("tz:")) {
|
|
4883
4892
|
const zone = id.slice("tz:".length);
|
|
4884
4893
|
if (this.cbs.setTimezone) this.cbs.setTimezone(zone);
|
|
4885
|
-
else chart.renderer.set("timezone", zone);
|
|
4894
|
+
else chart.renderer.set("timezone", resolveTimezone(zone, void 0));
|
|
4886
4895
|
} else if (id === "auto") {
|
|
4887
4896
|
chart.renderer.set("autoScale", chart.renderer.get("autoScale") === false);
|
|
4888
4897
|
} else if (id === "invert") {
|
|
@@ -5560,6 +5569,8 @@ var ChartCell = class {
|
|
|
5560
5569
|
this.activeRangeId = null;
|
|
5561
5570
|
/** Latched verdict of {@link sessionAvailable} (async metadata, sticky per symbol). */
|
|
5562
5571
|
this.sessionAvailableFlag = false;
|
|
5572
|
+
/** The symbol of the most recent metadata probe — an older one landing late is dropped. */
|
|
5573
|
+
this.metadataProbeSymbol = null;
|
|
5563
5574
|
/** Latched: the symbol's extended tape wraps midnight (an overnight roll market) —
|
|
5564
5575
|
* one extended-hours shading phase instead of the pre/post split. */
|
|
5565
5576
|
this.sessionOvernightFlag = false;
|
|
@@ -5628,7 +5639,11 @@ var ChartCell = class {
|
|
|
5628
5639
|
nativeBackend: deps.nativeBackend,
|
|
5629
5640
|
// The user's drawings option minus its toolbar: one SHARED bar serves
|
|
5630
5641
|
// the whole workspace (per-cell bars would cost a 44px gutter each).
|
|
5631
|
-
drawings: cellDrawings(deps.chartDefaults.drawings)
|
|
5642
|
+
drawings: cellDrawings(deps.chartDefaults.drawings),
|
|
5643
|
+
// The renderer's own Time zone row edits a resolved IANA zone; the cell
|
|
5644
|
+
// contributes the workspace picker instead (`time-zone`, with the
|
|
5645
|
+
// exchange rule — see pushSettingsSections).
|
|
5646
|
+
settings: { ...deps.chartDefaults.settings, hidden: [...deps.chartDefaults.settings?.hidden ?? [], "symbol.timezone"] }
|
|
5632
5647
|
},
|
|
5633
5648
|
{ dataFeed: deps.feed }
|
|
5634
5649
|
);
|
|
@@ -5641,7 +5656,7 @@ var ChartCell = class {
|
|
|
5641
5656
|
this.history.onChart(this.inner);
|
|
5642
5657
|
this.inner.renderer.onConfigChanged(() => {
|
|
5643
5658
|
const zone = this.inner?.renderer.get("timezone");
|
|
5644
|
-
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.
|
|
5659
|
+
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.displayTimezone)) {
|
|
5645
5660
|
this.deps.setTimezone(normalizeTimezone(zone));
|
|
5646
5661
|
}
|
|
5647
5662
|
const style = this.priceStyle;
|
|
@@ -5677,14 +5692,16 @@ var ChartCell = class {
|
|
|
5677
5692
|
const list = providers.length > 0 ? providers.join(", ") : "none";
|
|
5678
5693
|
this.deps.toast(`No registered provider serves "${symbol2}" (registered: ${list})`, "error", 6e3);
|
|
5679
5694
|
});
|
|
5680
|
-
this.inner.on("load:start", () =>
|
|
5695
|
+
this.inner.on("load:start", ({ symbol: symbol2 }) => {
|
|
5696
|
+
this.watermark?.setLoading(true);
|
|
5697
|
+
this.refreshSymbolMetadata(symbol2);
|
|
5698
|
+
});
|
|
5681
5699
|
this.inner.on("load:end", () => {
|
|
5682
5700
|
this.watermark?.setLoading(false);
|
|
5683
5701
|
this.refreshSessionShading();
|
|
5684
5702
|
});
|
|
5685
5703
|
this.inner.on("viewport:changed", (range) => this.sessionShading.updateRange(range));
|
|
5686
|
-
|
|
5687
|
-
if (tz !== "Etc/UTC") this.inner.renderer.set("timezone", tz);
|
|
5704
|
+
this.applyTimezone();
|
|
5688
5705
|
this.indicatorTitlesOn = seed.indicatorTitles ?? true;
|
|
5689
5706
|
if (!this.indicatorTitlesOn) this.inner.renderer.set("indicatorTitles", false);
|
|
5690
5707
|
this.indicatorValuesOn = seed.indicatorValues ?? true;
|
|
@@ -5706,7 +5723,7 @@ var ChartCell = class {
|
|
|
5706
5723
|
this.statusline?.setSymbol(this.state.symbol);
|
|
5707
5724
|
this.statusline?.setMeta(this.state.timeframe ?? "60", this.inner.data.displayPrefix(this.state.symbol) ?? this.state.provider ?? "");
|
|
5708
5725
|
}
|
|
5709
|
-
this.
|
|
5726
|
+
this.refreshSymbolMetadata();
|
|
5710
5727
|
if (this.inner && this.state.symbol) this.marketStatus?.track(this.inner.data, this.state.symbol);
|
|
5711
5728
|
});
|
|
5712
5729
|
this.syncStatuslineColors();
|
|
@@ -5780,7 +5797,7 @@ var ChartCell = class {
|
|
|
5780
5797
|
this.offMarket = this.inner.on("market:changed", ({ symbol: symbol2, timeframe }) => {
|
|
5781
5798
|
this.projectMarket(symbol2, timeframe);
|
|
5782
5799
|
this.refreshNativeCatalog();
|
|
5783
|
-
this.
|
|
5800
|
+
this.refreshSymbolMetadata();
|
|
5784
5801
|
if (this.inner) this.marketStatus?.track(this.inner.data, symbol2);
|
|
5785
5802
|
this.deps.onMarketChanged(this.id);
|
|
5786
5803
|
});
|
|
@@ -5821,15 +5838,56 @@ var ChartCell = class {
|
|
|
5821
5838
|
this.deps.onStateDirty();
|
|
5822
5839
|
void this.inner?.setMarket({ session });
|
|
5823
5840
|
}
|
|
5824
|
-
|
|
5841
|
+
/**
|
|
5842
|
+
* The symbol's own trading zone, once its metadata has landed — what the exchange
|
|
5843
|
+
* rule resolves to on this cell (the workspace labels the shared bottom bar with the
|
|
5844
|
+
* ACTIVE cell's). Undefined = unknown or undeclared (the rule then renders UTC).
|
|
5845
|
+
*/
|
|
5846
|
+
get exchangeTimezone() {
|
|
5847
|
+
return this.exchangeZone;
|
|
5848
|
+
}
|
|
5849
|
+
/** The IANA zone this cell's axis renders in: the workspace choice, resolved. */
|
|
5850
|
+
get displayTimezone() {
|
|
5851
|
+
return resolveTimezone(this.deps.timezone(), this.exchangeZone);
|
|
5852
|
+
}
|
|
5853
|
+
/**
|
|
5854
|
+
* Push the resolved zone to the renderer — on the workspace choice changing, and on
|
|
5855
|
+
* this cell's market zone changing under the exchange rule. Skips the write when the
|
|
5856
|
+
* renderer already holds it (its config default is the bare `'UTC'` alias).
|
|
5857
|
+
*/
|
|
5858
|
+
applyTimezone() {
|
|
5859
|
+
const chart = this.inner;
|
|
5860
|
+
if (!chart) return;
|
|
5861
|
+
const zone = this.displayTimezone;
|
|
5862
|
+
const current = chart.renderer.get("timezone");
|
|
5863
|
+
const held = typeof current === "string" && current ? current : "UTC";
|
|
5864
|
+
if (normalizeTimezone(held) === normalizeTimezone(zone)) return;
|
|
5865
|
+
chart.renderer.set("timezone", zone);
|
|
5866
|
+
}
|
|
5867
|
+
/** Re-read the symbol's metadata: session posture (RTH/ETH toggle, shading) and its
|
|
5868
|
+
* trading zone (the exchange rule). Async — the workspace re-projects when a verdict lands. */
|
|
5869
|
+
refreshSymbolMetadata(symbol = this.state.symbol, retry = true) {
|
|
5825
5870
|
const chart = this.inner;
|
|
5826
|
-
const symbol = this.state.symbol;
|
|
5827
5871
|
if (!chart || !symbol) return;
|
|
5872
|
+
this.metadataProbeSymbol = symbol;
|
|
5828
5873
|
void chart.data.symbolInfo(symbol).then((si) => {
|
|
5829
|
-
if (this.inner !== chart) return;
|
|
5874
|
+
if (this.inner !== chart || this.metadataProbeSymbol !== symbol) return;
|
|
5875
|
+
if (si === void 0 && retry) {
|
|
5876
|
+
void chart.data.ready().then(() => {
|
|
5877
|
+
if (this.inner === chart && this.metadataProbeSymbol === symbol) this.refreshSymbolMetadata(symbol, false);
|
|
5878
|
+
});
|
|
5879
|
+
return;
|
|
5880
|
+
}
|
|
5881
|
+
if (this.state.symbol !== symbol) return;
|
|
5830
5882
|
const available = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
|
|
5831
5883
|
const overnight = parseSessionSpec(si)?.overnight === true;
|
|
5832
|
-
|
|
5884
|
+
const zone = typeof si?.timezone === "string" && si.timezone !== "" ? si.timezone : void 0;
|
|
5885
|
+
const zoneChanged = zone !== this.exchangeZone;
|
|
5886
|
+
if (zoneChanged) {
|
|
5887
|
+
this.exchangeZone = zone;
|
|
5888
|
+
this.applyTimezone();
|
|
5889
|
+
}
|
|
5890
|
+
if (available !== this.sessionAvailableFlag || overnight !== this.sessionOvernightFlag || zoneChanged) {
|
|
5833
5891
|
this.sessionAvailableFlag = available;
|
|
5834
5892
|
this.sessionOvernightFlag = overnight;
|
|
5835
5893
|
this.deps.onMarketChanged(this.id);
|
|
@@ -5935,6 +5993,24 @@ var ChartCell = class {
|
|
|
5935
5993
|
}
|
|
5936
5994
|
]
|
|
5937
5995
|
};
|
|
5996
|
+
const timezoneSection = {
|
|
5997
|
+
title: "Time zone",
|
|
5998
|
+
id: "time-zone",
|
|
5999
|
+
placement: "symbol",
|
|
6000
|
+
rows: [
|
|
6001
|
+
{
|
|
6002
|
+
kind: "select",
|
|
6003
|
+
label: "Time zone",
|
|
6004
|
+
id: "zone",
|
|
6005
|
+
options: timezoneMenuRows(this.deps.timezone()).map((r) => [r.value, r.label]),
|
|
6006
|
+
get: () => {
|
|
6007
|
+
const choice = this.deps.timezone();
|
|
6008
|
+
return isExchangeTimezone(choice) ? choice : normalizeTimezone(choice);
|
|
6009
|
+
},
|
|
6010
|
+
set: (v) => this.deps.setTimezone(v)
|
|
6011
|
+
}
|
|
6012
|
+
]
|
|
6013
|
+
};
|
|
5938
6014
|
const watermarkSection = {
|
|
5939
6015
|
title: "Watermark",
|
|
5940
6016
|
id: "watermark",
|
|
@@ -6003,7 +6079,7 @@ var ChartCell = class {
|
|
|
6003
6079
|
]
|
|
6004
6080
|
});
|
|
6005
6081
|
}
|
|
6006
|
-
sections.push(advanced);
|
|
6082
|
+
sections.push(advanced, timezoneSection);
|
|
6007
6083
|
if (this.sessionAvailableFlag) sections.push(sessionSection);
|
|
6008
6084
|
sections.push(watermarkSection);
|
|
6009
6085
|
chart.renderer.setSettingsSections(sections);
|
|
@@ -7735,15 +7811,14 @@ var TimezoneDrawer = class {
|
|
|
7735
7811
|
this.drawer.body.replaceChildren();
|
|
7736
7812
|
const list = doc.createElement("div");
|
|
7737
7813
|
list.className = "vela-tzd-list";
|
|
7738
|
-
const
|
|
7739
|
-
for (const tz of TIMEZONES) {
|
|
7814
|
+
for (const tz of timezoneMenuRows(this.opts.timezone())) {
|
|
7740
7815
|
const row = doc.createElement("div");
|
|
7741
7816
|
row.className = "vela-tzd-row";
|
|
7742
7817
|
const label = doc.createElement("span");
|
|
7743
7818
|
label.className = "vela-tzd-row-label";
|
|
7744
|
-
label.textContent =
|
|
7819
|
+
label.textContent = tz.label;
|
|
7745
7820
|
row.appendChild(label);
|
|
7746
|
-
if (tz.
|
|
7821
|
+
if (tz.checked) row.appendChild(iconEl("check", doc));
|
|
7747
7822
|
row.addEventListener("click", () => {
|
|
7748
7823
|
this.opts.onTimezone(tz.value);
|
|
7749
7824
|
this.drawer.hide();
|
|
@@ -8851,13 +8926,23 @@ var VelaWorkspace = class {
|
|
|
8851
8926
|
}
|
|
8852
8927
|
}
|
|
8853
8928
|
}
|
|
8854
|
-
/**
|
|
8929
|
+
/**
|
|
8930
|
+
* Set the workspace-global display timezone — applied to EVERY cell. An IANA zone,
|
|
8931
|
+
* or `'exchange'` (the exchange rule): each cell then renders in its OWN market's
|
|
8932
|
+
* zone (Chicago for a CME future, New York for a US equity, UTC for crypto), and the
|
|
8933
|
+
* bottom bar follows the active cell's.
|
|
8934
|
+
*/
|
|
8855
8935
|
setTimezone(zone) {
|
|
8856
8936
|
this.timezone = zone;
|
|
8857
|
-
this.
|
|
8858
|
-
for (const cell of this.cellsById.values()) cell.
|
|
8937
|
+
this.projectTimezone();
|
|
8938
|
+
for (const cell of this.cellsById.values()) cell.applyTimezone();
|
|
8859
8939
|
this.markStateDirty();
|
|
8860
8940
|
}
|
|
8941
|
+
/** Bottom bar ⇐ the stored choice + the ACTIVE cell's market zone (labels the exchange row). */
|
|
8942
|
+
projectTimezone() {
|
|
8943
|
+
const active = this.activeId ? this.cellsById.get(this.activeId) : void 0;
|
|
8944
|
+
this.bottombar?.setTimezone(this.timezone, active?.exchangeTimezone);
|
|
8945
|
+
}
|
|
8861
8946
|
/**
|
|
8862
8947
|
* Swap the workspace theme at runtime — `'dark'`, `'light'`, or a full custom theme,
|
|
8863
8948
|
* applied to the shared chrome (topbar, panels, drawing toolbar) and EVERY cell.
|
|
@@ -9062,6 +9147,7 @@ var VelaWorkspace = class {
|
|
|
9062
9147
|
this.dock.onChart(cell.chart);
|
|
9063
9148
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
9064
9149
|
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
9150
|
+
this.projectTimezone();
|
|
9065
9151
|
this.indicatorPicker?.sync();
|
|
9066
9152
|
this.glider.stop();
|
|
9067
9153
|
const d = cell.chart.drawings;
|
|
@@ -9646,6 +9732,7 @@ var VelaWorkspace = class {
|
|
|
9646
9732
|
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
9647
9733
|
this.objectTree.setSymbol(cell.symbol);
|
|
9648
9734
|
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
9735
|
+
this.projectTimezone();
|
|
9649
9736
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
9650
9737
|
}
|
|
9651
9738
|
/** Trigger ② — a cell's price style changed: the topbar button/menu only if active.
|