@luxalgo/vela 0.7.5 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DataProvider-Dut6lXGM.d.cts → DataProvider-CGa4KHRa.d.cts} +1 -1
- package/dist/{DataProvider-DLeFs1gE.d.ts → DataProvider-CmWUtDVL.d.ts} +1 -1
- package/dist/{chunk-ZADTVRUO.js → chunk-PVGWNF7V.js} +1 -1
- package/dist/{chunk-MCLI6B3S.js → chunk-RVQWJOEE.js} +277 -120
- package/dist/{chunk-BKHSQ4YM.js → chunk-WTWGEB7K.js} +23 -9
- package/dist/{chunk-MNG5XPLV.js → chunk-ZA2XWTGH.js} +94 -37
- package/dist/{contributions-DYtiRtES.d.cts → contributions-DF_Ea07m.d.cts} +25 -2
- package/dist/{contributions-CEkgJKTU.d.ts → contributions-nKOSeLy8.d.ts} +25 -2
- package/dist/index.cjs +285 -127
- package/dist/index.d.cts +22 -7
- package/dist/index.d.ts +22 -7
- package/dist/index.js +2 -2
- package/dist/{options-DNBoMKkX.d.ts → options-D1AJKsn_.d.cts} +10 -0
- package/dist/{options-DNBoMKkX.d.cts → options-D1AJKsn_.d.ts} +10 -0
- package/dist/{plugin-CLn--oP6.d.ts → plugin-0oFDnexb.d.ts} +3 -3
- package/dist/{plugin-DtkeQVAO.d.cts → plugin-DPyVJFoA.d.cts} +3 -3
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/{statusline-model-gA__yaog.d.cts → statusline-model-BoWJ3cWQ.d.cts} +18 -5
- package/dist/{statusline-model-DypGXjtr.d.ts → statusline-model-DAFyqVmR.d.ts} +18 -5
- package/dist/ui.cjs +23 -9
- package/dist/ui.d.cts +20 -3
- package/dist/ui.d.ts +20 -3
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +285 -127
- package/dist/vela.global.min.js +59 -49
- package/dist/widget.cjs +389 -161
- package/dist/widget.d.cts +7 -7
- package/dist/widget.d.ts +7 -7
- package/dist/widget.js +5 -5
- package/dist/workspace.cjs +389 -161
- package/dist/workspace.d.cts +40 -8
- package/dist/workspace.d.ts +40 -8
- package/dist/workspace.js +4 -4
- package/package.json +21 -1
package/dist/vela.global.js
CHANGED
|
@@ -105,10 +105,18 @@ var Vela = (function (exports) {
|
|
|
105
105
|
this.records = /* @__PURE__ */ new Map();
|
|
106
106
|
this.counter = 0;
|
|
107
107
|
}
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Mint a unique per-instance id. Host-supplied ids share the namespace, so a minted
|
|
110
|
+
* id skips anything already recorded — and anything `taken` reports live elsewhere
|
|
111
|
+
* (a handle the orchestrator holds outside the records, e.g. a fail-soft native).
|
|
112
|
+
*/
|
|
113
|
+
nextId(prefix = "ind", taken = () => false) {
|
|
114
|
+
let id;
|
|
115
|
+
do {
|
|
116
|
+
this.counter += 1;
|
|
117
|
+
id = `${prefix}-${this.counter}`;
|
|
118
|
+
} while (this.records.has(id) || taken(id));
|
|
119
|
+
return id;
|
|
112
120
|
}
|
|
113
121
|
add(record) {
|
|
114
122
|
this.records.set(record.id, record);
|
|
@@ -8653,7 +8661,7 @@ var Vela = (function (exports) {
|
|
|
8653
8661
|
this.engines.set(language, engine);
|
|
8654
8662
|
}
|
|
8655
8663
|
addIndicator(source, options = {}) {
|
|
8656
|
-
const id = this.
|
|
8664
|
+
const id = this.claimIndicatorId(options.id);
|
|
8657
8665
|
const title = options.title ?? "Indicator";
|
|
8658
8666
|
const handle = new IndicatorHandleImpl(id, title, this, source);
|
|
8659
8667
|
this.handles.set(id, handle);
|
|
@@ -8675,7 +8683,7 @@ var Vela = (function (exports) {
|
|
|
8675
8683
|
const existing = this.registry.all().find((r) => r.native?.type === type);
|
|
8676
8684
|
if (existing) return this.handles.get(existing.id) ?? new IndicatorHandleImpl(existing.id, existing.title, this, void 0, type);
|
|
8677
8685
|
}
|
|
8678
|
-
const id = this.registry.nextId("native");
|
|
8686
|
+
const id = this.registry.nextId("native", (candidate) => this.handles.has(candidate));
|
|
8679
8687
|
const title = descriptor?.title ?? type;
|
|
8680
8688
|
const handle = new IndicatorHandleImpl(id, title, this, void 0, type);
|
|
8681
8689
|
this.handles.set(id, handle);
|
|
@@ -8953,6 +8961,24 @@ var Vela = (function (exports) {
|
|
|
8953
8961
|
this.events.clear();
|
|
8954
8962
|
}
|
|
8955
8963
|
// ── internals ───────────────────────────────────────────────
|
|
8964
|
+
/**
|
|
8965
|
+
* The id a new script indicator runs under: the host's when supplied, else a minted
|
|
8966
|
+
* one. A host id is opaque but must be a non-empty string, and it must not be live
|
|
8967
|
+
* on this chart — a duplicate is a programming error surfaced synchronously, never
|
|
8968
|
+
* renamed behind the caller's back (the whole point of supplying one is that
|
|
8969
|
+
* `handle.id` equals what was passed). "Live" reads both the records and the handle
|
|
8970
|
+
* map: a fail-soft handle never enters the registry but still owns its id.
|
|
8971
|
+
*/
|
|
8972
|
+
claimIndicatorId(requested) {
|
|
8973
|
+
if (requested === void 0) return this.registry.nextId("ind", (candidate) => this.handles.has(candidate));
|
|
8974
|
+
if (typeof requested !== "string" || requested.length === 0) {
|
|
8975
|
+
throw new TypeError("[vela] addIndicator: `id` must be a non-empty string");
|
|
8976
|
+
}
|
|
8977
|
+
if (this.handles.has(requested) || this.registry.get(requested)) {
|
|
8978
|
+
throw new Error(`[vela] addIndicator: indicator id "${requested}" is already live on this chart`);
|
|
8979
|
+
}
|
|
8980
|
+
return requested;
|
|
8981
|
+
}
|
|
8956
8982
|
async startIndicator(id, source, options, handle) {
|
|
8957
8983
|
try {
|
|
8958
8984
|
await this.readyPromise;
|
|
@@ -20535,7 +20561,8 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20535
20561
|
recents.unshift(hex6);
|
|
20536
20562
|
if (recents.length > 10) recents.length = 10;
|
|
20537
20563
|
}
|
|
20538
|
-
function buildColorPicker(color, theme, onChange) {
|
|
20564
|
+
function buildColorPicker(color, theme, onChange, options = {}) {
|
|
20565
|
+
const commit = options.commit ?? "live";
|
|
20539
20566
|
const parsed = splitColor(color);
|
|
20540
20567
|
let curHex = parsed.hex6;
|
|
20541
20568
|
let curAlpha = parsed.alpha;
|
|
@@ -20618,7 +20645,12 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20618
20645
|
const r = track.getBoundingClientRect();
|
|
20619
20646
|
curAlpha = Math.max(0, Math.min(1, (clientX - r.left) / r.width));
|
|
20620
20647
|
paintOpacity();
|
|
20621
|
-
emit();
|
|
20648
|
+
if (commit === "live") emit();
|
|
20649
|
+
};
|
|
20650
|
+
const endDrag = () => {
|
|
20651
|
+
if (!dragging) return;
|
|
20652
|
+
dragging = false;
|
|
20653
|
+
if (commit === "release") emit();
|
|
20622
20654
|
};
|
|
20623
20655
|
track.addEventListener("pointerdown", (e) => {
|
|
20624
20656
|
e.stopPropagation();
|
|
@@ -20629,7 +20661,8 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20629
20661
|
track.addEventListener("pointermove", (e) => {
|
|
20630
20662
|
if (dragging) onDrag(e.clientX);
|
|
20631
20663
|
});
|
|
20632
|
-
track.addEventListener("pointerup",
|
|
20664
|
+
track.addEventListener("pointerup", endDrag);
|
|
20665
|
+
track.addEventListener("pointercancel", endDrag);
|
|
20633
20666
|
function emit() {
|
|
20634
20667
|
onChange(combineColor(curHex, curAlpha));
|
|
20635
20668
|
}
|
|
@@ -20652,7 +20685,7 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20652
20685
|
return root;
|
|
20653
20686
|
}
|
|
20654
20687
|
function colorField(theme, getVal, onVal, opts) {
|
|
20655
|
-
return new ColorField({ theme, getVal, onVal, shape: opts?.shape, id: opts?.id, popover: opts?.popover }).el;
|
|
20688
|
+
return new ColorField({ theme, getVal, onVal, shape: opts?.shape, id: opts?.id, popover: opts?.popover, commit: opts?.commit }).el;
|
|
20656
20689
|
}
|
|
20657
20690
|
var ColorField = class {
|
|
20658
20691
|
constructor(opts) {
|
|
@@ -20661,6 +20694,7 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20661
20694
|
this.getVal = opts.getVal;
|
|
20662
20695
|
this.onVal = opts.onVal;
|
|
20663
20696
|
this.popoverOpts = opts.popover;
|
|
20697
|
+
this.commit = opts.commit;
|
|
20664
20698
|
const trigger = document.createElement("button");
|
|
20665
20699
|
trigger.type = "button";
|
|
20666
20700
|
if (opts.id) trigger.id = opts.id;
|
|
@@ -20700,10 +20734,15 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
20700
20734
|
boundary: this.popoverOpts?.boundary,
|
|
20701
20735
|
zIndex: this.popoverOpts?.zIndex,
|
|
20702
20736
|
className: "vela-color-field-pop",
|
|
20703
|
-
content: buildColorPicker(
|
|
20704
|
-
this.
|
|
20705
|
-
this.
|
|
20706
|
-
|
|
20737
|
+
content: buildColorPicker(
|
|
20738
|
+
this.getVal(),
|
|
20739
|
+
this.theme,
|
|
20740
|
+
(val) => {
|
|
20741
|
+
this.onVal(val);
|
|
20742
|
+
this.paint();
|
|
20743
|
+
},
|
|
20744
|
+
{ commit: this.commit }
|
|
20745
|
+
)
|
|
20707
20746
|
});
|
|
20708
20747
|
pop.show();
|
|
20709
20748
|
}
|
|
@@ -21184,7 +21223,8 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
21184
21223
|
const el2 = colorField(desc.theme, desc.get, desc.onChange, {
|
|
21185
21224
|
shape: "circle",
|
|
21186
21225
|
id: desc.id,
|
|
21187
|
-
popover: desc.popover
|
|
21226
|
+
popover: desc.popover,
|
|
21227
|
+
commit: desc.commit
|
|
21188
21228
|
});
|
|
21189
21229
|
if (desc.title) el2.title = desc.title;
|
|
21190
21230
|
return { el: el2 };
|
|
@@ -21562,7 +21602,10 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
21562
21602
|
id,
|
|
21563
21603
|
theme: this.host.theme(),
|
|
21564
21604
|
get: () => String(bagOf(row, inp)[inp.key] ?? inp.defval),
|
|
21565
|
-
onChange: (v) => emit(v)
|
|
21605
|
+
onChange: (v) => emit(v),
|
|
21606
|
+
// An input change re-executes the script over its whole history: commit the
|
|
21607
|
+
// opacity drag once on release, not once per pointer move.
|
|
21608
|
+
commit: "release"
|
|
21566
21609
|
}).el;
|
|
21567
21610
|
}
|
|
21568
21611
|
if (inp.type === "symbol") return this.buildSymbol(id, String(current), emit);
|
|
@@ -21809,10 +21852,6 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
21809
21852
|
}
|
|
21810
21853
|
/** Open a themed month calendar under `anchor` — same surface + shadow as the choice list. */
|
|
21811
21854
|
openCalendar(anchor, current, onPick) {
|
|
21812
|
-
const parsed = parseIsoDate(current);
|
|
21813
|
-
let year = parsed?.getFullYear() ?? (/* @__PURE__ */ new Date()).getFullYear();
|
|
21814
|
-
let month = parsed?.getMonth() ?? (/* @__PURE__ */ new Date()).getMonth();
|
|
21815
|
-
const selected = parsed ? isoDate(parsed) : current;
|
|
21816
21855
|
const pop = new Popover({
|
|
21817
21856
|
trigger: anchor,
|
|
21818
21857
|
theme: this.host.theme(),
|
|
@@ -21824,80 +21863,10 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
21824
21863
|
this.calendarPop = null;
|
|
21825
21864
|
this.calendarAnchor = null;
|
|
21826
21865
|
},
|
|
21827
|
-
content: (el) => {
|
|
21828
|
-
|
|
21829
|
-
|
|
21830
|
-
|
|
21831
|
-
prev3.type = "button";
|
|
21832
|
-
prev3.className = "vela-ind-cal-nav";
|
|
21833
|
-
prev3.setAttribute("aria-label", "Previous month");
|
|
21834
|
-
prev3.innerHTML = iconAt("chevron-left", 14);
|
|
21835
|
-
const next2 = document.createElement("button");
|
|
21836
|
-
next2.type = "button";
|
|
21837
|
-
next2.className = "vela-ind-cal-nav";
|
|
21838
|
-
next2.setAttribute("aria-label", "Next month");
|
|
21839
|
-
next2.innerHTML = iconAt("chevron-right", 14);
|
|
21840
|
-
const head = document.createElement("div");
|
|
21841
|
-
head.className = "vela-ind-cal-head";
|
|
21842
|
-
head.append(prev3, title, next2);
|
|
21843
|
-
const week = document.createElement("div");
|
|
21844
|
-
week.className = "vela-ind-cal-week";
|
|
21845
|
-
for (const d of WEEKDAY_LABELS) {
|
|
21846
|
-
const cell = document.createElement("span");
|
|
21847
|
-
cell.textContent = d;
|
|
21848
|
-
week.appendChild(cell);
|
|
21849
|
-
}
|
|
21850
|
-
const grid = document.createElement("div");
|
|
21851
|
-
grid.className = "vela-ind-cal-grid";
|
|
21852
|
-
const paint = () => {
|
|
21853
|
-
title.textContent = `${MONTH_LABELS[month]} ${year}`;
|
|
21854
|
-
grid.replaceChildren();
|
|
21855
|
-
const first2 = new Date(year, month, 1);
|
|
21856
|
-
const startPad = first2.getDay();
|
|
21857
|
-
const days = new Date(year, month + 1, 0).getDate();
|
|
21858
|
-
const today = isoDate(/* @__PURE__ */ new Date());
|
|
21859
|
-
for (let i = 0; i < startPad; i++) {
|
|
21860
|
-
const blank = document.createElement("span");
|
|
21861
|
-
blank.className = "vela-ind-cal-blank";
|
|
21862
|
-
grid.appendChild(blank);
|
|
21863
|
-
}
|
|
21864
|
-
for (let day = 1; day <= days; day++) {
|
|
21865
|
-
const iso = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
21866
|
-
const b = document.createElement("button");
|
|
21867
|
-
b.type = "button";
|
|
21868
|
-
b.className = "vela-ind-cal-day";
|
|
21869
|
-
b.textContent = String(day);
|
|
21870
|
-
if (iso === selected) b.dataset.checked = "1";
|
|
21871
|
-
if (iso === today) b.dataset.today = "1";
|
|
21872
|
-
b.addEventListener("click", (e) => {
|
|
21873
|
-
e.stopPropagation();
|
|
21874
|
-
pop.hide();
|
|
21875
|
-
onPick(iso);
|
|
21876
|
-
});
|
|
21877
|
-
grid.appendChild(b);
|
|
21878
|
-
}
|
|
21879
|
-
};
|
|
21880
|
-
prev3.addEventListener("click", (e) => {
|
|
21881
|
-
e.stopPropagation();
|
|
21882
|
-
month -= 1;
|
|
21883
|
-
if (month < 0) {
|
|
21884
|
-
month = 11;
|
|
21885
|
-
year -= 1;
|
|
21886
|
-
}
|
|
21887
|
-
paint();
|
|
21888
|
-
});
|
|
21889
|
-
next2.addEventListener("click", (e) => {
|
|
21890
|
-
e.stopPropagation();
|
|
21891
|
-
month += 1;
|
|
21892
|
-
if (month > 11) {
|
|
21893
|
-
month = 0;
|
|
21894
|
-
year += 1;
|
|
21895
|
-
}
|
|
21896
|
-
paint();
|
|
21897
|
-
});
|
|
21898
|
-
paint();
|
|
21899
|
-
el.append(head, week, grid);
|
|
21900
|
-
}
|
|
21866
|
+
content: (el) => fillCalendar(el, current, (iso) => {
|
|
21867
|
+
pop.hide();
|
|
21868
|
+
onPick(iso);
|
|
21869
|
+
})
|
|
21901
21870
|
});
|
|
21902
21871
|
this.calendarPop = pop;
|
|
21903
21872
|
this.calendarAnchor = anchor;
|
|
@@ -22006,7 +21975,7 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
22006
21975
|
var CALENDAR_SVG = iconAt("calendar", 14);
|
|
22007
21976
|
var CLOCK_SVG = iconAt("clock", 14);
|
|
22008
21977
|
var DIALOG_STYLE_ID2 = "vela-ind-dialog-styles";
|
|
22009
|
-
var DIALOG_STYLE_REV = "
|
|
21978
|
+
var DIALOG_STYLE_REV = "30";
|
|
22010
21979
|
var LEGEND_ICON_PX = 16;
|
|
22011
21980
|
function ensureDialogStyles() {
|
|
22012
21981
|
if (typeof document === "undefined") return;
|
|
@@ -22022,8 +21991,12 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
22022
21991
|
.vela-ind-combo-chevron{position:absolute;right:0;top:0;bottom:0;width:26px;border:none;background:transparent;color:inherit;opacity:0.55;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;}
|
|
22023
21992
|
.vela-ind-combo-chevron:hover{opacity:0.9;}
|
|
22024
21993
|
.vela-ind-cal{background:var(--vela-bg);color:var(--vela-fg);border:none;border-radius:6px;box-shadow:var(--vela-shadow);font:14px var(--vela-font);padding:10px 12px;user-select:none;}
|
|
21994
|
+
.vela-ind-cal [hidden]{display:none !important;}
|
|
22025
21995
|
.vela-ind-cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;}
|
|
22026
|
-
.vela-ind-cal-title{flex:1;
|
|
21996
|
+
.vela-ind-cal-title{flex:1;display:flex;align-items:center;justify-content:center;gap:2px;min-width:0;}
|
|
21997
|
+
.vela-ind-cal-switch{border:none;background:transparent;color:var(--vela-fg-bright);font:inherit;font-weight:600;font-size:14px;padding:2px 6px;border-radius:4px;cursor:pointer;}
|
|
21998
|
+
.vela-ind-cal-switch:not(:disabled):hover{background:var(--vela-hover);}
|
|
21999
|
+
.vela-ind-cal-switch:disabled{cursor:default;}
|
|
22027
22000
|
.vela-ind-cal-nav{width:24px;height:24px;border:none;background:transparent;color:var(--vela-fg-muted);border-radius:4px;padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;}
|
|
22028
22001
|
.vela-ind-cal-nav:hover{background:var(--vela-hover);color:var(--vela-fg-bright);}
|
|
22029
22002
|
.vela-ind-cal-week,.vela-ind-cal-grid{display:grid;grid-template-columns:repeat(7,28px);gap:2px;}
|
|
@@ -22034,6 +22007,12 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
22034
22007
|
.vela-ind-cal-day:hover{background:var(--vela-hover);}
|
|
22035
22008
|
.vela-ind-cal-day[data-checked]{background:var(--vela-hover-strong);color:var(--vela-fg-bright);}
|
|
22036
22009
|
.vela-ind-cal-day[data-today]:not([data-checked]){box-shadow:inset 0 0 0 1px var(--vela-border-strong);}
|
|
22010
|
+
.vela-ind-cal-cells{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;width:calc(7 * 28px + 6 * 2px);}
|
|
22011
|
+
.vela-ind-cal-cell{height:36px;border:none;background:transparent;color:inherit;border-radius:4px;padding:0 4px;cursor:pointer;font:inherit;font-size:14px;}
|
|
22012
|
+
.vela-ind-cal-cell:hover{background:var(--vela-hover);}
|
|
22013
|
+
.vela-ind-cal-cell[data-checked]{background:var(--vela-hover-strong);color:var(--vela-fg-bright);}
|
|
22014
|
+
.vela-ind-cal-cell[data-today]:not([data-checked]){box-shadow:inset 0 0 0 1px var(--vela-border-strong);}
|
|
22015
|
+
.vela-ind-cal-cell[data-outside]{opacity:0.45;}
|
|
22037
22016
|
${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
22038
22017
|
.vela-ind-tab{font-weight:600;font-size:13px;line-height:20px;transition:color var(--vela-dur-fast) ease,border-color var(--vela-dur-fast) ease;}
|
|
22039
22018
|
.vela-ind-tab:not(.vela-ind-tab-active):hover{color:var(--vela-fg-bright);}
|
|
@@ -22068,6 +22047,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22068
22047
|
return { value: v, label: v };
|
|
22069
22048
|
});
|
|
22070
22049
|
var MONTH_LABELS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
22050
|
+
var MONTH_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
22071
22051
|
var WEEKDAY_LABELS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
22072
22052
|
function normalizeDateInput(raw) {
|
|
22073
22053
|
const t = raw.trim();
|
|
@@ -22089,6 +22069,151 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22089
22069
|
function isoDate(d) {
|
|
22090
22070
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
22091
22071
|
}
|
|
22072
|
+
function fillCalendar(el, current, onPick) {
|
|
22073
|
+
const today = /* @__PURE__ */ new Date();
|
|
22074
|
+
const selected = parseIsoDate(current);
|
|
22075
|
+
let year = selected?.getFullYear() ?? today.getFullYear();
|
|
22076
|
+
let month = selected?.getMonth() ?? today.getMonth();
|
|
22077
|
+
let mode = "date";
|
|
22078
|
+
const prev3 = document.createElement("button");
|
|
22079
|
+
prev3.type = "button";
|
|
22080
|
+
prev3.className = "vela-ind-cal-nav";
|
|
22081
|
+
prev3.innerHTML = iconAt("chevron-left", 14);
|
|
22082
|
+
const next2 = document.createElement("button");
|
|
22083
|
+
next2.type = "button";
|
|
22084
|
+
next2.className = "vela-ind-cal-nav";
|
|
22085
|
+
next2.innerHTML = iconAt("chevron-right", 14);
|
|
22086
|
+
const monthBtn = document.createElement("button");
|
|
22087
|
+
monthBtn.type = "button";
|
|
22088
|
+
monthBtn.className = "vela-ind-cal-switch";
|
|
22089
|
+
monthBtn.setAttribute("aria-label", "Choose month");
|
|
22090
|
+
const yearBtn = document.createElement("button");
|
|
22091
|
+
yearBtn.type = "button";
|
|
22092
|
+
yearBtn.className = "vela-ind-cal-switch";
|
|
22093
|
+
yearBtn.setAttribute("aria-label", "Choose year");
|
|
22094
|
+
const title = document.createElement("div");
|
|
22095
|
+
title.className = "vela-ind-cal-title";
|
|
22096
|
+
title.append(monthBtn, yearBtn);
|
|
22097
|
+
const head = document.createElement("div");
|
|
22098
|
+
head.className = "vela-ind-cal-head";
|
|
22099
|
+
head.append(prev3, title, next2);
|
|
22100
|
+
const week = document.createElement("div");
|
|
22101
|
+
week.className = "vela-ind-cal-week";
|
|
22102
|
+
for (const d of WEEKDAY_LABELS) {
|
|
22103
|
+
const cell = document.createElement("span");
|
|
22104
|
+
cell.textContent = d;
|
|
22105
|
+
week.appendChild(cell);
|
|
22106
|
+
}
|
|
22107
|
+
const grid = document.createElement("div");
|
|
22108
|
+
const paint = () => {
|
|
22109
|
+
const decade = Math.floor(year / 10) * 10;
|
|
22110
|
+
monthBtn.hidden = mode !== "date";
|
|
22111
|
+
monthBtn.textContent = MONTH_LABELS[month] ?? "";
|
|
22112
|
+
yearBtn.textContent = mode === "year" ? `${decade}-${decade + 9}` : String(year);
|
|
22113
|
+
yearBtn.disabled = mode === "year";
|
|
22114
|
+
week.hidden = mode !== "date";
|
|
22115
|
+
prev3.setAttribute("aria-label", mode === "date" ? "Previous month" : mode === "month" ? "Previous year" : "Previous decade");
|
|
22116
|
+
next2.setAttribute("aria-label", mode === "date" ? "Next month" : mode === "month" ? "Next year" : "Next decade");
|
|
22117
|
+
grid.className = mode === "date" ? "vela-ind-cal-grid" : "vela-ind-cal-cells";
|
|
22118
|
+
grid.replaceChildren();
|
|
22119
|
+
if (mode === "date") {
|
|
22120
|
+
const startPad = new Date(year, month, 1).getDay();
|
|
22121
|
+
const days = new Date(year, month + 1, 0).getDate();
|
|
22122
|
+
const todayIso = isoDate(today);
|
|
22123
|
+
const selectedIso = selected ? isoDate(selected) : "";
|
|
22124
|
+
for (let i = 0; i < startPad; i++) {
|
|
22125
|
+
const blank = document.createElement("span");
|
|
22126
|
+
blank.className = "vela-ind-cal-blank";
|
|
22127
|
+
grid.appendChild(blank);
|
|
22128
|
+
}
|
|
22129
|
+
for (let day = 1; day <= days; day++) {
|
|
22130
|
+
const iso = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
22131
|
+
const b = document.createElement("button");
|
|
22132
|
+
b.type = "button";
|
|
22133
|
+
b.className = "vela-ind-cal-day";
|
|
22134
|
+
b.textContent = String(day);
|
|
22135
|
+
if (iso === selectedIso) b.dataset.checked = "1";
|
|
22136
|
+
if (iso === todayIso) b.dataset.today = "1";
|
|
22137
|
+
b.addEventListener("click", (e) => {
|
|
22138
|
+
e.stopPropagation();
|
|
22139
|
+
onPick(iso);
|
|
22140
|
+
});
|
|
22141
|
+
grid.appendChild(b);
|
|
22142
|
+
}
|
|
22143
|
+
return;
|
|
22144
|
+
}
|
|
22145
|
+
if (mode === "month") {
|
|
22146
|
+
for (let m = 0; m < 12; m++) {
|
|
22147
|
+
const b = document.createElement("button");
|
|
22148
|
+
b.type = "button";
|
|
22149
|
+
b.className = "vela-ind-cal-cell";
|
|
22150
|
+
b.textContent = MONTH_SHORT[m] ?? "";
|
|
22151
|
+
if (selected?.getFullYear() === year && selected.getMonth() === m) b.dataset.checked = "1";
|
|
22152
|
+
if (today.getFullYear() === year && today.getMonth() === m) b.dataset.today = "1";
|
|
22153
|
+
b.addEventListener("click", (e) => {
|
|
22154
|
+
e.stopPropagation();
|
|
22155
|
+
month = m;
|
|
22156
|
+
mode = "date";
|
|
22157
|
+
paint();
|
|
22158
|
+
});
|
|
22159
|
+
grid.appendChild(b);
|
|
22160
|
+
}
|
|
22161
|
+
return;
|
|
22162
|
+
}
|
|
22163
|
+
for (let y = decade - 1; y <= decade + 10; y++) {
|
|
22164
|
+
const b = document.createElement("button");
|
|
22165
|
+
b.type = "button";
|
|
22166
|
+
b.className = "vela-ind-cal-cell";
|
|
22167
|
+
b.textContent = String(y);
|
|
22168
|
+
if (y < decade || y > decade + 9) b.dataset.outside = "1";
|
|
22169
|
+
if (selected?.getFullYear() === y) b.dataset.checked = "1";
|
|
22170
|
+
if (today.getFullYear() === y) b.dataset.today = "1";
|
|
22171
|
+
b.addEventListener("click", (e) => {
|
|
22172
|
+
e.stopPropagation();
|
|
22173
|
+
year = y;
|
|
22174
|
+
mode = "month";
|
|
22175
|
+
paint();
|
|
22176
|
+
});
|
|
22177
|
+
grid.appendChild(b);
|
|
22178
|
+
}
|
|
22179
|
+
};
|
|
22180
|
+
const step = (dir) => {
|
|
22181
|
+
if (mode === "date") {
|
|
22182
|
+
month += dir;
|
|
22183
|
+
if (month < 0) {
|
|
22184
|
+
month = 11;
|
|
22185
|
+
year -= 1;
|
|
22186
|
+
}
|
|
22187
|
+
if (month > 11) {
|
|
22188
|
+
month = 0;
|
|
22189
|
+
year += 1;
|
|
22190
|
+
}
|
|
22191
|
+
} else {
|
|
22192
|
+
year += mode === "month" ? dir : dir * 10;
|
|
22193
|
+
}
|
|
22194
|
+
paint();
|
|
22195
|
+
};
|
|
22196
|
+
prev3.addEventListener("click", (e) => {
|
|
22197
|
+
e.stopPropagation();
|
|
22198
|
+
step(-1);
|
|
22199
|
+
});
|
|
22200
|
+
next2.addEventListener("click", (e) => {
|
|
22201
|
+
e.stopPropagation();
|
|
22202
|
+
step(1);
|
|
22203
|
+
});
|
|
22204
|
+
monthBtn.addEventListener("click", (e) => {
|
|
22205
|
+
e.stopPropagation();
|
|
22206
|
+
mode = "month";
|
|
22207
|
+
paint();
|
|
22208
|
+
});
|
|
22209
|
+
yearBtn.addEventListener("click", (e) => {
|
|
22210
|
+
e.stopPropagation();
|
|
22211
|
+
mode = "year";
|
|
22212
|
+
paint();
|
|
22213
|
+
});
|
|
22214
|
+
paint();
|
|
22215
|
+
el.append(head, week, grid);
|
|
22216
|
+
}
|
|
22092
22217
|
function normalizeTimeInput(raw) {
|
|
22093
22218
|
const t = raw.trim();
|
|
22094
22219
|
const m = /^(\d{1,2}):(\d{2})$/.exec(t) ?? /^(\d{2})(\d{2})$/.exec(t);
|
|
@@ -23370,10 +23495,12 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23370
23495
|
var PREMARKET_SHADE = withAlpha(WARNING, 0.08);
|
|
23371
23496
|
var POSTMARKET_SHADE = withAlpha(ACCENT, 0.08);
|
|
23372
23497
|
var EXTENDED_SHADE = POSTMARKET_SHADE;
|
|
23498
|
+
var DEFAULT_MARGINS = { top: 10, bottom: 10, right: 10 };
|
|
23373
23499
|
function defaultChartStyle() {
|
|
23374
23500
|
return {
|
|
23375
23501
|
chartTypes: {},
|
|
23376
23502
|
fontSize: 11,
|
|
23503
|
+
margins: { ...DEFAULT_MARGINS },
|
|
23377
23504
|
gridVert: { visible: true, color: null },
|
|
23378
23505
|
gridHorz: { visible: true, color: null },
|
|
23379
23506
|
borderColor: null,
|
|
@@ -23497,6 +23624,12 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23497
23624
|
function clampSpacing(v) {
|
|
23498
23625
|
return v < 0.1 ? 0.1 : v > 10 ? 10 : v;
|
|
23499
23626
|
}
|
|
23627
|
+
function clampMarginPct(v) {
|
|
23628
|
+
return v < 0 ? 0 : v > 40 ? 40 : v;
|
|
23629
|
+
}
|
|
23630
|
+
function clampMarginBars(v) {
|
|
23631
|
+
return Math.round(v < 0 ? 0 : v > 200 ? 200 : v);
|
|
23632
|
+
}
|
|
23500
23633
|
function factoryResetConfig(factory, priceStyle = factory.series.style) {
|
|
23501
23634
|
const bag = {};
|
|
23502
23635
|
for (const t of chartTypes()) {
|
|
@@ -23545,6 +23678,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23545
23678
|
const ps = asObject(p.priceScale);
|
|
23546
23679
|
const anim = asObject(p.animations);
|
|
23547
23680
|
const panes = asObject(p.panes);
|
|
23681
|
+
const margins = asObject(p.margins);
|
|
23548
23682
|
const trades = asObject(p.trades);
|
|
23549
23683
|
const ts = asObject(p.timeScale);
|
|
23550
23684
|
const marks = asObject(p.marks);
|
|
@@ -23604,6 +23738,11 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23604
23738
|
panes: {
|
|
23605
23739
|
separatorColor: isColor(panes.separatorColor) ? panes.separatorColor : base.panes.separatorColor
|
|
23606
23740
|
},
|
|
23741
|
+
margins: {
|
|
23742
|
+
top: isNum(margins.top) ? clampMarginPct(margins.top) : base.margins.top,
|
|
23743
|
+
bottom: isNum(margins.bottom) ? clampMarginPct(margins.bottom) : base.margins.bottom,
|
|
23744
|
+
right: isNum(margins.right) ? clampMarginBars(margins.right) : base.margins.right
|
|
23745
|
+
},
|
|
23607
23746
|
trades: {
|
|
23608
23747
|
visible: isBool(trades.visible) ? trades.visible : base.trades.visible,
|
|
23609
23748
|
labels: isBool(trades.labels) ? trades.labels : base.trades.labels,
|
|
@@ -28974,6 +29113,10 @@ void main() {
|
|
|
28974
29113
|
"canvas.grid",
|
|
28975
29114
|
"canvas.grid.vertical",
|
|
28976
29115
|
"canvas.grid.horizontal",
|
|
29116
|
+
"canvas.margins",
|
|
29117
|
+
"canvas.margins.top",
|
|
29118
|
+
"canvas.margins.bottom",
|
|
29119
|
+
"canvas.margins.right",
|
|
28977
29120
|
"canvas.theme"
|
|
28978
29121
|
];
|
|
28979
29122
|
function settingsIdCatalog(hostSections, markGroups = []) {
|
|
@@ -29504,6 +29647,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29504
29647
|
body.append(sid(this.toggleRow("Horizontal", config.grid.horzLines.visible, (v) => this.emit({ grid: { horzLines: { visible: v } } }), [
|
|
29505
29648
|
this.swatch(config.grid.horzLines.color, (v) => this.emit({ grid: { horzLines: { color: v } } }))
|
|
29506
29649
|
]), "canvas.grid.horizontal"));
|
|
29650
|
+
body.append(sid(this.sectionTitle("Margins"), "canvas.margins"));
|
|
29651
|
+
body.append(sid(this.numberRow("Top", config.margins.top, 0, 40, 1, (v) => this.emit({ margins: { top: v } }), "%"), "canvas.margins.top"));
|
|
29652
|
+
body.append(sid(this.numberRow("Bottom", config.margins.bottom, 0, 40, 1, (v) => this.emit({ margins: { bottom: v } }), "%"), "canvas.margins.bottom"));
|
|
29653
|
+
body.append(sid(this.numberRow("Right", config.margins.right, 0, 200, 1, (v) => this.emit({ margins: { right: v } }), "bars"), "canvas.margins.right"));
|
|
29507
29654
|
if (this.themeControl) {
|
|
29508
29655
|
const tc = this.themeControl;
|
|
29509
29656
|
body.append(sid(this.sectionTitle("Theme"), "canvas.theme"));
|
|
@@ -30075,23 +30222,16 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
30075
30222
|
this.hintTips.push(dispose);
|
|
30076
30223
|
return el;
|
|
30077
30224
|
}
|
|
30078
|
-
|
|
30079
|
-
|
|
30080
|
-
|
|
30081
|
-
|
|
30082
|
-
|
|
30083
|
-
|
|
30084
|
-
|
|
30085
|
-
|
|
30086
|
-
|
|
30087
|
-
|
|
30088
|
-
step,
|
|
30089
|
-
fill: false,
|
|
30090
|
-
commit: "live",
|
|
30091
|
-
steppers: true,
|
|
30092
|
-
onChange
|
|
30093
|
-
}).el
|
|
30094
|
-
});
|
|
30225
|
+
/** `unit` (optional) trails the input as muted text — "%", "bars". */
|
|
30226
|
+
numberRow(label, value, min2, max2, step, onChange, unit) {
|
|
30227
|
+
const controls = [buildFieldControl({ kind: "number", value, min: min2, max: max2, step, fill: false, commit: "live", steppers: true, onChange }).el];
|
|
30228
|
+
if (unit) {
|
|
30229
|
+
const u = document.createElement("span");
|
|
30230
|
+
u.textContent = unit;
|
|
30231
|
+
u.style.cssText = "color:var(--vela-fg-muted);";
|
|
30232
|
+
controls.push(u);
|
|
30233
|
+
}
|
|
30234
|
+
return this.rowWith(label, controls);
|
|
30095
30235
|
}
|
|
30096
30236
|
/** A dropdown whose option values differ from their display labels. */
|
|
30097
30237
|
selectRowLabeled(label, value, options, onChange) {
|
|
@@ -35610,9 +35750,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35610
35750
|
}
|
|
35611
35751
|
|
|
35612
35752
|
// src/renderers/native/core/autoscale.ts
|
|
35613
|
-
|
|
35614
|
-
var MARGIN_BOTTOM = 1 / 7;
|
|
35615
|
-
function computePaneScale(models, bars, includeCandles, i0, i1, drawings, log = false, offsetOf = () => 0) {
|
|
35753
|
+
function computePaneScale(models, bars, includeCandles, i0, i1, drawings, log = false, offsetOf = () => 0, margins = DEFAULT_MARGINS) {
|
|
35616
35754
|
let min2 = Infinity;
|
|
35617
35755
|
let max2 = -Infinity;
|
|
35618
35756
|
const consider = (v) => {
|
|
@@ -35647,14 +35785,17 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35647
35785
|
const pad = Math.abs(min2) * 0.1 || 1;
|
|
35648
35786
|
return { min: min2 - pad, max: max2 + pad, log: log && min2 - pad > 0 };
|
|
35649
35787
|
}
|
|
35788
|
+
const content = Math.max(0.1, 1 - (margins.top + margins.bottom) / 100);
|
|
35789
|
+
const above = margins.top / 100 / content;
|
|
35790
|
+
const below = margins.bottom / 100 / content;
|
|
35650
35791
|
if (log && min2 > 0) {
|
|
35651
35792
|
const lmin = Math.log(min2);
|
|
35652
35793
|
const lmax = Math.log(max2);
|
|
35653
35794
|
const lspan = lmax - lmin;
|
|
35654
|
-
return { min: Math.exp(lmin - lspan *
|
|
35795
|
+
return { min: Math.exp(lmin - lspan * below), max: Math.exp(lmax + lspan * above), log: true };
|
|
35655
35796
|
}
|
|
35656
35797
|
const span = max2 - min2;
|
|
35657
|
-
return { min: min2 - span *
|
|
35798
|
+
return { min: min2 - span * below, max: max2 + span * above };
|
|
35658
35799
|
}
|
|
35659
35800
|
function considerSeries(s, i0, i1, off, consider) {
|
|
35660
35801
|
if (!seriesInScale(s)) return;
|
|
@@ -37481,6 +37622,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37481
37622
|
intro: this.intro.style !== false
|
|
37482
37623
|
},
|
|
37483
37624
|
panes: { separatorColor: s.separatorColor ?? t.borderColor },
|
|
37625
|
+
margins: { ...s.margins },
|
|
37484
37626
|
trades: {
|
|
37485
37627
|
visible: this.scene.tradeMarkers.visible,
|
|
37486
37628
|
labels: this.scene.tradeMarkers.labels,
|
|
@@ -37593,6 +37735,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37593
37735
|
this.animAutoscale.toggle(next2.animations.autoscale);
|
|
37594
37736
|
this.intro = { style: next2.animations.intro ? this.introOnStyle : false, duration: this.intro.duration || INTRO_DURATION_DEFAULT_MS };
|
|
37595
37737
|
s.separatorColor = keepInherit(s.separatorColor, next2.panes.separatorColor, prevTheme.borderColor);
|
|
37738
|
+
if (next2.margins.right !== s.margins.right && this.coords.barCount > 0) {
|
|
37739
|
+
this.applyViewport({ barSpacing: this.coords.getViewport().barSpacing, rightOffset: next2.margins.right });
|
|
37740
|
+
}
|
|
37741
|
+
s.margins = { ...next2.margins };
|
|
37596
37742
|
this.scene.tradeMarkers = {
|
|
37597
37743
|
visible: next2.trades.visible,
|
|
37598
37744
|
labels: next2.trades.labels,
|
|
@@ -37836,7 +37982,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37836
37982
|
/** Glide the view back to the most recent bars, keeping the current zoom (barSpacing). */
|
|
37837
37983
|
scrollToRealtime() {
|
|
37838
37984
|
if (this.coords.barCount === 0) return;
|
|
37839
|
-
this.glideRightOffset(
|
|
37985
|
+
this.glideRightOffset(this.scene.style.margins.right);
|
|
37840
37986
|
}
|
|
37841
37987
|
/** Ease rightOffset to `target` at constant zoom (see animTick's scroll glide);
|
|
37842
37988
|
* instant when the scroll glide is off. Shared by scroll-to-latest and panBy. */
|
|
@@ -39778,6 +39924,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39778
39924
|
const pricePane = panes.find((p) => p.kind === "price") ?? null;
|
|
39779
39925
|
this.chrome.prepare(this.scene, this.coords, this.theme);
|
|
39780
39926
|
const animating = this.animator.active;
|
|
39927
|
+
const margins = this.scene.style.margins;
|
|
39781
39928
|
for (const pane of panes) {
|
|
39782
39929
|
if (pane.manualScale) {
|
|
39783
39930
|
pane.scaleTarget = pane.manualScale;
|
|
@@ -39793,7 +39940,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39793
39940
|
if (or2) dr = dr ? { min: Math.min(dr.min, or2.min), max: Math.max(dr.max, or2.max) } : or2;
|
|
39794
39941
|
}
|
|
39795
39942
|
const includeCandles = pane.kind === "price" && (!this.scene.candlesHidden || this.priceLayersAnchoredToBars(masterModels) || !this.paneHasMeasurableContent(masterModels, dr));
|
|
39796
|
-
pane.scaleTarget = computePaneScale(masterModels, this.bars, includeCandles, i0, i1, dr, paneLogScale(this.scene, pane), (id) => this.scene.offsetOf(id));
|
|
39943
|
+
pane.scaleTarget = computePaneScale(masterModels, this.bars, includeCandles, i0, i1, dr, paneLogScale(this.scene, pane), (id) => this.scene.offsetOf(id), margins);
|
|
39797
39944
|
pane.percentBaseline = pane.kind === "price" ? this.bars[i0]?.close ?? 0 : this.firstVisibleValue(masterModels, i0);
|
|
39798
39945
|
pane.axisFormat = void 0;
|
|
39799
39946
|
pane.axisBands = void 0;
|
|
@@ -39804,7 +39951,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39804
39951
|
pane.axisFormat = "volume";
|
|
39805
39952
|
}
|
|
39806
39953
|
} else if (this.layerNativesOwnPane(pane, masterModels)) {
|
|
39807
|
-
pane.scaleTarget = computePaneScale([], this.bars, true, i0, i1, dr, paneLogScale(this.scene, pane), (id) => this.scene.offsetOf(id));
|
|
39954
|
+
pane.scaleTarget = computePaneScale([], this.bars, true, i0, i1, dr, paneLogScale(this.scene, pane), (id) => this.scene.offsetOf(id), margins);
|
|
39808
39955
|
pane.percentBaseline = this.bars[i0]?.close ?? 0;
|
|
39809
39956
|
if (masterModels.every((m) => m.paneAxis != null)) {
|
|
39810
39957
|
pane.axisFormat = "none";
|
|
@@ -39833,7 +39980,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39833
39980
|
continue;
|
|
39834
39981
|
}
|
|
39835
39982
|
const mdr = this.chrome.paneDrawingsRange([model], this.scene, false, vr);
|
|
39836
|
-
sl.scaleTarget = computePaneScale([model], this.bars, false, i0, i1, mdr, false, (id) => this.scene.offsetOf(id));
|
|
39983
|
+
sl.scaleTarget = computePaneScale([model], this.bars, false, i0, i1, mdr, false, (id) => this.scene.offsetOf(id), margins);
|
|
39837
39984
|
if (!animating || !sl.initialized) {
|
|
39838
39985
|
sl.scale = { ...sl.scaleTarget };
|
|
39839
39986
|
sl.initialized = true;
|
|
@@ -39874,13 +40021,13 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39874
40021
|
for (const pane of this.scene.panes.values()) pane.manualScale = null;
|
|
39875
40022
|
for (const sl of this.scene.indicatorScales.values()) sl.manualScale = null;
|
|
39876
40023
|
const visibleBars = Math.min(n, 200);
|
|
39877
|
-
const rightOffset =
|
|
40024
|
+
const rightOffset = this.scene.style.margins.right;
|
|
39878
40025
|
const v = this.clampViewport(w / ((visibleBars + rightOffset) * this.coords.spacingScale), rightOffset);
|
|
39879
40026
|
this.coords.setViewport(v);
|
|
39880
40027
|
this.targetBarSpacing = v.barSpacing;
|
|
39881
40028
|
}
|
|
39882
40029
|
/** Re-frame after a series replacement (a symbol/timeframe switch): keep the user's
|
|
39883
|
-
* zoom (bar spacing), re-anchor the newest bars at the
|
|
40030
|
+
* zoom (bar spacing), re-anchor the newest bars at the configured right margin.
|
|
39884
40031
|
* `clampViewport`'s fit-all-bars floor deliberately does NOT apply — a progressive
|
|
39885
40032
|
* head may still be backfilling toward the previous depth, and raising the spacing
|
|
39886
40033
|
* to its temporary bar count would lose the zoom this exists to keep. */
|
|
@@ -39889,7 +40036,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
39889
40036
|
this.panVelocity = 0;
|
|
39890
40037
|
for (const pane of this.scene.panes.values()) pane.manualScale = null;
|
|
39891
40038
|
for (const sl of this.scene.indicatorScales.values()) sl.manualScale = null;
|
|
39892
|
-
const v = { barSpacing: clampBarSpacing(this.coords.getViewport().barSpacing), rightOffset:
|
|
40039
|
+
const v = { barSpacing: clampBarSpacing(this.coords.getViewport().barSpacing), rightOffset: this.scene.style.margins.right };
|
|
39893
40040
|
this.coords.setViewport(v);
|
|
39894
40041
|
this.targetBarSpacing = v.barSpacing;
|
|
39895
40042
|
}
|
|
@@ -43003,6 +43150,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
43003
43150
|
}
|
|
43004
43151
|
|
|
43005
43152
|
// src/Vela.ts
|
|
43153
|
+
var asError = (err) => err instanceof Error ? err : new Error(String(err));
|
|
43006
43154
|
var Vela = class {
|
|
43007
43155
|
constructor(container, options = {}, deps = {}) {
|
|
43008
43156
|
registerBuiltinChartTypes();
|
|
@@ -43126,7 +43274,12 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
43126
43274
|
* fetch from — the same relationship `script:run` has to `context:changed`.
|
|
43127
43275
|
*/
|
|
43128
43276
|
runScript(source, options) {
|
|
43129
|
-
|
|
43277
|
+
let handle;
|
|
43278
|
+
try {
|
|
43279
|
+
handle = this.addIndicator(source, options);
|
|
43280
|
+
} catch (err) {
|
|
43281
|
+
return Promise.resolve({ ok: false, run: null, error: asError(err), onUpdate: () => () => void 0, remove: () => void 0 });
|
|
43282
|
+
}
|
|
43130
43283
|
const updates = /* @__PURE__ */ new Set();
|
|
43131
43284
|
const drop = () => {
|
|
43132
43285
|
try {
|
|
@@ -43170,7 +43323,12 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
43170
43323
|
});
|
|
43171
43324
|
}
|
|
43172
43325
|
runIndicator(source, options) {
|
|
43173
|
-
|
|
43326
|
+
let handle;
|
|
43327
|
+
try {
|
|
43328
|
+
handle = this.addIndicator(source, options);
|
|
43329
|
+
} catch (err) {
|
|
43330
|
+
return Promise.resolve({ ok: false, handle: null, error: asError(err), context: null });
|
|
43331
|
+
}
|
|
43174
43332
|
return new Promise((resolve) => {
|
|
43175
43333
|
const offReady = handle.on("ready", () => {
|
|
43176
43334
|
offReady();
|