@luxalgo/vela 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/NOTICE +1 -1
  2. package/README.md +16 -8
  3. package/dist/{DataProvider-BrlxntPN.d.cts → DataProvider-COGDs9Xg.d.cts} +1 -1
  4. package/dist/{DataProvider-DwFIoV4r.d.ts → DataProvider-DpOWZD8F.d.ts} +1 -1
  5. package/dist/{chunk-KA77UTRF.js → chunk-27UTYE7T.js} +25 -2
  6. package/dist/{chunk-EZ5FWVLA.js → chunk-DPAA3SRT.js} +94 -13
  7. package/dist/{chunk-BZQM2XO7.js → chunk-HKNO24GD.js} +13 -1
  8. package/dist/{chunk-2IAETM2I.js → chunk-NLDTVFOI.js} +79 -6
  9. package/dist/{chunk-E3GU6AUI.js → chunk-R2JMNIHY.js} +68 -23
  10. package/dist/{chunk-QBPUT5SU.js → chunk-T3DZIR5Y.js} +211 -54
  11. package/dist/{contributions-tjNExo1o.d.ts → contributions-Cgm9RJYP.d.cts} +38 -11
  12. package/dist/{contributions-CtlptxR8.d.cts → contributions-bWgwyiVi.d.ts} +38 -11
  13. package/dist/index.cjs +317 -62
  14. package/dist/index.d.cts +8 -8
  15. package/dist/index.d.ts +8 -8
  16. package/dist/index.js +4 -4
  17. package/dist/{options-BnEPUuVV.d.ts → options-NAUHiQEC.d.cts} +3 -3
  18. package/dist/{options-BnEPUuVV.d.cts → options-NAUHiQEC.d.ts} +3 -3
  19. package/dist/{plugin-BWxJRKzS.d.cts → plugin-CjjzZX2F.d.cts} +4 -4
  20. package/dist/{plugin-e2WUEtiI.d.ts → plugin-CqxWoDKS.d.ts} +4 -4
  21. package/dist/plugin.cjs +20 -6
  22. package/dist/plugin.d.cts +5 -5
  23. package/dist/plugin.d.ts +5 -5
  24. package/dist/plugin.js +2 -2
  25. package/dist/providers/binance.d.cts +2 -2
  26. package/dist/providers/binance.d.ts +2 -2
  27. package/dist/providers/coinbase.d.cts +2 -2
  28. package/dist/providers/coinbase.d.ts +2 -2
  29. package/dist/providers/hyperliquid.d.cts +2 -2
  30. package/dist/providers/hyperliquid.d.ts +2 -2
  31. package/dist/{side-panel-HF0IAzwf.d.cts → side-panel-wMNfgyZb.d.cts} +13 -0
  32. package/dist/{side-panel-HF0IAzwf.d.ts → side-panel-wMNfgyZb.d.ts} +13 -0
  33. package/dist/{statusline-model-zKXtGIjj.d.ts → statusline-model-Dih6FGWP.d.ts} +3 -3
  34. package/dist/{statusline-model-DFY7tuHj.d.cts → statusline-model-Dpfpq54A.d.cts} +3 -3
  35. package/dist/ui.cjs +115 -5
  36. package/dist/ui.d.cts +28 -2
  37. package/dist/ui.d.ts +28 -2
  38. package/dist/ui.js +3 -3
  39. package/dist/vela.global.js +317 -62
  40. package/dist/vela.global.min.js +61 -68
  41. package/dist/widget.cjs +476 -85
  42. package/dist/widget.d.cts +20 -10
  43. package/dist/widget.d.ts +20 -10
  44. package/dist/widget.js +7 -7
  45. package/dist/workspace.cjs +476 -85
  46. package/dist/workspace.d.cts +6 -6
  47. package/dist/workspace.d.ts +6 -6
  48. package/dist/workspace.js +6 -6
  49. package/package.json +3 -3
@@ -1,8 +1,8 @@
1
- import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore } from './chunk-QBPUT5SU.js';
2
- import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, mobilePlacement, widgetAttachments, getDrawingType, inputDeltas } from './chunk-EZ5FWVLA.js';
3
- import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-KA77UTRF.js';
4
- import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-2IAETM2I.js';
5
- import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-BZQM2XO7.js';
1
+ import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore } from './chunk-T3DZIR5Y.js';
2
+ import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, mobilePlacement, widgetAttachments, getDrawingType, inputDeltas } from './chunk-DPAA3SRT.js';
3
+ import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-27UTYE7T.js';
4
+ import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-NLDTVFOI.js';
5
+ import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, announceSurface, icon, categoricalColor } from './chunk-HKNO24GD.js';
6
6
  import { baseOf } from './chunk-W4EJWLEO.js';
7
7
 
8
8
  // src/widget/timeframe.ts
@@ -261,6 +261,7 @@ var LayoutPicker = class {
261
261
  const panel = doc.createElement("div");
262
262
  panel.className = "vela-lp";
263
263
  this.layer.appendChild(panel);
264
+ this.panel = panel;
264
265
  const cols = doc.createElement("div");
265
266
  cols.className = "vela-lp-cols";
266
267
  panel.appendChild(cols);
@@ -342,10 +343,12 @@ var LayoutPicker = class {
342
343
  this.doc.addEventListener("pointerdown", this.onDocPointerDown, true);
343
344
  this.doc.addEventListener("keydown", this.onDocKeydown, true);
344
345
  this.opts.onOpenChange?.(true);
346
+ if (this.isOpen) announceSurface(this.panel, true, "popover", this.opts.trigger);
345
347
  }
346
348
  close() {
347
349
  if (!this.isOpen) return;
348
350
  this.isOpen = false;
351
+ announceSurface(this.panel, false, "popover", this.opts.trigger);
349
352
  this.layer.style.display = "none";
350
353
  this.opts.trigger.setAttribute("aria-expanded", "false");
351
354
  this.doc.removeEventListener("pointerdown", this.onDocPointerDown, true);
@@ -2813,19 +2816,22 @@ var PanelDock = class {
2813
2816
  /**
2814
2817
  * (Re)build the CONTRIBUTED panels from the registry — call once after the built-ins, and
2815
2818
  * again on `refreshActions()` so a late registration appears. Contributed panels that are
2816
- * gone from the registry are dropped; the ones still there are rebuilt, so a replaced
2817
- * descriptor takes effect.
2819
+ * gone from the registry are dropped and a REPLACED descriptor is rebuilt; a panel whose
2820
+ * descriptor is unchanged stays mounted as it is, so its content and state survive.
2818
2821
  */
2819
2822
  refresh() {
2820
2823
  const openBefore = this.openId;
2821
- for (const entry of [...this.entries]) if (entry.contributed) this.drop(entry);
2822
- for (const desc of sidePanels()) {
2824
+ const registered = sidePanels();
2825
+ for (const entry of [...this.entries]) if (entry.contributed && !registered.includes(entry.desc)) this.drop(entry);
2826
+ for (const desc of registered) {
2827
+ if (this.entries.some((e) => e.desc === desc)) continue;
2823
2828
  const panel = new SidePanel(this.host, desc.title, `vela-panel-${desc.id}`, {
2824
2829
  width: desc.width,
2825
2830
  resizable: desc.resizable,
2826
2831
  minWidth: desc.minWidth,
2827
2832
  maxWidth: desc.maxWidth,
2828
- overlay: desc.overlay
2833
+ overlay: desc.overlay,
2834
+ maximizable: desc.maximizable
2829
2835
  });
2830
2836
  const entry = {
2831
2837
  id: desc.id,
@@ -2833,10 +2839,19 @@ var PanelDock = class {
2833
2839
  icon: desc.icon,
2834
2840
  order: desc.order ?? DEFAULT_PANEL_ORDER,
2835
2841
  panel,
2836
- contributed: true
2842
+ contributed: true,
2843
+ desc
2837
2844
  };
2838
2845
  try {
2839
- entry.handle = desc.mount(this.deps.context(), panel.content, { slot: panel.headerSlot, setTitle: (t) => panel.setTitle(t) }) ?? void 0;
2846
+ const header = {
2847
+ slot: panel.headerSlot,
2848
+ setTitle: (t) => panel.setTitle(t),
2849
+ get maximized() {
2850
+ return panel.maximized;
2851
+ },
2852
+ setMaximized: (on) => panel.setMaximized(on)
2853
+ };
2854
+ entry.handle = desc.mount(this.deps.context(), panel.content, header) ?? void 0;
2840
2855
  if (this.chart) entry.handle?.onChart?.(this.chart);
2841
2856
  } catch (err) {
2842
2857
  console.warn(`[vela] side panel "${desc.id}" failed to mount`, err);
@@ -3652,7 +3667,12 @@ var TimeframeQuick = class {
3652
3667
  content: (body) => body.append(this.input, this.hint),
3653
3668
  onOpenChange: (open) => opts.onOpenChange?.(open)
3654
3669
  });
3655
- this.input.addEventListener("input", () => this.renderHint());
3670
+ this.input.addEventListener("input", () => {
3671
+ const { selectionStart, selectionEnd } = this.input;
3672
+ this.input.value = this.input.value.toUpperCase();
3673
+ this.input.setSelectionRange(selectionStart, selectionEnd);
3674
+ this.renderHint();
3675
+ });
3656
3676
  this.input.addEventListener("keydown", (e) => {
3657
3677
  if (e.key !== "Enter") return;
3658
3678
  const parsed = parseTimeframe(this.input.value);
@@ -3664,7 +3684,7 @@ var TimeframeQuick = class {
3664
3684
  }
3665
3685
  open(seed = "") {
3666
3686
  this.dialog.show();
3667
- this.input.value = seed;
3687
+ this.input.value = seed.toUpperCase();
3668
3688
  this.renderHint();
3669
3689
  setTimeout(() => {
3670
3690
  this.input.focus();
@@ -3682,7 +3702,7 @@ var TimeframeQuick = class {
3682
3702
  this.open(text);
3683
3703
  return;
3684
3704
  }
3685
- this.input.value += text;
3705
+ this.input.value += text.toUpperCase();
3686
3706
  this.renderHint();
3687
3707
  }
3688
3708
  close() {
@@ -3695,7 +3715,7 @@ var TimeframeQuick = class {
3695
3715
  const raw = this.input.value.trim();
3696
3716
  const parsed = parseTimeframe(raw);
3697
3717
  if (!raw) {
3698
- this.hint.textContent = "e.g. 15, 4h, D, 3M";
3718
+ this.hint.textContent = "e.g. 15, 4H, D, 3M";
3699
3719
  delete this.hint.dataset.invalid;
3700
3720
  } else if (parsed.valid) {
3701
3721
  this.hint.textContent = parsed.label ?? "";
@@ -3798,7 +3818,7 @@ var ShortcutsHelp = class {
3798
3818
  addRow("Delete the drawing under the cursor", ["Middle-click"]);
3799
3819
  const s = doc.createElement("div");
3800
3820
  s.className = "vela-sh-static";
3801
- s.textContent = "Typing a letter opens the symbol search; typing a digit opens the timeframe entry.";
3821
+ s.textContent = "Typing a letter or 0 opens the symbol search; typing a digit from 1 to 9 opens the timeframe entry.";
3802
3822
  this.list.appendChild(s);
3803
3823
  }
3804
3824
  };
@@ -4218,6 +4238,9 @@ var CSS10 = `
4218
4238
  .vela-statusline .vela-sl-market { align-self: center; display: inline-flex; }
4219
4239
  .vela-statusline .vela-sl-market > [hidden] { display: none !important; }
4220
4240
  .vela-statusline .vela-sl-replay-badge, .vela-statusline .vela-sl-replay-badge svg { display: block; width: 16px; height: 16px; }
4241
+ /* Tabular figures: every digit has one advance, so a readout whose text changes only in
4242
+ * its digits keeps its width \u2014 render() skips the ladder for those (see widthKey). */
4243
+ .vela-statusline .vela-sl-values { font-variant-numeric: tabular-nums; }
4221
4244
  .vela-statusline .vela-sl-ohlc { display: flex; gap: var(--vela-space-1); color: var(--vela-fg-muted); }
4222
4245
  .vela-statusline .vela-sl-ohlc b { color: var(--vela-fg); font-weight: 500; }
4223
4246
  /* The change value wears the SAME ink as the OHLC values (set inline per render) \u2014
@@ -4335,6 +4358,10 @@ var Statusline = class {
4335
4358
  this.fitRO = null;
4336
4359
  /** The ladder rung currently applied — see {@link fit}. */
4337
4360
  this.layout = { stacked: false, level: "full" };
4361
+ /** The readout {@link widthKey} the applied rung was fitted to. */
4362
+ this.fitKey = null;
4363
+ /** Web fonts landing after the last fit change every width without a resize. */
4364
+ this.onFontsLoaded = () => this.fit();
4338
4365
  this.onContextMenu = (e) => {
4339
4366
  if (!this.menu || !this.menuHooks) return;
4340
4367
  e.preventDefault();
@@ -4398,6 +4425,7 @@ var Statusline = class {
4398
4425
  this.fitRO = new ResizeObserver(() => this.fit());
4399
4426
  this.fitRO.observe(host);
4400
4427
  }
4428
+ doc.fonts?.addEventListener("loadingdone", this.onFontsLoaded);
4401
4429
  this.marketTip = new Tooltip(this.marketEl, { content: MARKET_LABELS.open, placement: "bottom" });
4402
4430
  this.eyeTip = new Tooltip(this.eyeEl, { content: "Show chart", placement: "bottom" });
4403
4431
  this.setMarketStatus("open");
@@ -4450,6 +4478,7 @@ var Statusline = class {
4450
4478
  * (detached host, node tests) nothing overflows, so the widest rung stays.
4451
4479
  */
4452
4480
  fit() {
4481
+ this.fitKey = this.widthKey();
4453
4482
  this.syncParts();
4454
4483
  const seg = segmentVisibility(this.parts, this.chartHidden);
4455
4484
  const overflows = () => this.el.scrollWidth > this.el.clientWidth;
@@ -4606,6 +4635,7 @@ var Statusline = class {
4606
4635
  this.detach();
4607
4636
  this.fitRO?.disconnect();
4608
4637
  this.fitRO = null;
4638
+ this.el.ownerDocument.fonts?.removeEventListener("loadingdone", this.onFontsLoaded);
4609
4639
  this.el.removeEventListener("contextmenu", this.onContextMenu);
4610
4640
  this.menu?.destroy();
4611
4641
  this.menu = null;
@@ -4621,7 +4651,22 @@ var Statusline = class {
4621
4651
  }
4622
4652
  render() {
4623
4653
  if (this.menuHooks) this.setChartHidden(!this.menuHooks.chartVisible());
4624
- this.fit();
4654
+ if (this.widthKey() === this.fitKey) this.renderValues();
4655
+ else this.fit();
4656
+ }
4657
+ /** Everything the readout's width depends on, at every rung: its shape, and each
4658
+ * value's sign, digit count and decimals (the digits themselves are tabular — see
4659
+ * the CSS; the grouping commas follow from the digit count). `toFixed` carries all
4660
+ * three at a fraction of the locale formatter's cost — this runs per pointer move.
4661
+ * The parts, the host's size and the fonts re-fit through their own paths. */
4662
+ widthKey() {
4663
+ const bar = this.hoverBar ?? this.lastBar;
4664
+ if (!bar) return this.readout;
4665
+ const dp = decimalsFor(bar.close);
4666
+ const diff = bar.close - bar.open;
4667
+ const text = [bar.open, bar.high, bar.low, bar.close, diff].map((v) => v.toFixed(dp));
4668
+ text.push((diff / bar.open * 100).toFixed(2));
4669
+ return `${this.readout} ${text.join(" ")}`.replace(/\d/g, "0");
4625
4670
  }
4626
4671
  /** Write the value readout for the current bar at the current ladder level. */
4627
4672
  renderValues() {
@@ -6424,7 +6469,7 @@ var ChartCell = class {
6424
6469
  * then the manifest in the host's own order. */
6425
6470
  libraryRows() {
6426
6471
  return [
6427
- ...this.supportedNatives().map((n) => ({ name: n.title, category: "Vela", native: true, nativeType: n.type, beta: n.beta })),
6472
+ ...this.supportedNatives().map((n) => ({ name: n.title, category: "Built-in", native: true, nativeType: n.type, beta: n.beta })),
6428
6473
  ...this.manifest.map((e) => ({ name: e.name, language: e.language, category: e.category }))
6429
6474
  ];
6430
6475
  }
@@ -8676,11 +8721,11 @@ function resolveTyping(key, open) {
8676
8721
  if (open.dialogs > 0) {
8677
8722
  if (key.length !== 1) return null;
8678
8723
  if (open.symbolSearch) return { target: "symbol", text: key.toUpperCase() };
8679
- if (open.timeframeEntry) return { target: "timeframe", text: key };
8724
+ if (open.timeframeEntry) return { target: "timeframe", text: key.toUpperCase() };
8680
8725
  return null;
8681
8726
  }
8682
- if (/^[a-zA-Z]$/.test(key)) return { target: "symbol", text: key.toUpperCase() };
8683
- if (/^[0-9]$/.test(key)) return { target: "timeframe", text: key };
8727
+ if (/^[a-zA-Z0]$/.test(key)) return { target: "symbol", text: key.toUpperCase() };
8728
+ if (/^[1-9]$/.test(key)) return { target: "timeframe", text: key };
8684
8729
  return null;
8685
8730
  }
8686
8731
  var VelaWorkspace = class {
@@ -10418,7 +10463,7 @@ var VelaWorkspace = class {
10418
10463
  }
10419
10464
  });
10420
10465
  }
10421
- /** Bare-typing router: letters → symbol search (seeded), digits → timeframe entry. */
10466
+ /** Bare-typing router: letters and `0` → symbol search (seeded), digits 1–9 → timeframe entry. */
10422
10467
  routeTyping(ev) {
10423
10468
  if (this.destroyed) return;
10424
10469
  if (ev.ctrlKey || ev.metaKey || ev.altKey) return;