@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.
Files changed (37) hide show
  1. package/dist/{DataProvider-DNx9ntBD.d.ts → DataProvider-BNKtYU5V.d.cts} +13 -3
  2. package/dist/{DataProvider-Ce6PuCzQ.d.cts → DataProvider-gJjN_0eh.d.ts} +13 -3
  3. package/dist/{chunk-CA3N3PYT.js → chunk-4MQEG67Z.js} +16 -12
  4. package/dist/{chunk-7ROONW6H.js → chunk-6LZJRO2S.js} +35 -7
  5. package/dist/{contributions-Dlc7ZWZz.d.cts → contributions-D64UA74H.d.cts} +2 -2
  6. package/dist/{contributions-DToMhiw3.d.ts → contributions-lPAgo9Cu.d.ts} +2 -2
  7. package/dist/{history-BZADxpKx.d.cts → history-CVoFDJ2D.d.ts} +21 -3
  8. package/dist/{history-BuHXJZJ2.d.ts → history-fSMXVLt1.d.cts} +21 -3
  9. package/dist/index.cjs +16 -12
  10. package/dist/index.d.cts +6 -6
  11. package/dist/index.d.ts +6 -6
  12. package/dist/index.js +1 -1
  13. package/dist/{options-BlQ00Fju.d.cts → options-BqGeFHtp.d.cts} +15 -1
  14. package/dist/{options-BlQ00Fju.d.ts → options-BqGeFHtp.d.ts} +15 -1
  15. package/dist/{plugin-BNPLOQO1.d.cts → plugin-D5ni4WEJ.d.cts} +3 -3
  16. package/dist/{plugin-BqjEa5r3.d.ts → plugin-o5HJH46Z.d.ts} +3 -3
  17. package/dist/plugin.d.cts +4 -4
  18. package/dist/plugin.d.ts +4 -4
  19. package/dist/providers/binance.d.cts +2 -2
  20. package/dist/providers/binance.d.ts +2 -2
  21. package/dist/providers/coinbase.d.cts +2 -2
  22. package/dist/providers/coinbase.d.ts +2 -2
  23. package/dist/providers/hyperliquid.d.cts +2 -2
  24. package/dist/providers/hyperliquid.d.ts +2 -2
  25. package/dist/ui.d.cts +1 -1
  26. package/dist/ui.d.ts +1 -1
  27. package/dist/vela.global.js +16 -12
  28. package/dist/vela.global.min.js +2 -2
  29. package/dist/widget.cjs +92 -19
  30. package/dist/widget.d.cts +18 -6
  31. package/dist/widget.d.ts +18 -6
  32. package/dist/widget.js +47 -6
  33. package/dist/workspace.cjs +94 -18
  34. package/dist/workspace.d.cts +20 -5
  35. package/dist/workspace.d.ts +20 -5
  36. package/dist/workspace.js +48 -4
  37. package/package.json +1 -1
package/dist/widget.cjs CHANGED
@@ -7546,7 +7546,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
7546
7546
  * an in-flight `setMarket` immediately (the config mutates before the load). */
7547
7547
  marketSnapshot() {
7548
7548
  const m = this.config.market;
7549
- return { symbol: m.symbol, provider: parseSymbol(m.symbol ?? "").provider ?? void 0, timeframe: m.timeframe, bars: m.bars, offline: m.data !== void 0 };
7549
+ 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 };
7550
7550
  }
7551
7551
  /**
7552
7552
  * Switch the chart's market IN PLACE — no destroy/recreate. The renderer stays
@@ -7565,7 +7565,9 @@ var EngineOrchestrator = class _EngineOrchestrator {
7565
7565
  */
7566
7566
  async setMarket(next) {
7567
7567
  const m = this.config.market;
7568
- const identityChanged = next.symbol !== void 0 && next.symbol !== m.symbol || next.timeframe !== void 0 && next.timeframe !== m.timeframe || next.data !== void 0;
7568
+ 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,
7569
+ // exactly like a timeframe change; the cache keys the sessions apart.
7570
+ next.session !== void 0 && next.session !== m.session || next.data !== void 0;
7569
7571
  const depthChanged = next.bars !== void 0 && next.bars !== m.bars;
7570
7572
  const depthOnly = depthChanged && !identityChanged && this.rawBars.length > 0 && !m.data?.length && ((next.bars ?? 0) <= this.rawBars.length || typeof this.feed.loadRange === "function");
7571
7573
  if (!identityChanged && !depthChanged) {
@@ -7587,6 +7589,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
7587
7589
  if (next.symbol !== void 0) m.symbol = next.symbol;
7588
7590
  if (next.timeframe !== void 0) m.timeframe = next.timeframe;
7589
7591
  if (next.bars !== void 0) m.bars = next.bars;
7592
+ if (next.session !== void 0) m.session = next.session;
7590
7593
  if (next.data !== void 0) m.data = next.data;
7591
7594
  else if (next.symbol !== void 0) delete m.data;
7592
7595
  m.visibleRange = next.visibleRange;
@@ -8940,8 +8943,8 @@ var PanesControl = class {
8940
8943
  };
8941
8944
 
8942
8945
  // src/data/BarStore.ts
8943
- function seriesKey(provider, symbol, timeframe) {
8944
- return `${provider}|${symbol}|${timeframe}`;
8946
+ function seriesKey(provider, symbol, timeframe, session) {
8947
+ return `${provider}|${symbol}|${timeframe}${session && session !== "regular" ? `|${session}` : ""}`;
8945
8948
  }
8946
8949
  function symbolOf(key) {
8947
8950
  return key.split("|")[1] ?? "";
@@ -9024,9 +9027,9 @@ var BarStore = class {
9024
9027
  var sharedBarStore = new BarStore();
9025
9028
 
9026
9029
  // src/data/CachingDataFeed.ts
9027
- function cacheKey(symbol, timeframe) {
9030
+ function cacheKey(symbol, timeframe, session) {
9028
9031
  const { provider, ticker } = parseSymbol(symbol);
9029
- return seriesKey(provider ?? "", ticker, timeframe);
9032
+ return seriesKey(provider ?? "", ticker, timeframe, session);
9030
9033
  }
9031
9034
  var PAGE_BARS = 1e4;
9032
9035
  var SINGLE_FETCH_BARS = PAGE_BARS + 1;
@@ -9038,7 +9041,7 @@ var CachingDataFeed = class {
9038
9041
  async load(cfg) {
9039
9042
  if (cfg.data && cfg.data.length > 0) return this.inner.load(cfg);
9040
9043
  const symbol = cfg.symbol ?? "TEST";
9041
- const key = cacheKey(symbol, cfg.timeframe ?? "60");
9044
+ const key = cacheKey(symbol, cfg.timeframe ?? "60", cfg.session);
9042
9045
  this.store.retainSymbol(symbol);
9043
9046
  const cached = this.store.get(key);
9044
9047
  const n = cfg.bars ?? 500;
@@ -9067,7 +9070,7 @@ var CachingDataFeed = class {
9067
9070
  */
9068
9071
  async loadRange(cfg, range) {
9069
9072
  if (!this.inner.loadRange) return this.inner.load(cfg);
9070
- const key = cacheKey(cfg.symbol ?? "TEST", cfg.timeframe ?? "60");
9073
+ const key = cacheKey(cfg.symbol ?? "TEST", cfg.timeframe ?? "60", cfg.session);
9071
9074
  let cached = this.store.get(key);
9072
9075
  let newest = cached?.[cached.length - 1];
9073
9076
  if (range.to != null && newest && range.to < newest.time) {
@@ -9374,13 +9377,13 @@ var RegistryFetchFeed = class {
9374
9377
  const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
9375
9378
  const provider = this.registry.get(name ?? "");
9376
9379
  if (!provider) return Promise.resolve([]);
9377
- return safeBars(provider, ticker, cfg.timeframe ?? "60", { limit: cfg.bars ?? 500 });
9380
+ return safeBars(provider, ticker, cfg.timeframe ?? "60", { limit: cfg.bars ?? 500, session: cfg.session });
9378
9381
  }
9379
9382
  loadRange(cfg, range) {
9380
9383
  const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
9381
9384
  const provider = this.registry.get(name ?? "");
9382
9385
  if (!provider) return Promise.resolve([]);
9383
- return safeBars(provider, ticker, cfg.timeframe ?? "60", range);
9386
+ return safeBars(provider, ticker, cfg.timeframe ?? "60", { ...range, session: cfg.session });
9384
9387
  }
9385
9388
  subscribe(cfg, onBar) {
9386
9389
  const { provider: name, ticker } = parseSymbol(cfg.symbol ?? "");
@@ -9388,13 +9391,13 @@ var RegistryFetchFeed = class {
9388
9391
  if (!provider) return () => {
9389
9392
  };
9390
9393
  const tf = cfg.timeframe ?? "60";
9391
- if (provider.subscribe) return provider.subscribe(ticker, tf, onBar);
9394
+ if (provider.subscribe) return provider.subscribe(ticker, tf, onBar, cfg.session ? { session: cfg.session } : void 0);
9392
9395
  let stopped = false;
9393
9396
  let timer = null;
9394
9397
  const poll = async () => {
9395
9398
  if (stopped) return;
9396
9399
  try {
9397
- const bars = await provider.getBars(ticker, tf, { limit: 2 });
9400
+ const bars = await provider.getBars(ticker, tf, { limit: 2, session: cfg.session });
9398
9401
  if (stopped) return;
9399
9402
  for (const b of bars) onBar(b);
9400
9403
  } catch {
@@ -27678,6 +27681,7 @@ var Vela = class {
27678
27681
  symbol: options.symbol,
27679
27682
  timeframe: options.timeframe,
27680
27683
  bars: options.bars,
27684
+ session: options.session,
27681
27685
  visibleRange: options.visibleRange,
27682
27686
  data: options.data
27683
27687
  },
@@ -27967,6 +27971,9 @@ function resolveElement(container) {
27967
27971
  if (!element) throw new Error(`[vela] container not found for selector "${container}"`);
27968
27972
  return element;
27969
27973
  }
27974
+
27975
+ // src/core/options.ts
27976
+ var normalizeSession = (v) => v === "regular" || v === "extended" ? v : void 0;
27970
27977
  function runMachine(machine5, props, render) {
27971
27978
  const m = new vanilla.VanillaMachine(machine5, props);
27972
27979
  const unsub = m.subscribe(render);
@@ -30526,10 +30533,12 @@ var CSS7 = `
30526
30533
  color: var(--vela-fg-muted);
30527
30534
  font-size: 11px;
30528
30535
  font-weight: 600;
30529
- cursor: not-allowed;
30530
- opacity: 0.55;
30536
+ cursor: pointer;
30531
30537
  }
30532
- .vela-bb-session-btn.is-active { color: var(--vela-fg); background: var(--vela-surface-elev); opacity: 0.8; }
30538
+ .vela-bb-session-btn:disabled { cursor: not-allowed; opacity: 0.55; }
30539
+ .vela-bb-session-btn:not(:disabled):hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
30540
+ .vela-bb-session-btn.is-active { color: var(--vela-fg); background: var(--vela-surface-elev); }
30541
+ .vela-bb-session-btn.is-active:disabled { opacity: 0.8; }
30533
30542
  .vela-bb-settings {
30534
30543
  all: unset;
30535
30544
  display: inline-flex;
@@ -30549,6 +30558,8 @@ var Bottombar = class {
30549
30558
  constructor(host, opts) {
30550
30559
  this.settingsTip = null;
30551
30560
  this.rangeButtons = /* @__PURE__ */ new Map();
30561
+ this.sessionButtons = /* @__PURE__ */ new Map();
30562
+ this.sessionEl = null;
30552
30563
  this.timer = null;
30553
30564
  this.timezone = opts.timezone;
30554
30565
  const doc = host.ownerDocument;
@@ -30578,12 +30589,19 @@ var Bottombar = class {
30578
30589
  this.tzButton.append(this.clockEl, this.tzLabelEl);
30579
30590
  const session = doc.createElement("span");
30580
30591
  session.className = "vela-bb-session";
30592
+ this.sessionEl = session;
30581
30593
  session.title = "Session \u2014 stocks & ETFs only";
30582
- for (const [label, active] of [["RTH", true], ["ETH", false]]) {
30594
+ for (const [key, label] of [["regular", "RTH"], ["extended", "ETH"]]) {
30583
30595
  const b = doc.createElement("button");
30584
- b.className = "vela-bb-session-btn" + (active ? " is-active" : "");
30596
+ b.className = "vela-bb-session-btn" + (key === "regular" ? " is-active" : "");
30585
30597
  b.textContent = label;
30586
30598
  b.disabled = true;
30599
+ b.addEventListener("click", () => {
30600
+ if (b.disabled) return;
30601
+ this.setSession({ session: key, enabled: true });
30602
+ opts.onSession?.(key);
30603
+ });
30604
+ this.sessionButtons.set(key, b);
30587
30605
  session.appendChild(b);
30588
30606
  }
30589
30607
  const settingsBtn = doc.createElement("button");
@@ -30621,6 +30639,19 @@ var Bottombar = class {
30621
30639
  else delete b.dataset.active;
30622
30640
  }
30623
30641
  }
30642
+ /**
30643
+ * Reflect the ACTIVE chart's session posture. `enabled: false` (a continuous
30644
+ * market, or metadata not landed yet) shows the disabled RTH-active stub — the
30645
+ * pre-session-model look, byte-for-byte. Enabled, the chips become clickable and
30646
+ * the active one tracks the chart's current session.
30647
+ */
30648
+ setSession(state) {
30649
+ if (this.sessionEl) this.sessionEl.title = state.enabled ? "Session \u2014 regular (RTH) vs extended (ETH) hours" : "Session \u2014 stocks & ETFs only";
30650
+ for (const [key, b] of this.sessionButtons) {
30651
+ b.disabled = !state.enabled;
30652
+ b.classList.toggle("is-active", state.enabled ? key === state.session : key === "regular");
30653
+ }
30654
+ }
30624
30655
  destroy() {
30625
30656
  if (this.timer !== null) clearInterval(this.timer);
30626
30657
  this.tzMenu.destroy();
@@ -34687,6 +34718,7 @@ function sanitizeCell(raw) {
34687
34718
  if (typeof c.timeframe === "string") out.timeframe = c.timeframe;
34688
34719
  if (typeof c.priceStyle === "string") out.priceStyle = c.priceStyle;
34689
34720
  if (typeof c.bars === "number" && Number.isFinite(c.bars) && c.bars > 0) out.bars = c.bars;
34721
+ if (c.session === "regular" || c.session === "extended") out.session = c.session;
34690
34722
  if (typeof c.watermark === "boolean") out.watermark = c.watermark;
34691
34723
  if (typeof c.indicatorTitles === "boolean") out.indicatorTitles = c.indicatorTitles;
34692
34724
  if (typeof c.indicatorValues === "boolean") out.indicatorValues = c.indicatorValues;
@@ -34753,7 +34785,8 @@ var PARAMS = [
34753
34785
  ["timeframe", "interval"],
34754
34786
  ["priceStyle", "style"],
34755
34787
  ["timezone", "tz"],
34756
- ["bars", "bars"]
34788
+ ["bars", "bars"],
34789
+ ["session", "session"]
34757
34790
  ];
34758
34791
  function readUrlState(search) {
34759
34792
  const out = {};
@@ -35150,6 +35183,7 @@ var VelaWidget = class {
35150
35183
  this.priceStyle = fromUrl.priceStyle ?? bootCell?.priceStyle ?? opts.priceStyle ?? "candles";
35151
35184
  this.timezone = fromUrl.timezone ?? boot?.timezone ?? opts.timezone ?? "Etc/UTC";
35152
35185
  this.bars = Number(fromUrl.bars ?? bootCell?.bars ?? opts.bars ?? 1e3);
35186
+ this.session = normalizeSession(fromUrl.session ?? bootCell?.session ?? opts.session);
35153
35187
  this.watermarkOn = bootCell?.watermark !== void 0 ? bootCell.watermark : opts.watermark !== false;
35154
35188
  this.indicatorTitlesOn = bootCell?.indicatorTitles ?? true;
35155
35189
  this.indicatorValuesOn = bootCell?.indicatorValues ?? true;
@@ -35256,6 +35290,7 @@ var VelaWidget = class {
35256
35290
  timezone: this.timezone,
35257
35291
  onRange: (preset) => this.applyRange(preset),
35258
35292
  onTimezone: (zone) => this.setTimezone(zone),
35293
+ onSession: (session) => this.setSession(session),
35259
35294
  onSettingsClick: () => this.inner?.renderer.openSettings()
35260
35295
  }) : null;
35261
35296
  this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
@@ -35504,6 +35539,30 @@ var VelaWidget = class {
35504
35539
  this.markStateDirty();
35505
35540
  void this.inner?.setMarket({ timeframe: tf, bars: this.bars });
35506
35541
  }
35542
+ /**
35543
+ * Switch the shown trading session (RTH/ETH) in place — a full reload, like a
35544
+ * timeframe change (the two sessions are different bar series). No-op on a chart
35545
+ * already showing that session; meaningless on continuous markets (the toggle is
35546
+ * disabled there, but the API tolerates the call — the provider ignores the flag).
35547
+ */
35548
+ setSession(session) {
35549
+ if (session === this.session || session === "regular" && this.session === void 0 || this.destroyed) return;
35550
+ this.session = session;
35551
+ this.refreshSessionToggle();
35552
+ this.markStateDirty();
35553
+ void this.inner?.setMarket({ session });
35554
+ }
35555
+ /** Re-derive the RTH/ETH toggle's posture from the ACTIVE symbol's metadata: enabled
35556
+ * iff the resolved symbol declares a real session vocabulary (not `24x7`). */
35557
+ refreshSessionToggle() {
35558
+ const chart = this.inner;
35559
+ if (!chart || !this.bottombar) return;
35560
+ void chart.data.symbolInfo(this.symbol).then((si) => {
35561
+ if (this.destroyed || this.inner !== chart) return;
35562
+ const enabled = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
35563
+ this.bottombar?.setSession({ session: this.session ?? "regular", enabled });
35564
+ });
35565
+ }
35507
35566
  /** Star/unstar a timeframe — the topbar chips and dropdown stars follow, and the
35508
35567
  * set persists with the rest of the shell state. */
35509
35568
  setTimeframeFavorite(tf, on) {
@@ -35550,6 +35609,8 @@ var VelaWidget = class {
35550
35609
  cell.timeframe = live?.timeframe ?? this.timeframe;
35551
35610
  cell.priceStyle = this.priceStyle;
35552
35611
  if (this.bars > 0) cell.bars = this.bars;
35612
+ const session = normalizeSession(live?.session ?? this.session);
35613
+ if (session === "extended") cell.session = session;
35553
35614
  cell.watermark = this.watermarkOn;
35554
35615
  cell.indicatorTitles = this.indicatorTitlesOn;
35555
35616
  cell.indicatorValues = this.indicatorValuesOn;
@@ -35616,9 +35677,15 @@ var VelaWidget = class {
35616
35677
  const symbol = fromUrl.symbol ?? prefixedSymbol(cell);
35617
35678
  const timeframe = fromUrl.timeframe ?? cell.timeframe;
35618
35679
  const bars = Number(fromUrl.bars ?? cell.bars ?? 0);
35680
+ const session = normalizeSession(fromUrl.session ?? cell.session);
35619
35681
  const next = {};
35620
35682
  if (symbol && symbol !== this.symbol) next.symbol = symbol;
35621
35683
  if (timeframe && timeframe !== this.timeframe) next.timeframe = timeframe;
35684
+ if (session && session !== (this.session ?? "regular")) {
35685
+ this.session = session;
35686
+ next.session = session;
35687
+ this.refreshSessionToggle();
35688
+ }
35622
35689
  if (bars > 0 && bars !== this.bars) {
35623
35690
  this.bars = bars;
35624
35691
  next.bars = Math.max(bars, this.rangeBars);
@@ -35845,6 +35912,7 @@ var VelaWidget = class {
35845
35912
  symbol: this.symbol,
35846
35913
  timeframe: this.timeframe,
35847
35914
  bars: Math.max(this.bars, this.rangeBars),
35915
+ session: this.session,
35848
35916
  volume: this.ledgerVolume ?? chartOpts.volume,
35849
35917
  // A pending range chip frames the FIRST paint (no preview flash, no re-frame).
35850
35918
  ...this.pendingRange ? { visibleRange: this.pendingRange.preset } : {}
@@ -35854,7 +35922,9 @@ var VelaWidget = class {
35854
35922
  this.inner = chart;
35855
35923
  this.symbolPicker.setSource(() => chart.data.symbols());
35856
35924
  void chart.data.ready().then(() => {
35857
- if (this.inner === chart) this.statusline?.setMeta(this.timeframe, this.providerLabel());
35925
+ if (this.inner !== chart) return;
35926
+ this.statusline?.setMeta(this.timeframe, this.providerLabel());
35927
+ this.refreshSessionToggle();
35858
35928
  });
35859
35929
  if (this.layoutCtl !== void 0) chart.renderer.setLayoutMode(this.layoutCtl.current);
35860
35930
  this.objectTree.setSymbol(this.symbol);
@@ -35931,6 +36001,7 @@ var VelaWidget = class {
35931
36001
  this.statusline?.setSymbol(symbol);
35932
36002
  this.objectTree.setSymbol(symbol);
35933
36003
  this.watermark?.update(symbol, this.timeframe);
36004
+ this.refreshSessionToggle();
35934
36005
  }
35935
36006
  if (timeframe !== this.timeframe) this.syncTimeframeChrome(timeframe);
35936
36007
  });
@@ -36228,6 +36299,8 @@ var VelaWidget = class {
36228
36299
  priceStyle: this.priceStyle,
36229
36300
  timezone: this.timezone,
36230
36301
  bars: String(this.bars),
36302
+ // Empty clears the param — the default (regular) keeps links lean.
36303
+ session: this.session === "extended" ? "extended" : "",
36231
36304
  watermark: this.watermarkOn ? "1" : "0",
36232
36305
  favorites: this.favs.join(",")
36233
36306
  });
package/dist/widget.d.cts CHANGED
@@ -1,10 +1,10 @@
1
- import { W as WidgetContext, V as Vela, y as SidePanelButton } from './contributions-Dlc7ZWZz.cjs';
2
- export { ah as DEFAULT_PANEL_ORDER, z as SidePanelDescriptor, A as SidePanelHandle, U as WidgetActionDescriptor, X as WidgetActionTarget, Y as WidgetAttachment, a4 as registerSidePanel, a5 as registerWidgetAction, a6 as registerWidgetAttachment, a8 as sidePanels, ac as unregisterSidePanel, ad as unregisterWidgetAction, ae as unregisterWidgetAttachment, af as widgetActions, ag as widgetAttachments } from './contributions-Dlc7ZWZz.cjs';
3
- import { b as VelaOptions, q as DataWindowReadout } from './options-BlQ00Fju.cjs';
1
+ import { W as WidgetContext, V as Vela, y as SidePanelButton } from './contributions-D64UA74H.cjs';
2
+ export { ah as DEFAULT_PANEL_ORDER, z as SidePanelDescriptor, A as SidePanelHandle, U as WidgetActionDescriptor, X as WidgetActionTarget, Y as WidgetAttachment, a4 as registerSidePanel, a5 as registerWidgetAction, a6 as registerWidgetAttachment, a8 as sidePanels, ac as unregisterSidePanel, ad as unregisterWidgetAction, ae as unregisterWidgetAttachment, af as widgetActions, ag as widgetAttachments } from './contributions-D64UA74H.cjs';
3
+ import { b as VelaOptions, d as MarketSession, r as DataWindowReadout } from './options-BqGeFHtp.cjs';
4
4
  import { K as KeymapManager } from './keymap-CGOz5F5f.cjs';
5
- import { W as WidgetHistory, b as VelaShellOptions, e as WorkspaceState, a as RangePreset, i as PersistedState, P as PanelsState } from './history-BZADxpKx.cjs';
6
- export { B as Bottombar, j as BottombarOptions, C as CellState, f as ChartState, I as IndicatorLoader, k as IndicatorManifest, l as IndicatorManifestEntry, m as RANGE_PRESETS, R as ResolvedIndicator, V as VelaStorage, n as WidgetStorage, g as decodeState, h as encodeState, o as legacyWidgetState, p as loadPersisted, q as localStorageAdapter, r as parsePersisted, t as resolveIndicators, s as sanitizeState, u as savePersisted } from './history-BZADxpKx.cjs';
7
- import { a as SymbolDescriptor } from './DataProvider-Ce6PuCzQ.cjs';
5
+ import { W as WidgetHistory, b as VelaShellOptions, e as WorkspaceState, a as RangePreset, i as PersistedState, P as PanelsState } from './history-fSMXVLt1.cjs';
6
+ export { B as Bottombar, j as BottombarOptions, C as CellState, f as ChartState, I as IndicatorLoader, k as IndicatorManifest, l as IndicatorManifestEntry, m as RANGE_PRESETS, R as ResolvedIndicator, V as VelaStorage, n as WidgetStorage, g as decodeState, h as encodeState, o as legacyWidgetState, p as loadPersisted, q as localStorageAdapter, r as parsePersisted, t as resolveIndicators, s as sanitizeState, u as savePersisted } from './history-fSMXVLt1.cjs';
7
+ import { a as SymbolDescriptor } from './DataProvider-BNKtYU5V.cjs';
8
8
  import { d as SidePanel } from './side-panel-CT9ZwIGz.cjs';
9
9
  export { D as DEFAULT_PANEL_MAX_WIDTH, a as DEFAULT_PANEL_MIN_WIDTH, b as DEFAULT_PANEL_WIDTH, S as SidePanelOptions, c as clampPanelWidth } from './side-panel-CT9ZwIGz.cjs';
10
10
 
@@ -51,6 +51,8 @@ declare class VelaWidget {
51
51
  private priceStyle;
52
52
  private timezone;
53
53
  private bars;
54
+ /** The shown trading session — undefined = the provider default (regular). */
55
+ private session;
54
56
  private watermarkOn;
55
57
  /** Indicator titles (the in-chart legend rows) shown — reapplied across rebuilds. */
56
58
  private indicatorTitlesOn;
@@ -149,6 +151,16 @@ declare class VelaWidget {
149
151
  */
150
152
  private providerLabel;
151
153
  setTimeframe(tf: string): void;
154
+ /**
155
+ * Switch the shown trading session (RTH/ETH) in place — a full reload, like a
156
+ * timeframe change (the two sessions are different bar series). No-op on a chart
157
+ * already showing that session; meaningless on continuous markets (the toggle is
158
+ * disabled there, but the API tolerates the call — the provider ignores the flag).
159
+ */
160
+ setSession(session: MarketSession): void;
161
+ /** Re-derive the RTH/ETH toggle's posture from the ACTIVE symbol's metadata: enabled
162
+ * iff the resolved symbol declares a real session vocabulary (not `24x7`). */
163
+ private refreshSessionToggle;
152
164
  /** Star/unstar a timeframe — the topbar chips and dropdown stars follow, and the
153
165
  * set persists with the rest of the shell state. */
154
166
  private setTimeframeFavorite;
package/dist/widget.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { W as WidgetContext, V as Vela, y as SidePanelButton } from './contributions-DToMhiw3.js';
2
- export { ah as DEFAULT_PANEL_ORDER, z as SidePanelDescriptor, A as SidePanelHandle, U as WidgetActionDescriptor, X as WidgetActionTarget, Y as WidgetAttachment, a4 as registerSidePanel, a5 as registerWidgetAction, a6 as registerWidgetAttachment, a8 as sidePanels, ac as unregisterSidePanel, ad as unregisterWidgetAction, ae as unregisterWidgetAttachment, af as widgetActions, ag as widgetAttachments } from './contributions-DToMhiw3.js';
3
- import { b as VelaOptions, q as DataWindowReadout } from './options-BlQ00Fju.js';
1
+ import { W as WidgetContext, V as Vela, y as SidePanelButton } from './contributions-lPAgo9Cu.js';
2
+ export { ah as DEFAULT_PANEL_ORDER, z as SidePanelDescriptor, A as SidePanelHandle, U as WidgetActionDescriptor, X as WidgetActionTarget, Y as WidgetAttachment, a4 as registerSidePanel, a5 as registerWidgetAction, a6 as registerWidgetAttachment, a8 as sidePanels, ac as unregisterSidePanel, ad as unregisterWidgetAction, ae as unregisterWidgetAttachment, af as widgetActions, ag as widgetAttachments } from './contributions-lPAgo9Cu.js';
3
+ import { b as VelaOptions, d as MarketSession, r as DataWindowReadout } from './options-BqGeFHtp.js';
4
4
  import { K as KeymapManager } from './keymap-CGOz5F5f.js';
5
- import { W as WidgetHistory, b as VelaShellOptions, e as WorkspaceState, a as RangePreset, i as PersistedState, P as PanelsState } from './history-BuHXJZJ2.js';
6
- export { B as Bottombar, j as BottombarOptions, C as CellState, f as ChartState, I as IndicatorLoader, k as IndicatorManifest, l as IndicatorManifestEntry, m as RANGE_PRESETS, R as ResolvedIndicator, V as VelaStorage, n as WidgetStorage, g as decodeState, h as encodeState, o as legacyWidgetState, p as loadPersisted, q as localStorageAdapter, r as parsePersisted, t as resolveIndicators, s as sanitizeState, u as savePersisted } from './history-BuHXJZJ2.js';
7
- import { a as SymbolDescriptor } from './DataProvider-DNx9ntBD.js';
5
+ import { W as WidgetHistory, b as VelaShellOptions, e as WorkspaceState, a as RangePreset, i as PersistedState, P as PanelsState } from './history-CVoFDJ2D.js';
6
+ export { B as Bottombar, j as BottombarOptions, C as CellState, f as ChartState, I as IndicatorLoader, k as IndicatorManifest, l as IndicatorManifestEntry, m as RANGE_PRESETS, R as ResolvedIndicator, V as VelaStorage, n as WidgetStorage, g as decodeState, h as encodeState, o as legacyWidgetState, p as loadPersisted, q as localStorageAdapter, r as parsePersisted, t as resolveIndicators, s as sanitizeState, u as savePersisted } from './history-CVoFDJ2D.js';
7
+ import { a as SymbolDescriptor } from './DataProvider-gJjN_0eh.js';
8
8
  import { d as SidePanel } from './side-panel-CT9ZwIGz.js';
9
9
  export { D as DEFAULT_PANEL_MAX_WIDTH, a as DEFAULT_PANEL_MIN_WIDTH, b as DEFAULT_PANEL_WIDTH, S as SidePanelOptions, c as clampPanelWidth } from './side-panel-CT9ZwIGz.js';
10
10
 
@@ -51,6 +51,8 @@ declare class VelaWidget {
51
51
  private priceStyle;
52
52
  private timezone;
53
53
  private bars;
54
+ /** The shown trading session — undefined = the provider default (regular). */
55
+ private session;
54
56
  private watermarkOn;
55
57
  /** Indicator titles (the in-chart legend rows) shown — reapplied across rebuilds. */
56
58
  private indicatorTitlesOn;
@@ -149,6 +151,16 @@ declare class VelaWidget {
149
151
  */
150
152
  private providerLabel;
151
153
  setTimeframe(tf: string): void;
154
+ /**
155
+ * Switch the shown trading session (RTH/ETH) in place — a full reload, like a
156
+ * timeframe change (the two sessions are different bar series). No-op on a chart
157
+ * already showing that session; meaningless on continuous markets (the toggle is
158
+ * disabled there, but the API tolerates the call — the provider ignores the flag).
159
+ */
160
+ setSession(session: MarketSession): void;
161
+ /** Re-derive the RTH/ETH toggle's posture from the ACTIVE symbol's metadata: enabled
162
+ * iff the resolved symbol declares a real session vocabulary (not `24x7`). */
163
+ private refreshSessionToggle;
152
164
  /** Star/unstar a timeframe — the topbar chips and dropdown stars follow, and the
153
165
  * set persists with the rest of the shell state. */
154
166
  private setTimeframeFavorite;
package/dist/widget.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Glider, WidgetHistory, localStorageAdapter, decodeState, prefixedSymbol, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, ChartContextMenu, Toast, Watermark, Statusline, Bottombar, MobileBar, DrawingPill, LayoutModeController, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, indicatorLedger, sanitizeState, legacyWidgetState, parsePersisted, statuslineInkOf, toolShortcutHints, resolveIndicators, encodeState } from './chunk-7ROONW6H.js';
2
- export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, legacyWidgetState, loadPersisted, localStorageAdapter, parsePersisted, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, timeframeLabel, timeframeMs } from './chunk-7ROONW6H.js';
3
- import { registerBuiltinChartTypes, resolveTheme, parseSymbol, buildToolbar, priceStyleIds, Vela, normalizeTimezone } from './chunk-CA3N3PYT.js';
4
- export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-CA3N3PYT.js';
1
+ import { Glider, WidgetHistory, localStorageAdapter, decodeState, prefixedSymbol, normalizeSession, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, ChartContextMenu, Toast, Watermark, Statusline, Bottombar, MobileBar, DrawingPill, LayoutModeController, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, indicatorLedger, sanitizeState, legacyWidgetState, parsePersisted, statuslineInkOf, toolShortcutHints, resolveIndicators, encodeState } from './chunk-6LZJRO2S.js';
2
+ export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, legacyWidgetState, loadPersisted, localStorageAdapter, parsePersisted, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, timeframeLabel, timeframeMs } from './chunk-6LZJRO2S.js';
3
+ import { registerBuiltinChartTypes, resolveTheme, parseSymbol, buildToolbar, priceStyleIds, Vela, normalizeTimezone } from './chunk-4MQEG67Z.js';
4
+ export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-4MQEG67Z.js';
5
5
  import { widgetActions, widgetAttachments, legendActionsProviderFor, resolveEngines } from './chunk-ZNL2X6U2.js';
6
6
  export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, SidePanel, clampPanelWidth, registerSidePanel, registerWidgetAction, registerWidgetAttachment, sidePanels, unregisterSidePanel, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-ZNL2X6U2.js';
7
7
  import { KeymapManager, Menu, isEditableTarget } from './chunk-QWIEKZRE.js';
@@ -14,7 +14,8 @@ var PARAMS = [
14
14
  ["timeframe", "interval"],
15
15
  ["priceStyle", "style"],
16
16
  ["timezone", "tz"],
17
- ["bars", "bars"]
17
+ ["bars", "bars"],
18
+ ["session", "session"]
18
19
  ];
19
20
  function readUrlState(search) {
20
21
  const out = {};
@@ -146,6 +147,7 @@ var VelaWidget = class {
146
147
  this.priceStyle = fromUrl.priceStyle ?? bootCell?.priceStyle ?? opts.priceStyle ?? "candles";
147
148
  this.timezone = fromUrl.timezone ?? boot?.timezone ?? opts.timezone ?? "Etc/UTC";
148
149
  this.bars = Number(fromUrl.bars ?? bootCell?.bars ?? opts.bars ?? 1e3);
150
+ this.session = normalizeSession(fromUrl.session ?? bootCell?.session ?? opts.session);
149
151
  this.watermarkOn = bootCell?.watermark !== void 0 ? bootCell.watermark : opts.watermark !== false;
150
152
  this.indicatorTitlesOn = bootCell?.indicatorTitles ?? true;
151
153
  this.indicatorValuesOn = bootCell?.indicatorValues ?? true;
@@ -252,6 +254,7 @@ var VelaWidget = class {
252
254
  timezone: this.timezone,
253
255
  onRange: (preset) => this.applyRange(preset),
254
256
  onTimezone: (zone) => this.setTimezone(zone),
257
+ onSession: (session) => this.setSession(session),
255
258
  onSettingsClick: () => this.inner?.renderer.openSettings()
256
259
  }) : null;
257
260
  this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
@@ -500,6 +503,30 @@ var VelaWidget = class {
500
503
  this.markStateDirty();
501
504
  void this.inner?.setMarket({ timeframe: tf, bars: this.bars });
502
505
  }
506
+ /**
507
+ * Switch the shown trading session (RTH/ETH) in place — a full reload, like a
508
+ * timeframe change (the two sessions are different bar series). No-op on a chart
509
+ * already showing that session; meaningless on continuous markets (the toggle is
510
+ * disabled there, but the API tolerates the call — the provider ignores the flag).
511
+ */
512
+ setSession(session) {
513
+ if (session === this.session || session === "regular" && this.session === void 0 || this.destroyed) return;
514
+ this.session = session;
515
+ this.refreshSessionToggle();
516
+ this.markStateDirty();
517
+ void this.inner?.setMarket({ session });
518
+ }
519
+ /** Re-derive the RTH/ETH toggle's posture from the ACTIVE symbol's metadata: enabled
520
+ * iff the resolved symbol declares a real session vocabulary (not `24x7`). */
521
+ refreshSessionToggle() {
522
+ const chart = this.inner;
523
+ if (!chart || !this.bottombar) return;
524
+ void chart.data.symbolInfo(this.symbol).then((si) => {
525
+ if (this.destroyed || this.inner !== chart) return;
526
+ const enabled = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
527
+ this.bottombar?.setSession({ session: this.session ?? "regular", enabled });
528
+ });
529
+ }
503
530
  /** Star/unstar a timeframe — the topbar chips and dropdown stars follow, and the
504
531
  * set persists with the rest of the shell state. */
505
532
  setTimeframeFavorite(tf, on) {
@@ -546,6 +573,8 @@ var VelaWidget = class {
546
573
  cell.timeframe = live?.timeframe ?? this.timeframe;
547
574
  cell.priceStyle = this.priceStyle;
548
575
  if (this.bars > 0) cell.bars = this.bars;
576
+ const session = normalizeSession(live?.session ?? this.session);
577
+ if (session === "extended") cell.session = session;
549
578
  cell.watermark = this.watermarkOn;
550
579
  cell.indicatorTitles = this.indicatorTitlesOn;
551
580
  cell.indicatorValues = this.indicatorValuesOn;
@@ -612,9 +641,15 @@ var VelaWidget = class {
612
641
  const symbol = fromUrl.symbol ?? prefixedSymbol(cell);
613
642
  const timeframe = fromUrl.timeframe ?? cell.timeframe;
614
643
  const bars = Number(fromUrl.bars ?? cell.bars ?? 0);
644
+ const session = normalizeSession(fromUrl.session ?? cell.session);
615
645
  const next = {};
616
646
  if (symbol && symbol !== this.symbol) next.symbol = symbol;
617
647
  if (timeframe && timeframe !== this.timeframe) next.timeframe = timeframe;
648
+ if (session && session !== (this.session ?? "regular")) {
649
+ this.session = session;
650
+ next.session = session;
651
+ this.refreshSessionToggle();
652
+ }
618
653
  if (bars > 0 && bars !== this.bars) {
619
654
  this.bars = bars;
620
655
  next.bars = Math.max(bars, this.rangeBars);
@@ -841,6 +876,7 @@ var VelaWidget = class {
841
876
  symbol: this.symbol,
842
877
  timeframe: this.timeframe,
843
878
  bars: Math.max(this.bars, this.rangeBars),
879
+ session: this.session,
844
880
  volume: this.ledgerVolume ?? chartOpts.volume,
845
881
  // A pending range chip frames the FIRST paint (no preview flash, no re-frame).
846
882
  ...this.pendingRange ? { visibleRange: this.pendingRange.preset } : {}
@@ -850,7 +886,9 @@ var VelaWidget = class {
850
886
  this.inner = chart;
851
887
  this.symbolPicker.setSource(() => chart.data.symbols());
852
888
  void chart.data.ready().then(() => {
853
- if (this.inner === chart) this.statusline?.setMeta(this.timeframe, this.providerLabel());
889
+ if (this.inner !== chart) return;
890
+ this.statusline?.setMeta(this.timeframe, this.providerLabel());
891
+ this.refreshSessionToggle();
854
892
  });
855
893
  if (this.layoutCtl !== void 0) chart.renderer.setLayoutMode(this.layoutCtl.current);
856
894
  this.objectTree.setSymbol(this.symbol);
@@ -927,6 +965,7 @@ var VelaWidget = class {
927
965
  this.statusline?.setSymbol(symbol);
928
966
  this.objectTree.setSymbol(symbol);
929
967
  this.watermark?.update(symbol, this.timeframe);
968
+ this.refreshSessionToggle();
930
969
  }
931
970
  if (timeframe !== this.timeframe) this.syncTimeframeChrome(timeframe);
932
971
  });
@@ -1224,6 +1263,8 @@ var VelaWidget = class {
1224
1263
  priceStyle: this.priceStyle,
1225
1264
  timezone: this.timezone,
1226
1265
  bars: String(this.bars),
1266
+ // Empty clears the param — the default (regular) keeps links lean.
1267
+ session: this.session === "extended" ? "extended" : "",
1227
1268
  watermark: this.watermarkOn ? "1" : "0",
1228
1269
  favorites: this.favs.join(",")
1229
1270
  });