@luxalgo/vela 0.6.11 → 0.6.12

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 (41) hide show
  1. package/README.md +110 -46
  2. package/dist/{DataProvider-BBf-jc6W.d.ts → DataProvider-DhzstpQb.d.ts} +1 -1
  3. package/dist/{DataProvider-p0TEyhlX.d.cts → DataProvider-DlMtrwqM.d.cts} +1 -1
  4. package/dist/{chunk-MTLJKZDZ.js → chunk-F4M24ANM.js} +122 -1
  5. package/dist/{chunk-IO3NYSQV.js → chunk-IZV3CW5N.js} +184 -25
  6. package/dist/{chunk-73PEA4MU.js → chunk-KV7FDWSL.js} +618 -38
  7. package/dist/{contributions-Bbe2R-mQ.d.ts → contributions-37nni40G.d.ts} +6 -4
  8. package/dist/{contributions-CO01zWve.d.cts → contributions-lPojhTxI.d.cts} +6 -4
  9. package/dist/index.cjs +727 -26
  10. package/dist/index.d.cts +6 -6
  11. package/dist/index.d.ts +6 -6
  12. package/dist/index.js +2 -2
  13. package/dist/{options-yp7sA96q.d.cts → options-CYS5Wmlx.d.cts} +71 -2
  14. package/dist/{options-yp7sA96q.d.ts → options-CYS5Wmlx.d.ts} +71 -2
  15. package/dist/{plugin-CkkH8QnX.d.cts → plugin-Cwikpz1m.d.cts} +10 -3
  16. package/dist/{plugin-DwxjM3Ni.d.ts → plugin-DHyaoMjW.d.ts} +10 -3
  17. package/dist/plugin.cjs +110 -0
  18. package/dist/plugin.d.cts +4 -4
  19. package/dist/plugin.d.ts +4 -4
  20. package/dist/plugin.js +1 -1
  21. package/dist/providers/binance.d.cts +2 -2
  22. package/dist/providers/binance.d.ts +2 -2
  23. package/dist/providers/coinbase.d.cts +2 -2
  24. package/dist/providers/coinbase.d.ts +2 -2
  25. package/dist/providers/hyperliquid.d.cts +2 -2
  26. package/dist/providers/hyperliquid.d.ts +2 -2
  27. package/dist/{statusline-CHPDuKNp.d.ts → statusline-model-CiJm-riV.d.cts} +7 -85
  28. package/dist/{statusline-DTHZUFqK.d.cts → statusline-model-D-q_OOx9.d.ts} +7 -85
  29. package/dist/ui.d.cts +1 -1
  30. package/dist/ui.d.ts +1 -1
  31. package/dist/vela.global.js +727 -26
  32. package/dist/vela.global.min.js +52 -52
  33. package/dist/widget.cjs +910 -50
  34. package/dist/widget.d.cts +118 -7
  35. package/dist/widget.d.ts +118 -7
  36. package/dist/widget.js +4 -4
  37. package/dist/workspace.cjs +910 -50
  38. package/dist/workspace.d.cts +5 -5
  39. package/dist/workspace.d.ts +5 -5
  40. package/dist/workspace.js +3 -3
  41. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
- import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-73PEA4MU.js';
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-MTLJKZDZ.js';
1
+ import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-KV7FDWSL.js';
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-F4M24ANM.js';
3
3
  import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-G77Y7LK2.js';
4
4
  import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-MHY7MVXH.js';
5
- import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-KG4YT3TI.js';
5
+ import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-KG4YT3TI.js';
6
6
  import { baseOf } from './chunk-W4EJWLEO.js';
7
7
 
8
8
  // src/widget/timeframe.ts
@@ -3988,6 +3988,21 @@ function fmtChange(open, close) {
3988
3988
  return `${sign}${fmtPrice(diff, decimalsFor(close))} (${sign}${pct.toFixed(2)}%)`;
3989
3989
  }
3990
3990
 
3991
+ // src/widget/statusline-model.ts
3992
+ function segmentVisibility(parts, chartHidden = false) {
3993
+ return { avatar: parts.logo, symbol: parts.name, meta: parts.name, market: parts.market, ohlc: parts.ohlc && !chartHidden, change: parts.change && !chartHidden, eye: chartHidden };
3994
+ }
3995
+ function statuslineMenuItems(parts, chartVisible) {
3996
+ return [
3997
+ { id: "part:logo", label: "Symbol logo", checked: parts.logo },
3998
+ { id: "part:name", label: "Symbol name", checked: parts.name },
3999
+ { id: "part:market", label: "Market status", checked: parts.market },
4000
+ { id: "part:ohlc", label: "OHLC values", checked: parts.ohlc },
4001
+ { id: "part:change", label: "Bar change values", checked: parts.change },
4002
+ { id: "chart", label: chartVisible ? "Hide chart" : "Show chart", separatorBefore: true }
4003
+ ];
4004
+ }
4005
+
3991
4006
  // src/widget/statusline.ts
3992
4007
  var STYLE_ID10 = "vela-widget-statusline";
3993
4008
  var CSS10 = `
@@ -4017,7 +4032,13 @@ var CSS10 = `
4017
4032
  padding: 2px 7px;
4018
4033
  margin-left: -7px;
4019
4034
  }
4020
- .vela-statusline:hover { background: var(--vela-bg); }
4035
+ /* Hovering opens the chip the same way a legend row opens: solid chart background
4036
+ * plus the same inset neutral outline the indicator rows wear (InputsUI's
4037
+ * setRowHighlighted) \u2014 the two columns read as one family. */
4038
+ .vela-statusline:hover { background: var(--vela-bg); box-shadow: inset 0 0 0 1px var(--vela-border); }
4039
+ /* Chart hidden (the price series' eye \u2014 renderer 'candleVisible'): the line dims to
4040
+ * the same 0.5 wash a hidden indicator's legend row wears. */
4041
+ .vela-statusline.vela-sl-chart-hidden { opacity: 0.5; }
4021
4042
  .vela-statusline .vela-sl-avatar {
4022
4043
  width: 18px;
4023
4044
  height: 18px;
@@ -4042,6 +4063,24 @@ var CSS10 = `
4042
4063
  * these are the pre-ink fallbacks only. */
4043
4064
  .vela-statusline .vela-sl-change[data-dir='up'] { color: var(--vela-up); }
4044
4065
  .vela-statusline .vela-sl-change[data-dir='down'] { color: var(--vela-down); }
4066
+ /* The show-chart eye \u2014 out only while the chart is hidden (syncParts drives display),
4067
+ * replacing the value readout it took away. Same footprint as a legend action button. */
4068
+ .vela-statusline .vela-sl-eye {
4069
+ align-self: center;
4070
+ align-items: center;
4071
+ justify-content: center;
4072
+ width: 18px;
4073
+ height: 18px;
4074
+ padding: 0;
4075
+ border: none;
4076
+ border-radius: 3px;
4077
+ background: none;
4078
+ color: var(--vela-fg-muted);
4079
+ cursor: pointer;
4080
+ line-height: 0;
4081
+ flex: none;
4082
+ }
4083
+ .vela-statusline .vela-sl-eye:hover { color: var(--vela-fg); background: color-mix(in srgb, var(--vela-fg) 12%, transparent); }
4045
4084
  /* Stack the TOP pane's legend below the status line (lower study panes stay put).
4046
4085
  * The renderer marks whichever legend sits at the plot's top edge \u2014 the price pane
4047
4086
  * normally, or a maximized study pane filling the plot \u2014 so the legend never merges
@@ -4151,7 +4190,12 @@ var Statusline = class {
4151
4190
  constructor(host, symbol, iconFor) {
4152
4191
  this.host = host;
4153
4192
  this.iconFor = iconFor;
4154
- this.parts = { name: true, market: true, ohlc: true, change: true };
4193
+ this.parts = { logo: true, name: true, market: true, ohlc: true, change: true };
4194
+ /** The right-click action menu — present once a host wires it via {@link attachMenu}. */
4195
+ this.menu = null;
4196
+ this.menuHooks = null;
4197
+ /** Mirror of the renderer's `candleVisible` — see {@link setChartHidden}. */
4198
+ this.chartHidden = false;
4155
4199
  this.lastBar = null;
4156
4200
  this.hoverBar = null;
4157
4201
  this.unsubs = [];
@@ -4167,6 +4211,15 @@ var Statusline = class {
4167
4211
  /** Fit mode (multi-chart cells): one row, overflowing segments hidden — see {@link setFitMode}. */
4168
4212
  this.fitMode = false;
4169
4213
  this.fitRO = null;
4214
+ this.onContextMenu = (e) => {
4215
+ if (!this.menu || !this.menuHooks) return;
4216
+ e.preventDefault();
4217
+ e.stopPropagation();
4218
+ const chartVisible = this.menuHooks.chartVisible();
4219
+ this.setChartHidden(!chartVisible);
4220
+ this.menu.setItems(statuslineMenuItems(this.parts, chartVisible));
4221
+ this.menu.openAt(e.clientX, e.clientY);
4222
+ };
4170
4223
  const doc = host.ownerDocument;
4171
4224
  injectStyles(STYLE_ID10, CSS10, doc);
4172
4225
  host.classList.add("vela-has-statusline");
@@ -4193,9 +4246,21 @@ var Statusline = class {
4193
4246
  this.ohlcEl.className = "vela-sl-ohlc";
4194
4247
  this.changeEl = doc.createElement("span");
4195
4248
  this.changeEl.className = "vela-sl-change";
4196
- this.el.append(this.avatarEl, this.symbolEl, this.metaEl, this.marketEl, this.ohlcEl, this.changeEl);
4249
+ this.eyeEl = doc.createElement("button");
4250
+ this.eyeEl.type = "button";
4251
+ this.eyeEl.className = "vela-sl-eye";
4252
+ this.eyeEl.innerHTML = iconAt("eye-off", 14);
4253
+ this.eyeEl.setAttribute("aria-label", "Show chart");
4254
+ this.eyeEl.style.display = "none";
4255
+ this.eyeEl.addEventListener("click", (e) => {
4256
+ e.stopPropagation();
4257
+ this.menuHooks?.setChartVisible(true);
4258
+ this.setChartHidden(false);
4259
+ });
4260
+ this.el.append(this.avatarEl, this.symbolEl, this.metaEl, this.marketEl, this.ohlcEl, this.changeEl, this.eyeEl);
4197
4261
  host.appendChild(this.el);
4198
4262
  this.marketTip = new Tooltip(this.marketEl, { content: MARKET_LABELS.open, placement: "bottom" });
4263
+ this.eyeTip = new Tooltip(this.eyeEl, { content: "Show chart", placement: "bottom" });
4199
4264
  this.setMarketStatus("open");
4200
4265
  this.render();
4201
4266
  }
@@ -4205,6 +4270,7 @@ var Statusline = class {
4205
4270
  const fresh = tickerIconEl(this.el.ownerDocument, baseOfTicker(ticker), ticker, "vela-sl-avatar", this.iconFor?.(symbol));
4206
4271
  this.avatarEl.replaceWith(fresh);
4207
4272
  this.avatarEl = fresh;
4273
+ this.syncParts();
4208
4274
  this.fit();
4209
4275
  }
4210
4276
  /**
@@ -4232,20 +4298,25 @@ var Statusline = class {
4232
4298
  }
4233
4299
  /** Project the parts config onto the segments (the baseline fit() prunes from). */
4234
4300
  syncParts() {
4235
- this.symbolEl.style.display = this.parts.name ? "" : "none";
4236
- this.marketEl.style.display = this.parts.market ? "" : "none";
4237
- this.ohlcEl.style.display = this.parts.ohlc ? "" : "none";
4238
- this.changeEl.style.display = this.parts.change ? "" : "none";
4301
+ const seg = segmentVisibility(this.parts, this.chartHidden);
4302
+ this.avatarEl.style.display = seg.avatar ? "" : "none";
4303
+ this.symbolEl.style.display = seg.symbol ? "" : "none";
4304
+ this.metaEl.style.display = seg.meta ? "" : "none";
4305
+ this.marketEl.style.display = seg.market ? "" : "none";
4306
+ this.ohlcEl.style.display = seg.ohlc ? "" : "none";
4307
+ this.changeEl.style.display = seg.change ? "" : "none";
4308
+ this.eyeEl.style.display = seg.eye ? "inline-flex" : "none";
4239
4309
  }
4240
4310
  /** Hide overflowing segments until the row fits its max-width (fit mode only). */
4241
4311
  fit() {
4242
4312
  if (!this.fitMode) return;
4243
4313
  this.syncParts();
4314
+ const seg = segmentVisibility(this.parts, this.chartHidden);
4244
4315
  const order = [
4245
- [this.ohlcEl, this.parts.ohlc],
4246
- [this.changeEl, this.parts.change],
4247
- [this.metaEl, true],
4248
- [this.marketEl, this.parts.market]
4316
+ [this.ohlcEl, seg.ohlc],
4317
+ [this.changeEl, seg.change],
4318
+ [this.metaEl, seg.meta],
4319
+ [this.marketEl, seg.market]
4249
4320
  ];
4250
4321
  for (const [el, shown] of order) {
4251
4322
  if (this.el.scrollWidth <= this.el.clientWidth) break;
@@ -4266,7 +4337,6 @@ var Statusline = class {
4266
4337
  this.readout = readout;
4267
4338
  this.render();
4268
4339
  }
4269
- /** Show/hide one part (the settings dialog's Status line tab drives these). */
4270
4340
  /** The "· BINANCE · 1h" segment after the symbol — venue first, then resolution. */
4271
4341
  setMeta(timeframe, provider) {
4272
4342
  this.metaEl.textContent = `${provider ? `\xB7 ${provider.toUpperCase()} ` : ""}\xB7 ${timeframeLabel(timeframe)}`;
@@ -4285,6 +4355,9 @@ var Statusline = class {
4285
4355
  });
4286
4356
  this.marketTip.setContent(MARKET_LABELS[status]);
4287
4357
  }
4358
+ /** Show/hide one part — the settings dialog's Status line tab and the right-click
4359
+ * menu both drive these. 'name' owns the venue/timeframe meta too (see
4360
+ * {@link segmentVisibility}). */
4288
4361
  setPartVisible(part, visible) {
4289
4362
  this.parts[part] = visible;
4290
4363
  this.syncParts();
@@ -4293,6 +4366,47 @@ var Statusline = class {
4293
4366
  partVisible(part) {
4294
4367
  return this.parts[part];
4295
4368
  }
4369
+ /** Mirror the chart's (price series') visibility: dim the whole line like a hidden
4370
+ * indicator's legend row, drop the value readout (OHLC + bar change — values of a
4371
+ * series that isn't painted), and put the show-chart eye out in its place. The
4372
+ * parts config is untouched, so showing the chart restores the readout exactly as
4373
+ * configured. Idempotent; {@link render} re-syncs it from the live renderer, so
4374
+ * toggles made elsewhere (the object tree's eye) converge too. */
4375
+ setChartHidden(hidden) {
4376
+ if (hidden === this.chartHidden) return;
4377
+ this.chartHidden = hidden;
4378
+ this.el.classList.toggle("vela-sl-chart-hidden", hidden);
4379
+ this.syncParts();
4380
+ this.fit();
4381
+ }
4382
+ /** Wire the right-click action menu: one checkable toggle per part plus hide/show
4383
+ * for the chart itself. The menu is built once; later calls just swap the hooks. */
4384
+ attachMenu(hooks) {
4385
+ this.menuHooks = hooks;
4386
+ if (this.menu) return;
4387
+ this.menu = new Menu({
4388
+ host: this.host,
4389
+ items: [],
4390
+ placement: "bottom-start",
4391
+ // Pointer-anchored action menu — checked state reads as a leading ✓ (the
4392
+ // same shape as the chart's own context menu).
4393
+ checkmarks: true,
4394
+ onSelect: (id) => this.runMenuItem(id)
4395
+ });
4396
+ this.el.addEventListener("contextmenu", this.onContextMenu);
4397
+ }
4398
+ runMenuItem(id) {
4399
+ const hooks = this.menuHooks;
4400
+ if (!hooks) return;
4401
+ if (id.startsWith("part:")) {
4402
+ const part = id.slice("part:".length);
4403
+ hooks.setPart(part, !this.parts[part]);
4404
+ } else if (id === "chart") {
4405
+ const next = !hooks.chartVisible();
4406
+ hooks.setChartVisible(next);
4407
+ this.setChartHidden(!next);
4408
+ }
4409
+ }
4296
4410
  /** (Re)bind to a chart instance — called after every widget rebuild. */
4297
4411
  onChart(chart) {
4298
4412
  this.detach();
@@ -4314,7 +4428,11 @@ var Statusline = class {
4314
4428
  this.detach();
4315
4429
  this.fitRO?.disconnect();
4316
4430
  this.fitRO = null;
4431
+ this.el.removeEventListener("contextmenu", this.onContextMenu);
4432
+ this.menu?.destroy();
4433
+ this.menu = null;
4317
4434
  this.marketTip.destroy();
4435
+ this.eyeTip.destroy();
4318
4436
  this.marketBubble.destroy();
4319
4437
  this.host.classList.remove("vela-has-statusline", "vela-sl-fit-host");
4320
4438
  this.el.remove();
@@ -4324,6 +4442,7 @@ var Statusline = class {
4324
4442
  this.unsubs = [];
4325
4443
  }
4326
4444
  render() {
4445
+ if (this.menuHooks) this.setChartHidden(!this.menuHooks.chartVisible());
4327
4446
  const bar = this.hoverBar ?? this.lastBar;
4328
4447
  if (!bar) {
4329
4448
  this.ohlcEl.replaceChildren();
@@ -5304,7 +5423,14 @@ var ChartCell = class {
5304
5423
  this.destroyed = false;
5305
5424
  this.appTheme = deps.theme;
5306
5425
  const symbol = prefixedSymbol(seed);
5307
- this.state = { symbol, provider: parseSymbol(symbol ?? "").provider ?? void 0, timeframe: seed.timeframe, priceStyle: seed.priceStyle, bars: seed.bars, session: normalizeSession(seed.session) };
5426
+ this.state = {
5427
+ symbol,
5428
+ provider: parseSymbol(symbol ?? "").provider ?? void 0,
5429
+ timeframe: seed.timeframe,
5430
+ priceStyle: seed.priceStyle,
5431
+ bars: seed.bars,
5432
+ session: normalizeSession(seed.session)
5433
+ };
5308
5434
  const doc = gridHost.ownerDocument;
5309
5435
  this.host = doc.createElement("div");
5310
5436
  this.host.className = "vela-cell";
@@ -5392,6 +5518,11 @@ var ChartCell = class {
5392
5518
  this.statusline = deps.statusline ? new Statusline(this.host, symbol ?? "", (sym) => this.inner?.data.symbolIcon(sym)) : null;
5393
5519
  this.statusline?.setMeta(seed.timeframe ?? "60", this.state.provider ?? "");
5394
5520
  this.statusline?.onChart(this.inner);
5521
+ this.statusline?.attachMenu({
5522
+ setPart: (part, visible) => this.setStatuslinePart(part, visible),
5523
+ chartVisible: () => this.inner?.renderer.get("candleVisible") !== false,
5524
+ setChartVisible: (visible) => this.inner?.renderer.set("candleVisible", visible)
5525
+ });
5395
5526
  this.marketStatus = this.statusline ? new MarketStatusTracker((s) => this.statusline?.setMarketStatus(s)) : null;
5396
5527
  void this.inner.data.ready().then(() => {
5397
5528
  if (this.inner && this.state.symbol) {
@@ -5599,7 +5730,7 @@ var ChartCell = class {
5599
5730
  kind: "select",
5600
5731
  label: "Bars to fetch",
5601
5732
  id: "bars",
5602
- options: ["500", "1000", "2000", "5000", "10000", "20000"],
5733
+ options: ["500", "1000", "2000", "5000", "10000", "20000", "50000", "60000", "80000", "100000"],
5603
5734
  get: () => String(this.state.bars ?? 1e3),
5604
5735
  set: (v) => {
5605
5736
  this.state.bars = Number(v);
@@ -5631,10 +5762,34 @@ var ChartCell = class {
5631
5762
  id: "status-line",
5632
5763
  rows: [
5633
5764
  { kind: "heading", label: "Status line", id: "parts" },
5634
- { kind: "toggle", label: "Symbol name", id: "name", get: () => sl.partVisible("name"), set: (v) => this.setStatuslinePart("name", v) },
5635
- { kind: "toggle", label: "Market status", id: "market", get: () => sl.partVisible("market"), set: (v) => this.setStatuslinePart("market", v) },
5636
- { kind: "toggle", label: "OHLC values", id: "ohlc", get: () => sl.partVisible("ohlc"), set: (v) => this.setStatuslinePart("ohlc", v) },
5637
- { kind: "toggle", label: "Bar change values", id: "change", get: () => sl.partVisible("change"), set: (v) => this.setStatuslinePart("change", v) },
5765
+ {
5766
+ kind: "toggle",
5767
+ label: "Symbol name",
5768
+ id: "name",
5769
+ get: () => sl.partVisible("name"),
5770
+ set: (v) => this.setStatuslinePart("name", v)
5771
+ },
5772
+ {
5773
+ kind: "toggle",
5774
+ label: "Market status",
5775
+ id: "market",
5776
+ get: () => sl.partVisible("market"),
5777
+ set: (v) => this.setStatuslinePart("market", v)
5778
+ },
5779
+ {
5780
+ kind: "toggle",
5781
+ label: "OHLC values",
5782
+ id: "ohlc",
5783
+ get: () => sl.partVisible("ohlc"),
5784
+ set: (v) => this.setStatuslinePart("ohlc", v)
5785
+ },
5786
+ {
5787
+ kind: "toggle",
5788
+ label: "Bar change values",
5789
+ id: "change",
5790
+ get: () => sl.partVisible("change"),
5791
+ set: (v) => this.setStatuslinePart("change", v)
5792
+ },
5638
5793
  { kind: "heading", label: "Indicators", id: "indicators" },
5639
5794
  {
5640
5795
  kind: "toggle",
@@ -5687,7 +5842,7 @@ var ChartCell = class {
5687
5842
  statusPrefs() {
5688
5843
  const sl = this.statusline;
5689
5844
  return {
5690
- parts: sl ? { name: sl.partVisible("name"), market: sl.partVisible("market"), ohlc: sl.partVisible("ohlc"), change: sl.partVisible("change") } : null,
5845
+ parts: sl ? { logo: sl.partVisible("logo"), name: sl.partVisible("name"), market: sl.partVisible("market"), ohlc: sl.partVisible("ohlc"), change: sl.partVisible("change") } : null,
5691
5846
  indicatorTitles: this.indicatorTitlesOn,
5692
5847
  indicatorValues: this.indicatorValuesOn
5693
5848
  };
@@ -5861,7 +6016,8 @@ var ChartCell = class {
5861
6016
  if (this.manifest.length > 0) {
5862
6017
  for (const item of led.manifest) {
5863
6018
  const entry = this.manifest.find((e) => e.name === ledgerEntryName(item));
5864
- if (entry) this.addManifestInstance(entry, { record: false, ...typeof item === "object" ? { inputs: item.inputs, props: item.props } : {} });
6019
+ if (entry)
6020
+ this.addManifestInstance(entry, { record: false, ...typeof item === "object" ? { inputs: item.inputs, props: item.props } : {} });
5865
6021
  }
5866
6022
  this.pendingManifestNames = null;
5867
6023
  } else if (!this.deps.manifestSettled()) {
@@ -5910,7 +6066,10 @@ var ChartCell = class {
5910
6066
  * a persistence handler's `restore` runs silently, a user-driven call records.
5911
6067
  */
5912
6068
  addExternalIndicator(entry) {
5913
- this.addManifestInstance({ ...entry, enabled: true }, { external: true, ...entry.inputs ? { inputs: entry.inputs } : {}, ...entry.props ? { props: entry.props } : {} });
6069
+ this.addManifestInstance(
6070
+ { ...entry, enabled: true },
6071
+ { external: true, ...entry.inputs ? { inputs: entry.inputs } : {}, ...entry.props ? { props: entry.props } : {} }
6072
+ );
5914
6073
  }
5915
6074
  /** Add ONE instance of a manifest entry (repeatable — duplicates are legitimate). */
5916
6075
  addManifestInstance(entry, opts = {}) {
@@ -7661,7 +7820,7 @@ function buildContext(host) {
7661
7820
  }
7662
7821
 
7663
7822
  // src/workspace/VelaWorkspace.ts
7664
- var DEFAULT_TIMEFRAMES = ["1", "5", "15", "60", "240", "D", "W"];
7823
+ var DEFAULT_TIMEFRAMES = ["1", "5", "15", "30", "60", "240", "D", "W", "M"];
7665
7824
  var GAP_PX = 2;
7666
7825
  var POOL_CAP = 16;
7667
7826
  var TIME_AXIS_H3 = 22;