@luxalgo/vela 0.6.0 → 0.6.1
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-DNx9ntBD.d.ts → DataProvider-BNKtYU5V.d.cts} +13 -3
- package/dist/{DataProvider-Ce6PuCzQ.d.cts → DataProvider-gJjN_0eh.d.ts} +13 -3
- package/dist/{chunk-CA3N3PYT.js → chunk-4MQEG67Z.js} +16 -12
- package/dist/{chunk-7ROONW6H.js → chunk-6LZJRO2S.js} +35 -7
- package/dist/{contributions-Dlc7ZWZz.d.cts → contributions-D64UA74H.d.cts} +2 -2
- package/dist/{contributions-DToMhiw3.d.ts → contributions-lPAgo9Cu.d.ts} +2 -2
- package/dist/{history-BZADxpKx.d.cts → history-CVoFDJ2D.d.ts} +21 -3
- package/dist/{history-BuHXJZJ2.d.ts → history-fSMXVLt1.d.cts} +21 -3
- package/dist/index.cjs +16 -12
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +1 -1
- package/dist/{options-BlQ00Fju.d.cts → options-BqGeFHtp.d.cts} +15 -1
- package/dist/{options-BlQ00Fju.d.ts → options-BqGeFHtp.d.ts} +15 -1
- package/dist/{plugin-BNPLOQO1.d.cts → plugin-D5ni4WEJ.d.cts} +3 -3
- package/dist/{plugin-BqjEa5r3.d.ts → plugin-o5HJH46Z.d.ts} +3 -3
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- 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.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/vela.global.js +16 -12
- package/dist/vela.global.min.js +2 -2
- package/dist/widget.cjs +92 -19
- package/dist/widget.d.cts +18 -6
- package/dist/widget.d.ts +18 -6
- package/dist/widget.js +47 -6
- package/dist/workspace.cjs +94 -18
- package/dist/workspace.d.cts +20 -5
- package/dist/workspace.d.ts +20 -5
- package/dist/workspace.js +48 -4
- package/package.json +1 -1
package/dist/workspace.cjs
CHANGED
|
@@ -326,8 +326,8 @@ var ProviderRegistry = class {
|
|
|
326
326
|
};
|
|
327
327
|
|
|
328
328
|
// src/data/BarStore.ts
|
|
329
|
-
function seriesKey(provider, symbol, timeframe) {
|
|
330
|
-
return `${provider}|${symbol}|${timeframe}`;
|
|
329
|
+
function seriesKey(provider, symbol, timeframe, session) {
|
|
330
|
+
return `${provider}|${symbol}|${timeframe}${session && session !== "regular" ? `|${session}` : ""}`;
|
|
331
331
|
}
|
|
332
332
|
function symbolOf(key) {
|
|
333
333
|
return key.split("|")[1] ?? "";
|
|
@@ -425,9 +425,9 @@ function timeframeToMs(timeframe) {
|
|
|
425
425
|
}
|
|
426
426
|
|
|
427
427
|
// src/data/CachingDataFeed.ts
|
|
428
|
-
function cacheKey(symbol, timeframe) {
|
|
428
|
+
function cacheKey(symbol, timeframe, session) {
|
|
429
429
|
const { provider, ticker } = parseSymbol(symbol);
|
|
430
|
-
return seriesKey(provider ?? "", ticker, timeframe);
|
|
430
|
+
return seriesKey(provider ?? "", ticker, timeframe, session);
|
|
431
431
|
}
|
|
432
432
|
var PAGE_BARS = 1e4;
|
|
433
433
|
var SINGLE_FETCH_BARS = PAGE_BARS + 1;
|
|
@@ -439,7 +439,7 @@ var CachingDataFeed = class {
|
|
|
439
439
|
async load(cfg) {
|
|
440
440
|
if (cfg.data && cfg.data.length > 0) return this.inner.load(cfg);
|
|
441
441
|
const symbol = cfg.symbol ?? "TEST";
|
|
442
|
-
const key = cacheKey(symbol, cfg.timeframe ?? "60");
|
|
442
|
+
const key = cacheKey(symbol, cfg.timeframe ?? "60", cfg.session);
|
|
443
443
|
this.store.retainSymbol(symbol);
|
|
444
444
|
const cached = this.store.get(key);
|
|
445
445
|
const n = cfg.bars ?? 500;
|
|
@@ -468,7 +468,7 @@ var CachingDataFeed = class {
|
|
|
468
468
|
*/
|
|
469
469
|
async loadRange(cfg, range) {
|
|
470
470
|
if (!this.inner.loadRange) return this.inner.load(cfg);
|
|
471
|
-
const key = cacheKey(cfg.symbol ?? "TEST", cfg.timeframe ?? "60");
|
|
471
|
+
const key = cacheKey(cfg.symbol ?? "TEST", cfg.timeframe ?? "60", cfg.session);
|
|
472
472
|
let cached = this.store.get(key);
|
|
473
473
|
let newest = cached?.[cached.length - 1];
|
|
474
474
|
if (range.to != null && newest && range.to < newest.time) {
|
|
@@ -775,13 +775,13 @@ var RegistryFetchFeed = class {
|
|
|
775
775
|
const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
|
|
776
776
|
const provider = this.registry.get(name ?? "");
|
|
777
777
|
if (!provider) return Promise.resolve([]);
|
|
778
|
-
return safeBars(provider, ticker, cfg.timeframe ?? "60", { limit: cfg.bars ?? 500 });
|
|
778
|
+
return safeBars(provider, ticker, cfg.timeframe ?? "60", { limit: cfg.bars ?? 500, session: cfg.session });
|
|
779
779
|
}
|
|
780
780
|
loadRange(cfg, range) {
|
|
781
781
|
const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
|
|
782
782
|
const provider = this.registry.get(name ?? "");
|
|
783
783
|
if (!provider) return Promise.resolve([]);
|
|
784
|
-
return safeBars(provider, ticker, cfg.timeframe ?? "60", range);
|
|
784
|
+
return safeBars(provider, ticker, cfg.timeframe ?? "60", { ...range, session: cfg.session });
|
|
785
785
|
}
|
|
786
786
|
subscribe(cfg, onBar) {
|
|
787
787
|
const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
|
|
@@ -789,13 +789,13 @@ var RegistryFetchFeed = class {
|
|
|
789
789
|
if (!provider) return () => {
|
|
790
790
|
};
|
|
791
791
|
const tf = cfg.timeframe ?? "60";
|
|
792
|
-
if (provider.subscribe) return provider.subscribe(ticker, tf, onBar);
|
|
792
|
+
if (provider.subscribe) return provider.subscribe(ticker, tf, onBar, cfg.session ? { session: cfg.session } : void 0);
|
|
793
793
|
let stopped = false;
|
|
794
794
|
let timer = null;
|
|
795
795
|
const poll = async () => {
|
|
796
796
|
if (stopped) return;
|
|
797
797
|
try {
|
|
798
|
-
const bars = await provider.getBars(ticker, tf, { limit: 2 });
|
|
798
|
+
const bars = await provider.getBars(ticker, tf, { limit: 2, session: cfg.session });
|
|
799
799
|
if (stopped) return;
|
|
800
800
|
for (const b of bars) onBar(b);
|
|
801
801
|
} catch {
|
|
@@ -4774,10 +4774,12 @@ var CSS4 = `
|
|
|
4774
4774
|
color: var(--vela-fg-muted);
|
|
4775
4775
|
font-size: 11px;
|
|
4776
4776
|
font-weight: 600;
|
|
4777
|
-
cursor:
|
|
4778
|
-
opacity: 0.55;
|
|
4777
|
+
cursor: pointer;
|
|
4779
4778
|
}
|
|
4780
|
-
.vela-bb-session-btn
|
|
4779
|
+
.vela-bb-session-btn:disabled { cursor: not-allowed; opacity: 0.55; }
|
|
4780
|
+
.vela-bb-session-btn:not(:disabled):hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
|
|
4781
|
+
.vela-bb-session-btn.is-active { color: var(--vela-fg); background: var(--vela-surface-elev); }
|
|
4782
|
+
.vela-bb-session-btn.is-active:disabled { opacity: 0.8; }
|
|
4781
4783
|
.vela-bb-settings {
|
|
4782
4784
|
all: unset;
|
|
4783
4785
|
display: inline-flex;
|
|
@@ -4797,6 +4799,8 @@ var Bottombar = class {
|
|
|
4797
4799
|
constructor(host, opts) {
|
|
4798
4800
|
this.settingsTip = null;
|
|
4799
4801
|
this.rangeButtons = /* @__PURE__ */ new Map();
|
|
4802
|
+
this.sessionButtons = /* @__PURE__ */ new Map();
|
|
4803
|
+
this.sessionEl = null;
|
|
4800
4804
|
this.timer = null;
|
|
4801
4805
|
this.timezone = opts.timezone;
|
|
4802
4806
|
const doc = host.ownerDocument;
|
|
@@ -4826,12 +4830,19 @@ var Bottombar = class {
|
|
|
4826
4830
|
this.tzButton.append(this.clockEl, this.tzLabelEl);
|
|
4827
4831
|
const session = doc.createElement("span");
|
|
4828
4832
|
session.className = "vela-bb-session";
|
|
4833
|
+
this.sessionEl = session;
|
|
4829
4834
|
session.title = "Session \u2014 stocks & ETFs only";
|
|
4830
|
-
for (const [
|
|
4835
|
+
for (const [key, label] of [["regular", "RTH"], ["extended", "ETH"]]) {
|
|
4831
4836
|
const b = doc.createElement("button");
|
|
4832
|
-
b.className = "vela-bb-session-btn" + (
|
|
4837
|
+
b.className = "vela-bb-session-btn" + (key === "regular" ? " is-active" : "");
|
|
4833
4838
|
b.textContent = label;
|
|
4834
4839
|
b.disabled = true;
|
|
4840
|
+
b.addEventListener("click", () => {
|
|
4841
|
+
if (b.disabled) return;
|
|
4842
|
+
this.setSession({ session: key, enabled: true });
|
|
4843
|
+
opts.onSession?.(key);
|
|
4844
|
+
});
|
|
4845
|
+
this.sessionButtons.set(key, b);
|
|
4835
4846
|
session.appendChild(b);
|
|
4836
4847
|
}
|
|
4837
4848
|
const settingsBtn = doc.createElement("button");
|
|
@@ -4869,6 +4880,19 @@ var Bottombar = class {
|
|
|
4869
4880
|
else delete b.dataset.active;
|
|
4870
4881
|
}
|
|
4871
4882
|
}
|
|
4883
|
+
/**
|
|
4884
|
+
* Reflect the ACTIVE chart's session posture. `enabled: false` (a continuous
|
|
4885
|
+
* market, or metadata not landed yet) shows the disabled RTH-active stub — the
|
|
4886
|
+
* pre-session-model look, byte-for-byte. Enabled, the chips become clickable and
|
|
4887
|
+
* the active one tracks the chart's current session.
|
|
4888
|
+
*/
|
|
4889
|
+
setSession(state) {
|
|
4890
|
+
if (this.sessionEl) this.sessionEl.title = state.enabled ? "Session \u2014 regular (RTH) vs extended (ETH) hours" : "Session \u2014 stocks & ETFs only";
|
|
4891
|
+
for (const [key, b] of this.sessionButtons) {
|
|
4892
|
+
b.disabled = !state.enabled;
|
|
4893
|
+
b.classList.toggle("is-active", state.enabled ? key === state.session : key === "regular");
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4872
4896
|
destroy() {
|
|
4873
4897
|
if (this.timer !== null) clearInterval(this.timer);
|
|
4874
4898
|
this.tzMenu.destroy();
|
|
@@ -16258,6 +16282,7 @@ function sanitizeCell(raw) {
|
|
|
16258
16282
|
if (typeof c.timeframe === "string") out.timeframe = c.timeframe;
|
|
16259
16283
|
if (typeof c.priceStyle === "string") out.priceStyle = c.priceStyle;
|
|
16260
16284
|
if (typeof c.bars === "number" && Number.isFinite(c.bars) && c.bars > 0) out.bars = c.bars;
|
|
16285
|
+
if (c.session === "regular" || c.session === "extended") out.session = c.session;
|
|
16261
16286
|
if (typeof c.watermark === "boolean") out.watermark = c.watermark;
|
|
16262
16287
|
if (typeof c.indicatorTitles === "boolean") out.indicatorTitles = c.indicatorTitles;
|
|
16263
16288
|
if (typeof c.indicatorValues === "boolean") out.indicatorValues = c.indicatorValues;
|
|
@@ -16891,7 +16916,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
16891
16916
|
* an in-flight `setMarket` immediately (the config mutates before the load). */
|
|
16892
16917
|
marketSnapshot() {
|
|
16893
16918
|
const m = this.config.market;
|
|
16894
|
-
return { symbol: m.symbol, provider: parseSymbol(m.symbol ?? "").provider ?? void 0, timeframe: m.timeframe, bars: m.bars, offline: m.data !== void 0 };
|
|
16919
|
+
return { symbol: m.symbol, provider: parseSymbol(m.symbol ?? "").provider ?? void 0, timeframe: m.timeframe, bars: m.bars, session: m.session, offline: m.data !== void 0 };
|
|
16895
16920
|
}
|
|
16896
16921
|
/**
|
|
16897
16922
|
* Switch the chart's market IN PLACE — no destroy/recreate. The renderer stays
|
|
@@ -16910,7 +16935,9 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
16910
16935
|
*/
|
|
16911
16936
|
async setMarket(next) {
|
|
16912
16937
|
const m = this.config.market;
|
|
16913
|
-
const identityChanged = next.symbol !== void 0 && next.symbol !== m.symbol || next.timeframe !== void 0 && next.timeframe !== m.timeframe ||
|
|
16938
|
+
const identityChanged = next.symbol !== void 0 && next.symbol !== m.symbol || next.timeframe !== void 0 && next.timeframe !== m.timeframe || // A session switch changes WHICH bars exist (RTH vs ETH) — a full reload,
|
|
16939
|
+
// exactly like a timeframe change; the cache keys the sessions apart.
|
|
16940
|
+
next.session !== void 0 && next.session !== m.session || next.data !== void 0;
|
|
16914
16941
|
const depthChanged = next.bars !== void 0 && next.bars !== m.bars;
|
|
16915
16942
|
const depthOnly = depthChanged && !identityChanged && this.rawBars.length > 0 && !m.data?.length && ((next.bars ?? 0) <= this.rawBars.length || typeof this.feed.loadRange === "function");
|
|
16916
16943
|
if (!identityChanged && !depthChanged) {
|
|
@@ -16932,6 +16959,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
16932
16959
|
if (next.symbol !== void 0) m.symbol = next.symbol;
|
|
16933
16960
|
if (next.timeframe !== void 0) m.timeframe = next.timeframe;
|
|
16934
16961
|
if (next.bars !== void 0) m.bars = next.bars;
|
|
16962
|
+
if (next.session !== void 0) m.session = next.session;
|
|
16935
16963
|
if (next.data !== void 0) m.data = next.data;
|
|
16936
16964
|
else if (next.symbol !== void 0) delete m.data;
|
|
16937
16965
|
m.visibleRange = next.visibleRange;
|
|
@@ -34003,6 +34031,7 @@ var Vela = class {
|
|
|
34003
34031
|
symbol: options.symbol,
|
|
34004
34032
|
timeframe: options.timeframe,
|
|
34005
34033
|
bars: options.bars,
|
|
34034
|
+
session: options.session,
|
|
34006
34035
|
visibleRange: options.visibleRange,
|
|
34007
34036
|
data: options.data
|
|
34008
34037
|
},
|
|
@@ -34293,6 +34322,9 @@ function resolveElement(container) {
|
|
|
34293
34322
|
return element;
|
|
34294
34323
|
}
|
|
34295
34324
|
|
|
34325
|
+
// src/core/options.ts
|
|
34326
|
+
var normalizeSession = (v) => v === "regular" || v === "extended" ? v : void 0;
|
|
34327
|
+
|
|
34296
34328
|
// src/widget/format.ts
|
|
34297
34329
|
function decimalsFor(ref) {
|
|
34298
34330
|
const a = Math.abs(ref);
|
|
@@ -34971,6 +35003,7 @@ function seedDefaults(opts) {
|
|
|
34971
35003
|
timeframe: opts.timeframe,
|
|
34972
35004
|
bars: opts.bars,
|
|
34973
35005
|
priceStyle: opts.priceStyle,
|
|
35006
|
+
session: opts.session,
|
|
34974
35007
|
data: opts.data,
|
|
34975
35008
|
visibleRange: opts.visibleRange
|
|
34976
35009
|
};
|
|
@@ -34999,6 +35032,8 @@ var ChartCell = class {
|
|
|
34999
35032
|
this.lastCrossPrice = null;
|
|
35000
35033
|
/** The bottombar range chip this cell is framed on (null = none). */
|
|
35001
35034
|
this.activeRangeId = null;
|
|
35035
|
+
/** Latched verdict of {@link sessionAvailable} (async metadata, sticky per symbol). */
|
|
35036
|
+
this.sessionAvailableFlag = false;
|
|
35002
35037
|
this.manifest = [];
|
|
35003
35038
|
/** A restored ledger's manifest entry NAMES, waiting for the manifest to resolve
|
|
35004
35039
|
* (a pool/persisted cell can be built before the shared manifest has loaded). */
|
|
@@ -35018,7 +35053,7 @@ var ChartCell = class {
|
|
|
35018
35053
|
this.destroyed = false;
|
|
35019
35054
|
this.appTheme = deps.theme;
|
|
35020
35055
|
const symbol = prefixedSymbol(seed);
|
|
35021
|
-
this.state = { symbol, provider: parseSymbol(symbol ?? "").provider ?? void 0, timeframe: seed.timeframe, priceStyle: seed.priceStyle, bars: seed.bars };
|
|
35056
|
+
this.state = { symbol, provider: parseSymbol(symbol ?? "").provider ?? void 0, timeframe: seed.timeframe, priceStyle: seed.priceStyle, bars: seed.bars, session: normalizeSession(seed.session) };
|
|
35022
35057
|
const doc = gridHost.ownerDocument;
|
|
35023
35058
|
this.host = doc.createElement("div");
|
|
35024
35059
|
this.host.className = "vela-cell";
|
|
@@ -35035,6 +35070,7 @@ var ChartCell = class {
|
|
|
35035
35070
|
timeframe: seed.timeframe,
|
|
35036
35071
|
bars: seed.bars,
|
|
35037
35072
|
priceStyle: seed.priceStyle,
|
|
35073
|
+
session: normalizeSession(seed.session),
|
|
35038
35074
|
data: seed.data,
|
|
35039
35075
|
visibleRange: seed.visibleRange,
|
|
35040
35076
|
theme: deps.theme,
|
|
@@ -35095,6 +35131,7 @@ var ChartCell = class {
|
|
|
35095
35131
|
this.statusline?.onChart(this.inner);
|
|
35096
35132
|
void this.inner.data.ready().then(() => {
|
|
35097
35133
|
if (this.inner && this.state.symbol) this.statusline?.setMeta(this.state.timeframe ?? "60", this.inner.data.displayPrefix(this.state.symbol) ?? this.state.provider ?? "");
|
|
35134
|
+
this.refreshSessionAvailable();
|
|
35098
35135
|
});
|
|
35099
35136
|
this.syncStatuslineColors();
|
|
35100
35137
|
this.contextMenu = new ChartContextMenu(this.host, {
|
|
@@ -35216,14 +35253,48 @@ var ChartCell = class {
|
|
|
35216
35253
|
this.state.symbol = symbol2;
|
|
35217
35254
|
this.state.provider = parseSymbol(symbol2).provider ?? void 0;
|
|
35218
35255
|
this.state.timeframe = timeframe;
|
|
35256
|
+
this.state.session = normalizeSession(this.inner?.market.session);
|
|
35219
35257
|
this.watermark?.update(symbol2, timeframe);
|
|
35220
35258
|
this.statusline?.setSymbol(symbol2);
|
|
35221
35259
|
this.statusline?.setMeta(timeframe, this.inner?.data.displayPrefix(symbol2) ?? this.state.provider ?? "");
|
|
35222
35260
|
if (this.inner) this.statusline?.onChart(this.inner);
|
|
35223
35261
|
this.refreshNativeCatalog();
|
|
35262
|
+
this.refreshSessionAvailable();
|
|
35224
35263
|
this.deps.onMarketChanged(this.id);
|
|
35225
35264
|
});
|
|
35226
35265
|
}
|
|
35266
|
+
/**
|
|
35267
|
+
* Does this cell's market HAVE sessions (RTH/ETH meaningful)? Derived from the
|
|
35268
|
+
* symbol's own metadata (`syminfo.session !== '24x7'`), asynchronously — the
|
|
35269
|
+
* workspace re-projects the shared bottombar when the verdict lands or changes.
|
|
35270
|
+
*/
|
|
35271
|
+
get sessionAvailable() {
|
|
35272
|
+
return this.sessionAvailableFlag;
|
|
35273
|
+
}
|
|
35274
|
+
/** This cell's shown session (`regular` when unset — the provider default). */
|
|
35275
|
+
get session() {
|
|
35276
|
+
return normalizeSession(this.state.session) ?? "regular";
|
|
35277
|
+
}
|
|
35278
|
+
/** Switch this cell's shown session in place (a reload — RTH and ETH are different bars). */
|
|
35279
|
+
setSession(session) {
|
|
35280
|
+
if (session === this.session) return;
|
|
35281
|
+
this.state.session = session;
|
|
35282
|
+
this.deps.onStateDirty();
|
|
35283
|
+
void this.inner?.setMarket({ session });
|
|
35284
|
+
}
|
|
35285
|
+
refreshSessionAvailable() {
|
|
35286
|
+
const chart = this.inner;
|
|
35287
|
+
const symbol = this.state.symbol;
|
|
35288
|
+
if (!chart || !symbol) return;
|
|
35289
|
+
void chart.data.symbolInfo(symbol).then((si) => {
|
|
35290
|
+
if (this.inner !== chart) return;
|
|
35291
|
+
const available = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
|
|
35292
|
+
if (available !== this.sessionAvailableFlag) {
|
|
35293
|
+
this.sessionAvailableFlag = available;
|
|
35294
|
+
this.deps.onMarketChanged(this.id);
|
|
35295
|
+
}
|
|
35296
|
+
});
|
|
35297
|
+
}
|
|
35227
35298
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
35228
35299
|
setWatermarkVisible(visible) {
|
|
35229
35300
|
this.watermarkOn = visible;
|
|
@@ -36081,6 +36152,9 @@ var VelaWorkspace = class {
|
|
|
36081
36152
|
this.bottombar?.setActiveRange(preset.id);
|
|
36082
36153
|
},
|
|
36083
36154
|
onTimezone: (zone) => this.setTimezone(zone),
|
|
36155
|
+
// RTH/ETH acts on the ACTIVE cell (like the range chips): sessions
|
|
36156
|
+
// are a per-chart market dimension, not a shell preference.
|
|
36157
|
+
onSession: (session) => this.active.setSession(session),
|
|
36084
36158
|
onSettingsClick: () => this.active.chart.renderer.openSettings()
|
|
36085
36159
|
}) : null;
|
|
36086
36160
|
this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
|
|
@@ -36413,6 +36487,7 @@ var VelaWorkspace = class {
|
|
|
36413
36487
|
this.objectTree.setSymbol(cell.symbol);
|
|
36414
36488
|
this.dock.onChart(cell.chart);
|
|
36415
36489
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
36490
|
+
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
36416
36491
|
this.indicatorPicker?.sync();
|
|
36417
36492
|
this.glider.stop();
|
|
36418
36493
|
const d = cell.chart.drawings;
|
|
@@ -36814,6 +36889,7 @@ var VelaWorkspace = class {
|
|
|
36814
36889
|
this.mobileBar?.setSymbol(cell.symbol);
|
|
36815
36890
|
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
36816
36891
|
this.objectTree.setSymbol(cell.symbol);
|
|
36892
|
+
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
36817
36893
|
}
|
|
36818
36894
|
/** Trigger ② — a cell's indicator ledger changed: count + picker only if active. */
|
|
36819
36895
|
onCellIndicatorsChanged(id) {
|
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, d as MarketSession } from './options-BqGeFHtp.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-fSMXVLt1.cjs';
|
|
3
|
+
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-fSMXVLt1.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-D64UA74H.cjs';
|
|
6
|
+
import { M as MarketDataFeed } from './DataProvider-BNKtYU5V.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[];
|
|
@@ -35,6 +35,8 @@ interface CellSeed {
|
|
|
35
35
|
timeframe?: string;
|
|
36
36
|
priceStyle?: string;
|
|
37
37
|
bars?: number;
|
|
38
|
+
/** Trading session to show (markets that have one; `regular` is the default). */
|
|
39
|
+
session?: string;
|
|
38
40
|
/** Offline bars for this cell — replaces the provider (boot-only). */
|
|
39
41
|
data?: OHLCV[];
|
|
40
42
|
/** Initial visible window (boot-only). */
|
|
@@ -118,6 +120,8 @@ declare class ChartCell {
|
|
|
118
120
|
lastCrossPrice: number | null;
|
|
119
121
|
/** The bottombar range chip this cell is framed on (null = none). */
|
|
120
122
|
activeRangeId: string | null;
|
|
123
|
+
/** Latched verdict of {@link sessionAvailable} (async metadata, sticky per symbol). */
|
|
124
|
+
private sessionAvailableFlag;
|
|
121
125
|
private inner;
|
|
122
126
|
/** The live app theme — seeded from deps, updated on `theme:changed` (the base the
|
|
123
127
|
* plot-overlay tokens re-derive from). */
|
|
@@ -150,6 +154,17 @@ declare class ChartCell {
|
|
|
150
154
|
private indicatorValuesOn;
|
|
151
155
|
private destroyed;
|
|
152
156
|
constructor(id: string, gridHost: HTMLElement, seed: CellBoot, deps: CellDeps);
|
|
157
|
+
/**
|
|
158
|
+
* Does this cell's market HAVE sessions (RTH/ETH meaningful)? Derived from the
|
|
159
|
+
* symbol's own metadata (`syminfo.session !== '24x7'`), asynchronously — the
|
|
160
|
+
* workspace re-projects the shared bottombar when the verdict lands or changes.
|
|
161
|
+
*/
|
|
162
|
+
get sessionAvailable(): boolean;
|
|
163
|
+
/** This cell's shown session (`regular` when unset — the provider default). */
|
|
164
|
+
get session(): MarketSession;
|
|
165
|
+
/** Switch this cell's shown session in place (a reload — RTH and ETH are different bars). */
|
|
166
|
+
setSession(session: MarketSession): void;
|
|
167
|
+
private refreshSessionAvailable;
|
|
153
168
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
154
169
|
setWatermarkVisible(visible: boolean): void;
|
|
155
170
|
/** Show/hide this cell's indicator titles — the in-chart legend rows (persisted per cell). */
|
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, d as MarketSession } from './options-BqGeFHtp.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-CVoFDJ2D.js';
|
|
3
|
+
export { f as ChartState, P as PanelsState, g as decodeState, h as encodeState, s as sanitizeState } from './history-CVoFDJ2D.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-lPAgo9Cu.js';
|
|
6
|
+
import { M as MarketDataFeed } from './DataProvider-gJjN_0eh.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[];
|
|
@@ -35,6 +35,8 @@ interface CellSeed {
|
|
|
35
35
|
timeframe?: string;
|
|
36
36
|
priceStyle?: string;
|
|
37
37
|
bars?: number;
|
|
38
|
+
/** Trading session to show (markets that have one; `regular` is the default). */
|
|
39
|
+
session?: string;
|
|
38
40
|
/** Offline bars for this cell — replaces the provider (boot-only). */
|
|
39
41
|
data?: OHLCV[];
|
|
40
42
|
/** Initial visible window (boot-only). */
|
|
@@ -118,6 +120,8 @@ declare class ChartCell {
|
|
|
118
120
|
lastCrossPrice: number | null;
|
|
119
121
|
/** The bottombar range chip this cell is framed on (null = none). */
|
|
120
122
|
activeRangeId: string | null;
|
|
123
|
+
/** Latched verdict of {@link sessionAvailable} (async metadata, sticky per symbol). */
|
|
124
|
+
private sessionAvailableFlag;
|
|
121
125
|
private inner;
|
|
122
126
|
/** The live app theme — seeded from deps, updated on `theme:changed` (the base the
|
|
123
127
|
* plot-overlay tokens re-derive from). */
|
|
@@ -150,6 +154,17 @@ declare class ChartCell {
|
|
|
150
154
|
private indicatorValuesOn;
|
|
151
155
|
private destroyed;
|
|
152
156
|
constructor(id: string, gridHost: HTMLElement, seed: CellBoot, deps: CellDeps);
|
|
157
|
+
/**
|
|
158
|
+
* Does this cell's market HAVE sessions (RTH/ETH meaningful)? Derived from the
|
|
159
|
+
* symbol's own metadata (`syminfo.session !== '24x7'`), asynchronously — the
|
|
160
|
+
* workspace re-projects the shared bottombar when the verdict lands or changes.
|
|
161
|
+
*/
|
|
162
|
+
get sessionAvailable(): boolean;
|
|
163
|
+
/** This cell's shown session (`regular` when unset — the provider default). */
|
|
164
|
+
get session(): MarketSession;
|
|
165
|
+
/** Switch this cell's shown session in place (a reload — RTH and ETH are different bars). */
|
|
166
|
+
setSession(session: MarketSession): void;
|
|
167
|
+
private refreshSessionAvailable;
|
|
153
168
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
154
169
|
setWatermarkVisible(visible: boolean): void;
|
|
155
170
|
/** Show/hide this cell's indicator titles — the in-chart legend rows (persisted per cell). */
|
package/dist/workspace.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
2
|
-
export { decodeState, encodeState, sanitizeState } from './chunk-
|
|
3
|
-
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs, priceStyleIds } from './chunk-
|
|
1
|
+
import { WidgetHistory, prefixedSymbol, normalizeSession, 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-6LZJRO2S.js';
|
|
2
|
+
export { decodeState, encodeState, sanitizeState } from './chunk-6LZJRO2S.js';
|
|
3
|
+
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs, priceStyleIds } from './chunk-4MQEG67Z.js';
|
|
4
4
|
import { resolveEngines, legendActionsProviderFor, rendererDefaults, widgetActions, widgetAttachments } from './chunk-ZNL2X6U2.js';
|
|
5
5
|
import { KeymapManager, Menu, isEditableTarget } from './chunk-QWIEKZRE.js';
|
|
6
6
|
import { applyPlotOverlayTokens, ensureUIHost } from './chunk-OGRQW3M6.js';
|
|
@@ -39,6 +39,7 @@ function seedDefaults(opts) {
|
|
|
39
39
|
timeframe: opts.timeframe,
|
|
40
40
|
bars: opts.bars,
|
|
41
41
|
priceStyle: opts.priceStyle,
|
|
42
|
+
session: opts.session,
|
|
42
43
|
data: opts.data,
|
|
43
44
|
visibleRange: opts.visibleRange
|
|
44
45
|
};
|
|
@@ -67,6 +68,8 @@ var ChartCell = class {
|
|
|
67
68
|
this.lastCrossPrice = null;
|
|
68
69
|
/** The bottombar range chip this cell is framed on (null = none). */
|
|
69
70
|
this.activeRangeId = null;
|
|
71
|
+
/** Latched verdict of {@link sessionAvailable} (async metadata, sticky per symbol). */
|
|
72
|
+
this.sessionAvailableFlag = false;
|
|
70
73
|
this.manifest = [];
|
|
71
74
|
/** A restored ledger's manifest entry NAMES, waiting for the manifest to resolve
|
|
72
75
|
* (a pool/persisted cell can be built before the shared manifest has loaded). */
|
|
@@ -86,7 +89,7 @@ var ChartCell = class {
|
|
|
86
89
|
this.destroyed = false;
|
|
87
90
|
this.appTheme = deps.theme;
|
|
88
91
|
const symbol = prefixedSymbol(seed);
|
|
89
|
-
this.state = { symbol, provider: parseSymbol(symbol ?? "").provider ?? void 0, timeframe: seed.timeframe, priceStyle: seed.priceStyle, bars: seed.bars };
|
|
92
|
+
this.state = { symbol, provider: parseSymbol(symbol ?? "").provider ?? void 0, timeframe: seed.timeframe, priceStyle: seed.priceStyle, bars: seed.bars, session: normalizeSession(seed.session) };
|
|
90
93
|
const doc = gridHost.ownerDocument;
|
|
91
94
|
this.host = doc.createElement("div");
|
|
92
95
|
this.host.className = "vela-cell";
|
|
@@ -103,6 +106,7 @@ var ChartCell = class {
|
|
|
103
106
|
timeframe: seed.timeframe,
|
|
104
107
|
bars: seed.bars,
|
|
105
108
|
priceStyle: seed.priceStyle,
|
|
109
|
+
session: normalizeSession(seed.session),
|
|
106
110
|
data: seed.data,
|
|
107
111
|
visibleRange: seed.visibleRange,
|
|
108
112
|
theme: deps.theme,
|
|
@@ -163,6 +167,7 @@ var ChartCell = class {
|
|
|
163
167
|
this.statusline?.onChart(this.inner);
|
|
164
168
|
void this.inner.data.ready().then(() => {
|
|
165
169
|
if (this.inner && this.state.symbol) this.statusline?.setMeta(this.state.timeframe ?? "60", this.inner.data.displayPrefix(this.state.symbol) ?? this.state.provider ?? "");
|
|
170
|
+
this.refreshSessionAvailable();
|
|
166
171
|
});
|
|
167
172
|
this.syncStatuslineColors();
|
|
168
173
|
this.contextMenu = new ChartContextMenu(this.host, {
|
|
@@ -284,14 +289,48 @@ var ChartCell = class {
|
|
|
284
289
|
this.state.symbol = symbol2;
|
|
285
290
|
this.state.provider = parseSymbol(symbol2).provider ?? void 0;
|
|
286
291
|
this.state.timeframe = timeframe;
|
|
292
|
+
this.state.session = normalizeSession(this.inner?.market.session);
|
|
287
293
|
this.watermark?.update(symbol2, timeframe);
|
|
288
294
|
this.statusline?.setSymbol(symbol2);
|
|
289
295
|
this.statusline?.setMeta(timeframe, this.inner?.data.displayPrefix(symbol2) ?? this.state.provider ?? "");
|
|
290
296
|
if (this.inner) this.statusline?.onChart(this.inner);
|
|
291
297
|
this.refreshNativeCatalog();
|
|
298
|
+
this.refreshSessionAvailable();
|
|
292
299
|
this.deps.onMarketChanged(this.id);
|
|
293
300
|
});
|
|
294
301
|
}
|
|
302
|
+
/**
|
|
303
|
+
* Does this cell's market HAVE sessions (RTH/ETH meaningful)? Derived from the
|
|
304
|
+
* symbol's own metadata (`syminfo.session !== '24x7'`), asynchronously — the
|
|
305
|
+
* workspace re-projects the shared bottombar when the verdict lands or changes.
|
|
306
|
+
*/
|
|
307
|
+
get sessionAvailable() {
|
|
308
|
+
return this.sessionAvailableFlag;
|
|
309
|
+
}
|
|
310
|
+
/** This cell's shown session (`regular` when unset — the provider default). */
|
|
311
|
+
get session() {
|
|
312
|
+
return normalizeSession(this.state.session) ?? "regular";
|
|
313
|
+
}
|
|
314
|
+
/** Switch this cell's shown session in place (a reload — RTH and ETH are different bars). */
|
|
315
|
+
setSession(session) {
|
|
316
|
+
if (session === this.session) return;
|
|
317
|
+
this.state.session = session;
|
|
318
|
+
this.deps.onStateDirty();
|
|
319
|
+
void this.inner?.setMarket({ session });
|
|
320
|
+
}
|
|
321
|
+
refreshSessionAvailable() {
|
|
322
|
+
const chart = this.inner;
|
|
323
|
+
const symbol = this.state.symbol;
|
|
324
|
+
if (!chart || !symbol) return;
|
|
325
|
+
void chart.data.symbolInfo(symbol).then((si) => {
|
|
326
|
+
if (this.inner !== chart) return;
|
|
327
|
+
const available = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
|
|
328
|
+
if (available !== this.sessionAvailableFlag) {
|
|
329
|
+
this.sessionAvailableFlag = available;
|
|
330
|
+
this.deps.onMarketChanged(this.id);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
295
334
|
/** Show/hide this cell's symbol watermark (persisted per cell). */
|
|
296
335
|
setWatermarkVisible(visible) {
|
|
297
336
|
this.watermarkOn = visible;
|
|
@@ -1149,6 +1188,9 @@ var VelaWorkspace = class {
|
|
|
1149
1188
|
this.bottombar?.setActiveRange(preset.id);
|
|
1150
1189
|
},
|
|
1151
1190
|
onTimezone: (zone) => this.setTimezone(zone),
|
|
1191
|
+
// RTH/ETH acts on the ACTIVE cell (like the range chips): sessions
|
|
1192
|
+
// are a per-chart market dimension, not a shell preference.
|
|
1193
|
+
onSession: (session) => this.active.setSession(session),
|
|
1152
1194
|
onSettingsClick: () => this.active.chart.renderer.openSettings()
|
|
1153
1195
|
}) : null;
|
|
1154
1196
|
this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
|
|
@@ -1481,6 +1523,7 @@ var VelaWorkspace = class {
|
|
|
1481
1523
|
this.objectTree.setSymbol(cell.symbol);
|
|
1482
1524
|
this.dock.onChart(cell.chart);
|
|
1483
1525
|
this.bottombar?.setActiveRange(cell.activeRangeId);
|
|
1526
|
+
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
1484
1527
|
this.indicatorPicker?.sync();
|
|
1485
1528
|
this.glider.stop();
|
|
1486
1529
|
const d = cell.chart.drawings;
|
|
@@ -1882,6 +1925,7 @@ var VelaWorkspace = class {
|
|
|
1882
1925
|
this.mobileBar?.setSymbol(cell.symbol);
|
|
1883
1926
|
this.mobileBar?.setTimeframe(cell.timeframe);
|
|
1884
1927
|
this.objectTree.setSymbol(cell.symbol);
|
|
1928
|
+
this.bottombar?.setSession({ session: cell.session, enabled: cell.sessionAvailable });
|
|
1885
1929
|
}
|
|
1886
1930
|
/** Trigger ② — a cell's indicator ledger changed: count + picker only if active. */
|
|
1887
1931
|
onCellIndicatorsChanged(id) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luxalgo/vela",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Open-source charting library with a native high-performance renderer, drawing tools, pluggable chart types and pluggable scripting engines.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://luxalgo.com/vela",
|