@luxalgo/vela 0.5.1 → 0.5.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 (45) hide show
  1. package/dist/{DataProvider-DGesjOJT.d.ts → DataProvider-DTOEXKTI.d.ts} +1 -1
  2. package/dist/{DataProvider-BBQ3Hr21.d.cts → DataProvider-gnzv-dgc.d.cts} +1 -1
  3. package/dist/{chunk-ULIX6AE2.js → chunk-ATPU5CI6.js} +1 -1
  4. package/dist/{chunk-S6F6SQ2L.js → chunk-B5TIKQJ5.js} +60 -7
  5. package/dist/{chunk-EP6NDJYK.js → chunk-LJLZR44Y.js} +4 -2
  6. package/dist/{chunk-AIW3EJUE.js → chunk-P556H6EA.js} +329 -10
  7. package/dist/{chunk-FNOMKHEZ.js → chunk-RRFGWZNJ.js} +1321 -363
  8. package/dist/{chunk-5SE4PL3H.js → chunk-Y7TK4ZWK.js} +1363 -48
  9. package/dist/{contributions-BlV3kb0O.d.cts → contributions-Ci_i3IN2.d.cts} +33 -2
  10. package/dist/{contributions-6N0rbrPC.d.ts → contributions-b6AVrqqG.d.ts} +33 -2
  11. package/dist/{history-DX3Zne3a.d.cts → history-Cf1lVsap.d.cts} +15 -3
  12. package/dist/{history-BTd52YMA.d.ts → history-Ci3M0xLV.d.ts} +15 -3
  13. package/dist/index.cjs +1374 -366
  14. package/dist/index.d.cts +52 -19
  15. package/dist/index.d.ts +52 -19
  16. package/dist/index.js +4 -4
  17. package/dist/{options-DbQholFV.d.cts → options-XTBpbx0s.d.cts} +47 -1
  18. package/dist/{options-DbQholFV.d.ts → options-XTBpbx0s.d.ts} +47 -1
  19. package/dist/{plugin-TN3n-9YN.d.ts → plugin-CnNd7cuF.d.ts} +172 -25
  20. package/dist/{plugin-O34MbXf-.d.cts → plugin-DfH4Y-Om.d.cts} +172 -25
  21. package/dist/plugin.cjs +53 -7
  22. package/dist/plugin.d.cts +4 -4
  23. package/dist/plugin.d.ts +4 -4
  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/ui.cjs +332 -9
  32. package/dist/ui.d.cts +64 -2
  33. package/dist/ui.d.ts +64 -2
  34. package/dist/ui.js +3 -3
  35. package/dist/vela.global.js +1374 -366
  36. package/dist/vela.global.min.js +84 -34
  37. package/dist/widget.cjs +3348 -550
  38. package/dist/widget.d.cts +65 -7
  39. package/dist/widget.d.ts +65 -7
  40. package/dist/widget.js +169 -18
  41. package/dist/workspace.cjs +4251 -1400
  42. package/dist/workspace.d.cts +45 -9
  43. package/dist/workspace.d.ts +45 -9
  44. package/dist/workspace.js +226 -22
  45. package/package.json +1 -1
package/dist/widget.js CHANGED
@@ -1,12 +1,12 @@
1
- import { Glider, WidgetHistory, localStorageAdapter, decodeState, prefixedSymbol, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, ChartContextMenu, Toast, Watermark, Statusline, Bottombar, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp, indicatorLedger, sanitizeState, legacyWidgetState, parsePersisted, statuslineInkOf, toolShortcutHints, resolveIndicators, encodeState } from './chunk-5SE4PL3H.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-5SE4PL3H.js';
3
- import { registerBuiltinChartTypes, resolveTheme, parseSymbol, Vela, normalizeTimezone } from './chunk-FNOMKHEZ.js';
4
- export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-FNOMKHEZ.js';
5
- import { widgetAttachments, legendActionsProviderFor, resolveEngines } from './chunk-S6F6SQ2L.js';
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-S6F6SQ2L.js';
7
- import { ensureUIHost, KeymapManager, Menu, applyPlotOverlayTokens, isEditableTarget } from './chunk-AIW3EJUE.js';
8
- import './chunk-ULIX6AE2.js';
9
- import { injectStyles } from './chunk-EP6NDJYK.js';
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-Y7TK4ZWK.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-Y7TK4ZWK.js';
3
+ import { registerBuiltinChartTypes, resolveTheme, parseSymbol, buildToolbar, priceStyleIds, Vela, normalizeTimezone } from './chunk-RRFGWZNJ.js';
4
+ export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-RRFGWZNJ.js';
5
+ import { widgetActions, widgetAttachments, legendActionsProviderFor, resolveEngines } from './chunk-B5TIKQJ5.js';
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-B5TIKQJ5.js';
7
+ import { ensureUIHost, KeymapManager, Menu, applyPlotOverlayTokens, isEditableTarget } from './chunk-P556H6EA.js';
8
+ import './chunk-ATPU5CI6.js';
9
+ import { injectStyles } from './chunk-LJLZR44Y.js';
10
10
 
11
11
  // src/widget/url-state.ts
12
12
  var PARAMS = [
@@ -47,8 +47,8 @@ function writeUrlState(state) {
47
47
  var DEFAULT_TIMEFRAMES = ["1", "5", "15", "60", "240", "D", "W"];
48
48
  var WIDGET_STYLE_ID = "vela-widget";
49
49
  var WIDGET_CSS = `
50
- .vela-widget { display: flex; flex-direction: column; width: 100%; height: 100%; background: var(--vela-bg); }
51
- .vela-widget-main { display: flex; flex-direction: row; flex: 1 1 auto; min-height: 0; }
50
+ .vela-widget { position: relative; display: flex; flex-direction: column; width: 100%; height: 100%; background: var(--vela-bg); }
51
+ .vela-widget-main { position: relative; display: flex; flex-direction: row; flex: 1 1 auto; min-height: 0; }
52
52
  .vela-widget-chart { position: relative; flex: 1 1 auto; min-width: 0; }
53
53
  `;
54
54
  var VelaWidget = class {
@@ -67,6 +67,8 @@ var VelaWidget = class {
67
67
  this.onRootKeydown = (ev) => this.routeTyping(ev);
68
68
  /** Indicator titles (the in-chart legend rows) shown — reapplied across rebuilds. */
69
69
  this.indicatorTitlesOn = true;
70
+ /** Plot values beside the legend titles shown — reapplied across rebuilds. */
71
+ this.indicatorValuesOn = true;
70
72
  this.pendingRange = null;
71
73
  /** Symbol already reported as unservable (the core re-reports on every index settle). */
72
74
  this.unresolvedToasted = null;
@@ -110,6 +112,15 @@ var VelaWidget = class {
110
112
  this.indicatorsPromise = null;
111
113
  this.destroyed = false;
112
114
  this.buildSeq = 0;
115
+ this.tfDrawer = null;
116
+ this.drawingsDrawer = null;
117
+ this.moreDrawer = null;
118
+ this.timezoneDrawer = null;
119
+ this.priceScaleDrawer = null;
120
+ /** Plot-local y of the last price-axis long-press (targets the pane under the finger). */
121
+ this.priceScalePressY = 0;
122
+ /** The active range chip id (both bottom bars + the timeframe drawer mirror it). */
123
+ this.activeRangeId = null;
113
124
  const hostEl = typeof container === "string" ? document.querySelector(container) : container;
114
125
  if (!hostEl) throw new Error(`VelaWidget: container not found: ${String(container)}`);
115
126
  registerBuiltinChartTypes();
@@ -135,6 +146,7 @@ var VelaWidget = class {
135
146
  this.bars = Number(fromUrl.bars ?? bootCell?.bars ?? opts.bars ?? 1e3);
136
147
  this.watermarkOn = bootCell?.watermark !== void 0 ? bootCell.watermark : opts.watermark !== false;
137
148
  this.indicatorTitlesOn = bootCell?.indicatorTitles ?? true;
149
+ this.indicatorValuesOn = bootCell?.indicatorValues ?? true;
138
150
  this.favs = boot?.favorites ? [...boot.favorites] : [];
139
151
  this.savedConfig = bootCell?.rendererConfig ?? null;
140
152
  this.savedDrawings = bootCell?.drawings ?? null;
@@ -154,7 +166,7 @@ var VelaWidget = class {
154
166
  this.trackDialog(open);
155
167
  }
156
168
  });
157
- this.indicatorPicker = new IndicatorPicker({
169
+ this.indicatorPicker = opts.indicatorPicker !== false ? new IndicatorPicker({
158
170
  host: this.root,
159
171
  library: () => [
160
172
  ...this.nativeCatalog.filter((n) => n.supported).map((n) => ({ name: n.title, category: "Vela", native: true, nativeType: n.type, beta: n.beta })),
@@ -174,17 +186,21 @@ var VelaWidget = class {
174
186
  if (i < present.length) this.removeNative(present[i].type);
175
187
  else this.removeInstance(i - present.length);
176
188
  },
177
- onOpenChange: (open) => this.trackDialog(open)
178
- });
189
+ onOpenChange: (open) => {
190
+ if (open) this.inner?.renderer.closeDialogs();
191
+ this.trackDialog(open);
192
+ }
193
+ }) : null;
179
194
  this.tfQuick = new TimeframeQuick({
180
195
  host: this.root,
181
196
  onApply: (tf) => this.setTimeframe(tf),
182
197
  onOpenChange: (open) => this.trackDialog(open)
183
198
  });
199
+ const picker = this.indicatorPicker;
184
200
  this.topbar = new Topbar(this.root, {
185
201
  symbol: this.symbol,
186
202
  onSymbolClick: () => this.symbolPicker.open(),
187
- onIndicatorsClick: () => this.indicatorPicker.open(),
203
+ ...picker ? { onIndicatorsClick: () => picker.open() } : {},
188
204
  onUndoClick: () => this.history.undo(),
189
205
  onRedoClick: () => this.history.redo(),
190
206
  onScreenshotClick: () => this.downloadScreenshot(),
@@ -233,7 +249,21 @@ var VelaWidget = class {
233
249
  onTimezone: (zone) => this.setTimezone(zone),
234
250
  onSettingsClick: () => this.inner?.renderer.openSettings()
235
251
  }) : null;
252
+ this.mobileBar = opts.bottombar !== false ? new MobileBar(this.root, {
253
+ symbol: this.symbol,
254
+ timeframe: this.timeframe,
255
+ onSymbolClick: () => this.symbolPicker.open(),
256
+ onTimeframeClick: () => this.openTimeframeDrawer(),
257
+ ...picker ? { onIndicatorsClick: () => picker.open() } : {},
258
+ getContext: () => this.context(),
259
+ onDrawingsClick: () => this.openDrawingsDrawer(),
260
+ onMoreClick: () => this.openMoreDrawer(),
261
+ onSettingsClick: () => this.inner?.renderer.openSettings()
262
+ }) : null;
263
+ this.drawingPill = new DrawingPill(this.chartHost);
236
264
  hostEl.appendChild(this.root);
265
+ this.layoutCtl = new LayoutModeController(this.root, opts.layoutMode ?? "auto");
266
+ this.layoutCtl.onChange((mode) => this.onLayoutModeChange(mode));
237
267
  this.keymap = new KeymapManager();
238
268
  this.keymap.attach(this.root);
239
269
  this.keymap.register({
@@ -282,7 +312,7 @@ var VelaWidget = class {
282
312
  this.keymap.register({ id: "view.zoom-out", keys: "mod+arrowdown", label: "Zoom out", category: "Chart", run: () => this.glider.zoom(ZOOM_OUT) });
283
313
  this.keymap.register({ id: "view.pan-left", keys: "mod+arrowleft", label: "Pan toward history", category: "Chart", run: () => this.inner?.panBy(-PAN_FAST) });
284
314
  this.keymap.register({ id: "view.pan-right", keys: "mod+arrowright", label: "Pan toward now", category: "Chart", run: () => this.inner?.panBy(PAN_FAST) });
285
- this.keymap.register({ id: "indicators.open", keys: "/", label: "Open the indicator picker", category: "Indicators", run: () => this.indicatorPicker.open() });
315
+ if (picker) this.keymap.register({ id: "indicators.open", keys: "/", label: "Open the indicator picker", category: "Indicators", run: () => picker.open() });
286
316
  this.keymap.register({
287
317
  id: "help.shortcuts",
288
318
  keys: "?",
@@ -299,6 +329,86 @@ var VelaWidget = class {
299
329
  this.mountAttachments();
300
330
  if (opts.autofocus) this.inner?.renderer.focus();
301
331
  }
332
+ /** The mode flipped (container resized across the breakpoint, or a coarse-pointer
333
+ * change). Close the open surfaces — a desktop card must not linger over the
334
+ * mobile chrome (and vice versa) — and re-present the renderer's own chrome. */
335
+ onLayoutModeChange(mode) {
336
+ this.symbolPicker.close();
337
+ this.indicatorPicker?.close();
338
+ this.tfDrawer?.close();
339
+ this.drawingsDrawer?.close();
340
+ this.moreDrawer?.close();
341
+ this.timezoneDrawer?.close();
342
+ this.priceScaleDrawer?.close();
343
+ this.inner?.renderer.closeDialogs();
344
+ this.inner?.renderer.setLayoutMode(mode);
345
+ }
346
+ // ── mobile drawers (built on first open; every list is read live at open time) ──
347
+ openTimeframeDrawer() {
348
+ this.tfDrawer ?? (this.tfDrawer = new TimeframeDrawer({
349
+ host: this.root,
350
+ timeframes: this.opts.timeframes ?? DEFAULT_TIMEFRAMES,
351
+ ranges: RANGE_PRESETS,
352
+ currentTimeframe: () => this.timeframe,
353
+ activeRange: () => this.activeRangeId,
354
+ onTimeframe: (tf) => this.setTimeframe(tf),
355
+ onRange: (preset) => this.applyRange(preset),
356
+ onOpenChange: (open) => this.trackDialog(open)
357
+ }));
358
+ this.tfDrawer.open();
359
+ }
360
+ openDrawingsDrawer() {
361
+ this.drawingsDrawer ?? (this.drawingsDrawer = new DrawingsDrawer({
362
+ host: this.root,
363
+ toolbar: () => buildToolbar(this.opts.drawings).definition,
364
+ currentTool: () => this.inner?.drawings.getTool() ?? null,
365
+ isFavorite: (type) => this.inner?.drawings.isFavorite(type) ?? false,
366
+ onFavorite: (type, on) => this.inner?.drawings.setFavorite(type, on),
367
+ onSelect: (type) => this.inner?.drawings.setTool(type),
368
+ onOpenChange: (open) => this.trackDialog(open)
369
+ }));
370
+ this.drawingsDrawer.open();
371
+ }
372
+ openMoreDrawer() {
373
+ this.moreDrawer ?? (this.moreDrawer = new MoreDrawer({
374
+ host: this.root,
375
+ onUndo: () => this.history.undo(),
376
+ onRedo: () => this.history.redo(),
377
+ onScreenshot: () => this.downloadScreenshot(),
378
+ canUndo: () => this.history.canUndo,
379
+ canRedo: () => this.history.canRedo,
380
+ priceStyles: () => priceStyleIds().map((id) => ({ id, label: priceStyleLabel(id), icon: priceStyleIcon(id) })),
381
+ priceStyle: () => this.priceStyle,
382
+ onPriceStyle: (id) => this.setPriceStyle(id),
383
+ panels: () => [...this.dock.list()],
384
+ onTogglePanel: (id) => this.dock.toggle(id),
385
+ alerts: () => this.alerts,
386
+ // Left-aligned actions have their own bottom-bar stop — only the rest
387
+ // lands in the drawer, or every left action would appear twice.
388
+ actions: () => widgetActions("topbar", this.context()).filter((a) => a.align !== "left").map((a) => ({ label: a.label, icon: a.icon, run: () => a.run(this.context()) })),
389
+ onOpenChange: (open) => this.trackDialog(open)
390
+ }));
391
+ this.moreDrawer.open();
392
+ }
393
+ openTimezoneDrawer() {
394
+ this.timezoneDrawer ?? (this.timezoneDrawer = new TimezoneDrawer({
395
+ host: this.root,
396
+ timezone: () => this.timezone,
397
+ onTimezone: (zone) => this.setTimezone(zone),
398
+ onOpenChange: (open) => this.trackDialog(open)
399
+ }));
400
+ this.timezoneDrawer.open();
401
+ }
402
+ openPriceScaleDrawer(y) {
403
+ this.priceScalePressY = y;
404
+ this.priceScaleDrawer ?? (this.priceScaleDrawer = new PriceScaleDrawer({
405
+ host: this.root,
406
+ chart: () => this.inner,
407
+ pressY: () => this.priceScalePressY,
408
+ onOpenChange: (open) => this.trackDialog(open)
409
+ }));
410
+ this.priceScaleDrawer.open();
411
+ }
302
412
  /** Mount registered attachments not yet mounted on this widget (idempotent per id). */
303
413
  mountAttachments() {
304
414
  for (const att of widgetAttachments()) {
@@ -345,6 +455,7 @@ var VelaWidget = class {
345
455
  refreshActions() {
346
456
  this.mountAttachments();
347
457
  this.topbar.renderActions();
458
+ this.mobileBar?.renderActions();
348
459
  this.dock.refresh();
349
460
  if (this.inner) this.inner.renderer.setLegendActions(legendActionsProviderFor(this.inner, () => this.context()));
350
461
  }
@@ -360,6 +471,7 @@ var VelaWidget = class {
360
471
  syncTimeframeChrome(tf) {
361
472
  this.timeframe = tf;
362
473
  this.topbar.setTimeframe(tf);
474
+ this.mobileBar?.setTimeframe(tf);
363
475
  this.watermark?.update(this.symbol, tf);
364
476
  this.statusline?.setMeta(tf, this.providerLabel());
365
477
  }
@@ -374,6 +486,7 @@ var VelaWidget = class {
374
486
  }
375
487
  setTimeframe(tf) {
376
488
  if (tf === this.timeframe || this.destroyed) return;
489
+ this.activeRangeId = null;
377
490
  this.bottombar?.setActiveRange(null);
378
491
  this.rangeBars = 0;
379
492
  this.syncTimeframeChrome(tf);
@@ -391,6 +504,7 @@ var VelaWidget = class {
391
504
  this.unresolvedToasted = null;
392
505
  this.symbol = symbol;
393
506
  this.topbar.setSymbol(symbol);
507
+ this.mobileBar?.setSymbol(symbol);
394
508
  this.statusline?.setSymbol(symbol);
395
509
  this.objectTree.setSymbol(symbol);
396
510
  this.watermark?.update(symbol, this.timeframe);
@@ -419,6 +533,7 @@ var VelaWidget = class {
419
533
  if (this.bars > 0) cell.bars = this.bars;
420
534
  cell.watermark = this.watermarkOn;
421
535
  cell.indicatorTitles = this.indicatorTitlesOn;
536
+ cell.indicatorValues = this.indicatorValuesOn;
422
537
  if (this.inner) {
423
538
  cell.rendererConfig = this.inner.renderer.getConfig();
424
539
  cell.drawings = this.inner.drawings.toJSON();
@@ -464,6 +579,7 @@ var VelaWidget = class {
464
579
  if (style && style !== this.priceStyle) this.setPriceStyle(style);
465
580
  if (cell.watermark !== void 0 && cell.watermark !== this.watermarkOn) this.setWatermarkVisible(cell.watermark);
466
581
  if (cell.indicatorTitles !== void 0 && cell.indicatorTitles !== this.indicatorTitlesOn) this.setIndicatorTitlesVisible(cell.indicatorTitles);
582
+ if (cell.indicatorValues !== void 0 && cell.indicatorValues !== this.indicatorValuesOn) this.setIndicatorValuesVisible(cell.indicatorValues);
467
583
  if (cell.rendererConfig != null) {
468
584
  this.savedConfig = cell.rendererConfig;
469
585
  this.inner?.renderer.applyConfig(cell.rendererConfig);
@@ -566,6 +682,12 @@ var VelaWidget = class {
566
682
  this.inner?.renderer.set("indicatorTitles", visible);
567
683
  this.markStateDirty();
568
684
  }
685
+ /** Show/hide the plot values beside every indicator's legend title (persisted). */
686
+ setIndicatorValuesVisible(visible) {
687
+ this.indicatorValuesOn = visible;
688
+ this.inner?.renderer.set("indicatorValues", visible);
689
+ this.markStateDirty();
690
+ }
569
691
  /** Applied LIVE (renderer feature) — no rebuild; persists across rebuilds. */
570
692
  setPriceStyle(style) {
571
693
  this.priceStyle = style;
@@ -612,6 +734,8 @@ var VelaWidget = class {
612
734
  */
613
735
  applyRange(preset) {
614
736
  if (this.destroyed) return;
737
+ this.activeRangeId = preset.id;
738
+ this.bottombar?.setActiveRange(preset.id);
615
739
  this.pendingRange = preset;
616
740
  const tfChanged = preset.tf !== this.timeframe;
617
741
  const deeper = preset.bars > Math.max(this.bars, this.rangeBars);
@@ -650,16 +774,24 @@ var VelaWidget = class {
650
774
  this.shortcutsHelp?.destroy();
651
775
  this.contextMenu.destroy();
652
776
  this.symbolPicker.destroy();
653
- this.indicatorPicker.destroy();
777
+ this.indicatorPicker?.destroy();
654
778
  this.tfQuick.destroy();
655
779
  this.statusline?.destroy();
656
780
  this.watermark?.destroy();
657
781
  this.bottombar?.destroy();
782
+ this.mobileBar?.destroy();
783
+ this.drawingPill.destroy();
784
+ this.tfDrawer?.destroy();
785
+ this.drawingsDrawer?.destroy();
786
+ this.moreDrawer?.destroy();
787
+ this.timezoneDrawer?.destroy();
788
+ this.priceScaleDrawer?.destroy();
658
789
  this.toast?.destroy();
659
790
  this.alertsMenu?.destroy();
660
791
  this.glider.stop();
661
792
  this.history.destroy();
662
793
  this.keymap.destroy();
794
+ this.layoutCtl.destroy();
663
795
  this.root.remove();
664
796
  }
665
797
  /** Destroy + recreate the inner chart with the current symbol/timeframe, then
@@ -681,6 +813,7 @@ var VelaWidget = class {
681
813
  statusline: _statusline,
682
814
  watermark: _watermark,
683
815
  bottombar: _bottombar,
816
+ layoutMode: _layoutMode,
684
817
  ...chartOpts
685
818
  } = this.opts;
686
819
  const chart = new Vela(this.chartHost, {
@@ -696,11 +829,17 @@ var VelaWidget = class {
696
829
  for (const [language, make] of Object.entries(resolveEngines(engines))) chart.registerEngine(language, make());
697
830
  this.inner = chart;
698
831
  this.symbolPicker.setSource(() => chart.data.symbols());
832
+ if (this.layoutCtl !== void 0) chart.renderer.setLayoutMode(this.layoutCtl.current);
699
833
  this.objectTree.setSymbol(this.symbol);
700
834
  chart.renderer.setLegendActions(legendActionsProviderFor(chart, () => this.context()));
701
835
  if (chart.renderer.supports("historyChords")) chart.renderer.set("historyChords", false);
702
836
  this.dock.onChart(chart);
703
837
  this.contextMenu.onChart(chart);
838
+ chart.renderer.onAxisLongPress((e) => {
839
+ if (this.layoutCtl.current !== "mobile") return;
840
+ if (e.axis === "time") this.openTimezoneDrawer();
841
+ else this.openPriceScaleDrawer(e.y);
842
+ });
704
843
  this.refreshNativeCatalog();
705
844
  chart.on("indicator:added", () => {
706
845
  this.syncPresentNatives();
@@ -748,6 +887,8 @@ var VelaWidget = class {
748
887
  chart.on("load:end", () => {
749
888
  this.volumeMayBePending = false;
750
889
  });
890
+ chart.on("load:start", () => this.watermark?.setLoading(true));
891
+ chart.on("load:end", () => this.watermark?.setLoading(false));
751
892
  chart.on("theme:changed", (t) => {
752
893
  this.opts.theme = t;
753
894
  ensureUIHost(this.root, t);
@@ -759,6 +900,7 @@ var VelaWidget = class {
759
900
  if (symbol !== this.symbol) {
760
901
  this.symbol = symbol;
761
902
  this.topbar.setSymbol(symbol);
903
+ this.mobileBar?.setSymbol(symbol);
762
904
  this.statusline?.setSymbol(symbol);
763
905
  this.objectTree.setSymbol(symbol);
764
906
  this.watermark?.update(symbol, this.timeframe);
@@ -793,11 +935,13 @@ var VelaWidget = class {
793
935
  this.lastCrossTime = e.time;
794
936
  });
795
937
  this.topbar.renderActions();
938
+ this.mobileBar?.renderActions();
796
939
  if (this.savedConfig != null) chart.renderer.applyConfig(this.savedConfig);
797
940
  if (this.savedDrawings != null) chart.drawings.fromJSON(this.savedDrawings);
798
941
  if (this.priceStyle !== "candles") chart.renderer.set("priceStyle", this.priceStyle);
799
942
  if (this.timezone !== "Etc/UTC") chart.renderer.set("timezone", this.timezone);
800
943
  if (!this.indicatorTitlesOn) chart.renderer.set("indicatorTitles", false);
944
+ if (!this.indicatorValuesOn) chart.renderer.set("indicatorValues", false);
801
945
  chart.renderer.onConfigChanged(() => {
802
946
  const zone = chart.renderer.get("timezone");
803
947
  if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.timezone)) {
@@ -808,6 +952,7 @@ var VelaWidget = class {
808
952
  });
809
953
  this.syncPlotOverlayTokens();
810
954
  this.statusline?.onChart(chart);
955
+ this.drawingPill.onChart(chart);
811
956
  this.syncStatuslineColors();
812
957
  const advanced = {
813
958
  title: "Advanced",
@@ -855,6 +1000,12 @@ var VelaWidget = class {
855
1000
  label: "Titles",
856
1001
  get: () => this.indicatorTitlesOn,
857
1002
  set: (v) => this.setIndicatorTitlesVisible(v)
1003
+ },
1004
+ {
1005
+ kind: "toggle",
1006
+ label: "Values",
1007
+ get: () => this.indicatorValuesOn,
1008
+ set: (v) => this.setIndicatorValuesVisible(v)
858
1009
  }
859
1010
  ]
860
1011
  },
@@ -901,7 +1052,7 @@ var VelaWidget = class {
901
1052
  if (this.inner !== chart || this.destroyed) return;
902
1053
  this.nativeCatalog = list.map((n) => ({ type: n.type, title: n.title, supported: n.supported, present: n.present, beta: n.beta }));
903
1054
  this.syncIndicatorCount();
904
- this.indicatorPicker.sync();
1055
+ this.indicatorPicker?.sync();
905
1056
  });
906
1057
  }
907
1058
  /** Add a native indicator (single-instance per type — the core dedupes). */