@luxalgo/vela 0.7.4 → 0.7.5
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-CVpN5sCq.d.ts → DataProvider-DLeFs1gE.d.ts} +1 -1
- package/dist/{DataProvider-RF1axuy1.d.cts → DataProvider-Dut6lXGM.d.cts} +1 -1
- package/dist/{chunk-DUURH3RN.js → chunk-MCLI6B3S.js} +226 -66
- package/dist/{chunk-CSFNKXUW.js → chunk-MNG5XPLV.js} +6 -1
- package/dist/{contributions-CspPrMAJ.d.ts → contributions-CEkgJKTU.d.ts} +7 -3
- package/dist/{contributions-DpZeu7KP.d.cts → contributions-DYtiRtES.d.cts} +7 -3
- package/dist/index.cjs +226 -66
- package/dist/index.d.cts +19 -6
- package/dist/index.d.ts +19 -6
- package/dist/index.js +1 -1
- package/dist/{options-XVpfr9HV.d.cts → options-DNBoMKkX.d.cts} +8 -0
- package/dist/{options-XVpfr9HV.d.ts → options-DNBoMKkX.d.ts} +8 -0
- package/dist/{plugin-BoLOkblF.d.ts → plugin-CLn--oP6.d.ts} +3 -3
- package/dist/{plugin-D07HD2GL.d.cts → plugin-DtkeQVAO.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-CPa_hmhd.d.ts → statusline-model-DypGXjtr.d.ts} +3 -3
- package/dist/{statusline-model-Bd4qKuD6.d.cts → statusline-model-gA__yaog.d.cts} +3 -3
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/vela.global.js +226 -66
- package/dist/vela.global.min.js +53 -49
- package/dist/widget.cjs +231 -66
- package/dist/widget.d.cts +6 -6
- package/dist/widget.d.ts +6 -6
- package/dist/widget.js +3 -3
- package/dist/workspace.cjs +231 -66
- package/dist/workspace.d.cts +5 -5
- package/dist/workspace.d.ts +5 -5
- package/dist/workspace.js +2 -2
- package/package.json +1 -1
|
@@ -5356,6 +5356,17 @@ function hasOwnCandlePaint(style) {
|
|
|
5356
5356
|
for (const t of chartTypes()) if (t.id === style) return (t.basePainting ?? "candles") === "candles";
|
|
5357
5357
|
return false;
|
|
5358
5358
|
}
|
|
5359
|
+
var CANDLE_OVERRIDE_KEYS = [
|
|
5360
|
+
"candleUpColor",
|
|
5361
|
+
"candleDownColor",
|
|
5362
|
+
"candleBodyVisible",
|
|
5363
|
+
"candleBorderVisible",
|
|
5364
|
+
"candleBorderUpColor",
|
|
5365
|
+
"candleBorderDownColor",
|
|
5366
|
+
"candleWickVisible",
|
|
5367
|
+
"candleWickUpColor",
|
|
5368
|
+
"candleWickDownColor"
|
|
5369
|
+
];
|
|
5359
5370
|
function candleOverrideFor(style, bags) {
|
|
5360
5371
|
if (!hasOwnCandlePaint(style)) return null;
|
|
5361
5372
|
const bag = bags[style] ?? {};
|
|
@@ -5427,7 +5438,7 @@ function clampLevel(v) {
|
|
|
5427
5438
|
function clampSpacing(v) {
|
|
5428
5439
|
return v < 0.1 ? 0.1 : v > 10 ? 10 : v;
|
|
5429
5440
|
}
|
|
5430
|
-
function factoryResetConfig(factory) {
|
|
5441
|
+
function factoryResetConfig(factory, priceStyle = factory.series.style) {
|
|
5431
5442
|
const bag = {};
|
|
5432
5443
|
for (const t of chartTypes()) {
|
|
5433
5444
|
const section = t.settings;
|
|
@@ -5449,10 +5460,16 @@ function factoryResetConfig(factory) {
|
|
|
5449
5460
|
if (!section.instances) addRows(section.rows);
|
|
5450
5461
|
bag[t.id] = defaults;
|
|
5451
5462
|
}
|
|
5463
|
+
for (const t of chartTypes()) {
|
|
5464
|
+
if (!hasOwnCandlePaint(t.id)) continue;
|
|
5465
|
+
const defaults = bag[t.id] ?? {};
|
|
5466
|
+
for (const key of CANDLE_OVERRIDE_KEYS) defaults[key] = null;
|
|
5467
|
+
bag[t.id] = defaults;
|
|
5468
|
+
}
|
|
5452
5469
|
for (const [typeId, vals] of Object.entries(factory.chartTypes)) {
|
|
5453
5470
|
bag[typeId] = { ...bag[typeId] ?? {}, ...vals };
|
|
5454
5471
|
}
|
|
5455
|
-
return { ...factory, chartTypes: bag };
|
|
5472
|
+
return { ...factory, chartTypes: bag, series: { ...factory.series, style: priceStyle } };
|
|
5456
5473
|
}
|
|
5457
5474
|
function mergeConfig(base, patch) {
|
|
5458
5475
|
const p = asObject(patch);
|
|
@@ -7819,6 +7836,42 @@ function drawTextLines(ctx, lines, x, firstY, step, color) {
|
|
|
7819
7836
|
for (let i = 0; i < lines.length; i += 1) ctx.fillText(lines[i], x, firstY + i * step);
|
|
7820
7837
|
}
|
|
7821
7838
|
|
|
7839
|
+
// src/core/marks/visibility.ts
|
|
7840
|
+
function markGroupOwnVisible(choices, groupId, groups) {
|
|
7841
|
+
const chosen = choices[groupId];
|
|
7842
|
+
if (typeof chosen === "boolean") return chosen;
|
|
7843
|
+
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
7844
|
+
}
|
|
7845
|
+
function markGroupVisible(choices, groupId, groups) {
|
|
7846
|
+
if (groupId === void 0) return true;
|
|
7847
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7848
|
+
let id = groupId;
|
|
7849
|
+
while (id !== void 0 && !seen.has(id)) {
|
|
7850
|
+
seen.add(id);
|
|
7851
|
+
if (!markGroupOwnVisible(choices, id, groups)) return false;
|
|
7852
|
+
const parent = groups.find((g) => g.id === id)?.parent;
|
|
7853
|
+
id = parent !== void 0 && groups.some((g) => g.id === parent) ? parent : void 0;
|
|
7854
|
+
}
|
|
7855
|
+
return true;
|
|
7856
|
+
}
|
|
7857
|
+
function markGroupRows(groups) {
|
|
7858
|
+
const ids = new Set(groups.map((g) => g.id));
|
|
7859
|
+
const out = [];
|
|
7860
|
+
const placed = /* @__PURE__ */ new Set();
|
|
7861
|
+
const place = (group, depth) => {
|
|
7862
|
+
if (placed.has(group.id)) return;
|
|
7863
|
+
placed.add(group.id);
|
|
7864
|
+
out.push({ group, depth });
|
|
7865
|
+
for (const child of groups) if (child.parent === group.id && child.id !== group.id) place(child, depth + 1);
|
|
7866
|
+
};
|
|
7867
|
+
for (const g of groups) {
|
|
7868
|
+
const parentKnown = g.parent !== void 0 && ids.has(g.parent) && g.parent !== g.id;
|
|
7869
|
+
if (!parentKnown) place(g, 0);
|
|
7870
|
+
}
|
|
7871
|
+
for (const g of groups) place(g, 0);
|
|
7872
|
+
return out;
|
|
7873
|
+
}
|
|
7874
|
+
|
|
7822
7875
|
// src/renderers/shared/marks-state.ts
|
|
7823
7876
|
function defaultMarksState() {
|
|
7824
7877
|
return { visible: true, groups: {} };
|
|
@@ -7831,11 +7884,8 @@ function mergeMarksState(base, patch) {
|
|
|
7831
7884
|
for (const [id, v] of Object.entries(g)) if (typeof v === "boolean") groups[id] = v;
|
|
7832
7885
|
return { visible: typeof p.visible === "boolean" ? p.visible : base.visible, groups };
|
|
7833
7886
|
}
|
|
7834
|
-
function
|
|
7835
|
-
|
|
7836
|
-
const chosen = state.groups[groupId];
|
|
7837
|
-
if (typeof chosen === "boolean") return chosen;
|
|
7838
|
-
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
7887
|
+
function markGroupVisible2(state, groupId, groups) {
|
|
7888
|
+
return markGroupVisible(state.groups, groupId, groups);
|
|
7839
7889
|
}
|
|
7840
7890
|
|
|
7841
7891
|
// src/renderers/native/core/SceneGraph.ts
|
|
@@ -10011,13 +10061,29 @@ function paintMarkLane(ctx, layout, deps) {
|
|
|
10011
10061
|
const img = deps.icons.get(mark.glyph.icon, ink, symbolPx, deps.dpr);
|
|
10012
10062
|
if (img) ctx.drawImage(img, center.x - symbolPx / 2, center.y - symbolPx / 2, symbolPx, symbolPx);
|
|
10013
10063
|
} else if (mark.glyph.letter) {
|
|
10064
|
+
const letter = mark.glyph.letter.slice(0, 2);
|
|
10014
10065
|
ctx.fillStyle = ink;
|
|
10015
|
-
|
|
10016
|
-
ctx.
|
|
10066
|
+
let px = letterFontPx(size, letter);
|
|
10067
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
10068
|
+
if (letter.length > 1) {
|
|
10069
|
+
px = fitLetterPx(px, ctx.measureText(letter).width, symbolInnerWidth(shape, size));
|
|
10070
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
10071
|
+
}
|
|
10072
|
+
ctx.fillText(letter, center.x, center.y + 0.5);
|
|
10017
10073
|
}
|
|
10018
10074
|
}
|
|
10019
10075
|
ctx.restore();
|
|
10020
10076
|
}
|
|
10077
|
+
function letterFontPx(size, letter) {
|
|
10078
|
+
return Math.round(size * (letter.length > 1 ? 0.38 : 0.58));
|
|
10079
|
+
}
|
|
10080
|
+
function symbolInnerWidth(shape, size) {
|
|
10081
|
+
return (shape === "pin" ? size * 0.82 : size) - 3;
|
|
10082
|
+
}
|
|
10083
|
+
function fitLetterPx(px, width, inner) {
|
|
10084
|
+
if (!(width > inner) || !(width > 0)) return px;
|
|
10085
|
+
return Math.max(4, Math.floor(px * inner / width));
|
|
10086
|
+
}
|
|
10021
10087
|
function traceShape(ctx, shape, x, y, size) {
|
|
10022
10088
|
const r = size / 2;
|
|
10023
10089
|
ctx.beginPath();
|
|
@@ -10219,7 +10285,7 @@ var ChromeRenderer = class {
|
|
|
10219
10285
|
this.markLayout = layoutMarkLane({
|
|
10220
10286
|
marks: scene.timelineMarks,
|
|
10221
10287
|
groups: scene.markGroups,
|
|
10222
|
-
hidden: (groupId) => !
|
|
10288
|
+
hidden: (groupId) => !markGroupVisible2(scene.marks, groupId, scene.markGroups),
|
|
10223
10289
|
barTimes: this.barTimes(scene),
|
|
10224
10290
|
intervalMs: coords.barInterval,
|
|
10225
10291
|
xOf: (bar) => coords.logicalToX(bar),
|
|
@@ -10909,6 +10975,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
10909
10975
|
muted and non-interactive. Applied to each row's children so it survives display:contents;
|
|
10910
10976
|
!important beats the inline opacity on labels. */
|
|
10911
10977
|
.vela-sd-soft>*{opacity:0.4 !important;pointer-events:none !important;}
|
|
10978
|
+
/* A mark group nested under a parent group on the Events tab: indented one step per level
|
|
10979
|
+
(--vela-sd-depth). The indent rides the first child (the switch) as a MARGIN \u2014 padding
|
|
10980
|
+
would push the switch's own tick out of its box. */
|
|
10981
|
+
.vela-sd-nested>*:first-child{margin-left:calc(var(--vela-sd-depth,1)*24px);}
|
|
10912
10982
|
/* \u2500\u2500 mobile presentation (.vela-sd-mobile on the scrim; structural sizes are inline in open()) \u2500\u2500
|
|
10913
10983
|
The tab rail becomes a burger-opened overlay sidebar; the group TOC becomes a sticky
|
|
10914
10984
|
row of horizontally scrollable tabs; the instance strip scrolls instead of wrapping;
|
|
@@ -10957,6 +11027,8 @@ var SettingsDialog = class {
|
|
|
10957
11027
|
this.hostSections = [];
|
|
10958
11028
|
/** The timeline-mark groups (defined + named by marks) — one checkbox each on the Events tab. */
|
|
10959
11029
|
this.markGroups = [];
|
|
11030
|
+
/** A group's OWN switch (what its checkbox shows) — a child under an off parent keeps its own state. */
|
|
11031
|
+
this.markGroupOwnVisible = () => true;
|
|
10960
11032
|
this.markGroupVisible = () => true;
|
|
10961
11033
|
/** The Canvas → Theme row: current app theme + where a pick is raised. The row is a
|
|
10962
11034
|
* host callback, NOT a config patch — the app theme stays out of the persisted
|
|
@@ -10974,6 +11046,9 @@ var SettingsDialog = class {
|
|
|
10974
11046
|
this.activeSection = null;
|
|
10975
11047
|
/** Mobile chrome: fullscreen card, burger-opened section sidebar, TOC as top tabs. */
|
|
10976
11048
|
this.mobileLayout = false;
|
|
11049
|
+
/** Opens/closes the mobile section sidebar of the CURRENT build (the burger in the
|
|
11050
|
+
* shell header outlives pane rebuilds, so it reaches the rail through here). */
|
|
11051
|
+
this.toggleRail = null;
|
|
10977
11052
|
/** The visibility policy: setting ids hidden by the host (subtree semantics). */
|
|
10978
11053
|
this.hiddenSettings = /* @__PURE__ */ new Set();
|
|
10979
11054
|
if (getComputedStyle(container).position === "static") container.style.position = "relative";
|
|
@@ -10983,7 +11058,8 @@ var SettingsDialog = class {
|
|
|
10983
11058
|
this.hostSections = sections;
|
|
10984
11059
|
}
|
|
10985
11060
|
/** The timeline-mark groups and their current visibility — the Events tab's rows on next open. */
|
|
10986
|
-
setMarkGroups(groups, visible) {
|
|
11061
|
+
setMarkGroups(groups, visible, ownVisible = visible) {
|
|
11062
|
+
this.markGroupOwnVisible = ownVisible;
|
|
10987
11063
|
this.markGroups = groups;
|
|
10988
11064
|
this.markGroupVisible = visible;
|
|
10989
11065
|
}
|
|
@@ -11049,7 +11125,6 @@ var SettingsDialog = class {
|
|
|
11049
11125
|
this.onReset = onReset ?? null;
|
|
11050
11126
|
ensureControlStyles();
|
|
11051
11127
|
const mobile = this.mobileLayout;
|
|
11052
|
-
let toggleRail = null;
|
|
11053
11128
|
let burger;
|
|
11054
11129
|
if (mobile) {
|
|
11055
11130
|
burger = document.createElement("button");
|
|
@@ -11057,8 +11132,83 @@ var SettingsDialog = class {
|
|
|
11057
11132
|
burger.className = "vela-sd-burger";
|
|
11058
11133
|
burger.innerHTML = iconAt("burger", 16);
|
|
11059
11134
|
burger.title = "Sections";
|
|
11060
|
-
burger.addEventListener("click", () => toggleRail?.());
|
|
11135
|
+
burger.addEventListener("click", () => this.toggleRail?.());
|
|
11061
11136
|
}
|
|
11137
|
+
const ui = new Dialog({
|
|
11138
|
+
host: this.container,
|
|
11139
|
+
title: "Chart settings",
|
|
11140
|
+
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
11141
|
+
// machine locks pointer events on the whole body, killing the chart, the
|
|
11142
|
+
// legend, and the body-portaled popovers (color picker, select lists).
|
|
11143
|
+
modal: false,
|
|
11144
|
+
contained: true,
|
|
11145
|
+
align: "top",
|
|
11146
|
+
draggable: !mobile,
|
|
11147
|
+
flush: true,
|
|
11148
|
+
className: "vela-dialog--settings",
|
|
11149
|
+
headerStart: burger,
|
|
11150
|
+
closeOnBackdrop: true,
|
|
11151
|
+
footer: (foot) => {
|
|
11152
|
+
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
11153
|
+
const resetBtn = document.createElement("button");
|
|
11154
|
+
resetBtn.type = "button";
|
|
11155
|
+
resetBtn.textContent = "Reset defaults";
|
|
11156
|
+
resetBtn.className = "vela-sd-btn";
|
|
11157
|
+
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
11158
|
+
foot.appendChild(resetBtn);
|
|
11159
|
+
},
|
|
11160
|
+
// A close signal may only close ITS OWN dialog: the machine reports the exit
|
|
11161
|
+
// asynchronously, so a close-then-reopen in one tick would otherwise see the
|
|
11162
|
+
// old instance's signal tear down the freshly opened one.
|
|
11163
|
+
onOpenChange: (open) => {
|
|
11164
|
+
if (!open && this.ui === ui) this.close();
|
|
11165
|
+
}
|
|
11166
|
+
});
|
|
11167
|
+
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
11168
|
+
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
11169
|
+
this.root = ui.positioner;
|
|
11170
|
+
this.ui = ui;
|
|
11171
|
+
const panes = this.buildContent(ui, config, section, mobile);
|
|
11172
|
+
ui.show();
|
|
11173
|
+
this.layoutPanes(panes);
|
|
11174
|
+
}
|
|
11175
|
+
/**
|
|
11176
|
+
* Re-seed every control of an OPEN dialog from `config`, in place: the shell stays
|
|
11177
|
+
* (no close/open transition), only the tab rail and panes rebuild, landing back on
|
|
11178
|
+
* the current tab. The reset path — the restored values must show without the
|
|
11179
|
+
* dialog re-entering. No-op while closed.
|
|
11180
|
+
*/
|
|
11181
|
+
refresh(config) {
|
|
11182
|
+
const ui = this.ui;
|
|
11183
|
+
if (!ui) return;
|
|
11184
|
+
closeOpenPopovers();
|
|
11185
|
+
closeWidthPopover();
|
|
11186
|
+
for (const dispose of this.hintTips) dispose();
|
|
11187
|
+
this.hintTips = [];
|
|
11188
|
+
this.config = config;
|
|
11189
|
+
ui.body.replaceChildren();
|
|
11190
|
+
this.layoutPanes(this.buildContent(ui, config, this.activeSection ?? void 0, this.mobileLayout));
|
|
11191
|
+
}
|
|
11192
|
+
/** Structured chart-type panes (instance strip / group TOC) own their layout and
|
|
11193
|
+
* tag their rows hosts instead; each host gets its own field grid. Runs on a SHOWN
|
|
11194
|
+
* dialog — the grids measure their labels. */
|
|
11195
|
+
layoutPanes(panes) {
|
|
11196
|
+
for (const el of panes) {
|
|
11197
|
+
const hosts = [...el.querySelectorAll("[data-sd-rows-host]")];
|
|
11198
|
+
if (hosts.length === 0) {
|
|
11199
|
+
this.layoutSettingsGrids(el);
|
|
11200
|
+
continue;
|
|
11201
|
+
}
|
|
11202
|
+
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
/**
|
|
11206
|
+
* Build the tab rail + one pane per section into `ui.body` (the linear `body` of
|
|
11207
|
+
* section markers and rows is split afterwards), select `section` (the active
|
|
11208
|
+
* style's own tab when none is asked for), and return the pane elements for
|
|
11209
|
+
* {@link layoutPanes}.
|
|
11210
|
+
*/
|
|
11211
|
+
buildContent(ui, config, section, mobile) {
|
|
11062
11212
|
const body = document.createElement("div");
|
|
11063
11213
|
body.style.cssText = "display:flex;flex-direction:column;gap:0;";
|
|
11064
11214
|
const sid = (el, id) => {
|
|
@@ -11262,9 +11412,28 @@ var SettingsDialog = class {
|
|
|
11262
11412
|
if (this.markGroups.length > 0) {
|
|
11263
11413
|
body.append(sid(this.section("Events"), MARKS_SETTINGS_ID));
|
|
11264
11414
|
body.append(sid(this.sectionTitle("Visible events"), MARKS_GROUPS_SETTINGS_ID));
|
|
11265
|
-
|
|
11266
|
-
|
|
11415
|
+
const rowsById = /* @__PURE__ */ new Map();
|
|
11416
|
+
const rows = markGroupRows(this.markGroups);
|
|
11417
|
+
const refreshDimming = () => {
|
|
11418
|
+
for (const { group } of rows) {
|
|
11419
|
+
const el = rowsById.get(group.id);
|
|
11420
|
+
if (!el || group.parent === void 0) continue;
|
|
11421
|
+
el.classList.toggle("vela-sd-soft", !this.markGroupVisible(group.parent));
|
|
11422
|
+
}
|
|
11423
|
+
};
|
|
11424
|
+
for (const { group: g, depth } of rows) {
|
|
11425
|
+
const row = this.boolRow(g.label, this.markGroupOwnVisible(g.id), (v) => {
|
|
11426
|
+
this.emit({ marks: { groups: { [g.id]: v } } });
|
|
11427
|
+
refreshDimming();
|
|
11428
|
+
});
|
|
11429
|
+
if (depth > 0) {
|
|
11430
|
+
row.classList.add("vela-sd-nested");
|
|
11431
|
+
row.style.setProperty("--vela-sd-depth", String(depth));
|
|
11432
|
+
}
|
|
11433
|
+
rowsById.set(g.id, row);
|
|
11434
|
+
body.append(sid(row, markGroupSettingsId(g.id)));
|
|
11267
11435
|
}
|
|
11436
|
+
refreshDimming();
|
|
11268
11437
|
}
|
|
11269
11438
|
renderChartTypeSections("end");
|
|
11270
11439
|
renderHostSections("end");
|
|
@@ -11292,8 +11461,8 @@ var SettingsDialog = class {
|
|
|
11292
11461
|
if (mobile) {
|
|
11293
11462
|
railScrim = document.createElement("div");
|
|
11294
11463
|
railScrim.className = "vela-sd-railscrim";
|
|
11295
|
-
railScrim.addEventListener("click", () => toggleRail?.());
|
|
11296
|
-
toggleRail = (open) => {
|
|
11464
|
+
railScrim.addEventListener("click", () => this.toggleRail?.());
|
|
11465
|
+
this.toggleRail = (open) => {
|
|
11297
11466
|
const on = open ?? !rail.classList.contains("open");
|
|
11298
11467
|
rail.classList.toggle("open", on);
|
|
11299
11468
|
railScrim?.classList.toggle("open", on);
|
|
@@ -11333,35 +11502,6 @@ var SettingsDialog = class {
|
|
|
11333
11502
|
});
|
|
11334
11503
|
if (hidActive) activate(0);
|
|
11335
11504
|
};
|
|
11336
|
-
const ui = new Dialog({
|
|
11337
|
-
host: this.container,
|
|
11338
|
-
title: "Chart settings",
|
|
11339
|
-
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
11340
|
-
// machine locks pointer events on the whole body, killing the chart, the
|
|
11341
|
-
// legend, and the body-portaled popovers (color picker, select lists).
|
|
11342
|
-
modal: false,
|
|
11343
|
-
contained: true,
|
|
11344
|
-
align: "top",
|
|
11345
|
-
draggable: !mobile,
|
|
11346
|
-
flush: true,
|
|
11347
|
-
className: "vela-dialog--settings",
|
|
11348
|
-
headerStart: burger,
|
|
11349
|
-
closeOnBackdrop: true,
|
|
11350
|
-
footer: (foot) => {
|
|
11351
|
-
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
11352
|
-
const resetBtn = document.createElement("button");
|
|
11353
|
-
resetBtn.type = "button";
|
|
11354
|
-
resetBtn.textContent = "Reset defaults";
|
|
11355
|
-
resetBtn.className = "vela-sd-btn";
|
|
11356
|
-
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
11357
|
-
foot.appendChild(resetBtn);
|
|
11358
|
-
},
|
|
11359
|
-
onOpenChange: (open) => {
|
|
11360
|
-
if (!open) this.close();
|
|
11361
|
-
}
|
|
11362
|
-
});
|
|
11363
|
-
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
11364
|
-
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
11365
11505
|
const activate = (idx) => {
|
|
11366
11506
|
panes.forEach((p, i) => {
|
|
11367
11507
|
p.el.style.display = i === idx ? "block" : "none";
|
|
@@ -11370,7 +11510,7 @@ var SettingsDialog = class {
|
|
|
11370
11510
|
this.activeSection = panes[idx]?.title ?? null;
|
|
11371
11511
|
if (mobile) {
|
|
11372
11512
|
ui.titleEl.textContent = panes[idx]?.title ?? "Chart settings";
|
|
11373
|
-
toggleRail?.(false);
|
|
11513
|
+
this.toggleRail?.(false);
|
|
11374
11514
|
}
|
|
11375
11515
|
};
|
|
11376
11516
|
panes.forEach((p, i) => {
|
|
@@ -11385,17 +11525,7 @@ var SettingsDialog = class {
|
|
|
11385
11525
|
shell.append(rail, paneHost);
|
|
11386
11526
|
if (railScrim) shell.append(railScrim);
|
|
11387
11527
|
ui.body.appendChild(shell);
|
|
11388
|
-
|
|
11389
|
-
this.ui = ui;
|
|
11390
|
-
ui.show();
|
|
11391
|
-
for (const p of panes) {
|
|
11392
|
-
const hosts = [...p.el.querySelectorAll("[data-sd-rows-host]")];
|
|
11393
|
-
if (hosts.length === 0) {
|
|
11394
|
-
this.layoutSettingsGrids(p.el);
|
|
11395
|
-
continue;
|
|
11396
|
-
}
|
|
11397
|
-
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
11398
|
-
}
|
|
11528
|
+
return panes.map((p) => p.el);
|
|
11399
11529
|
}
|
|
11400
11530
|
close() {
|
|
11401
11531
|
closeOpenPopovers();
|
|
@@ -11403,6 +11533,7 @@ var SettingsDialog = class {
|
|
|
11403
11533
|
const ui = this.ui;
|
|
11404
11534
|
this.ui = null;
|
|
11405
11535
|
this.root = null;
|
|
11536
|
+
this.toggleRail = null;
|
|
11406
11537
|
this.tabs = [];
|
|
11407
11538
|
for (const dispose of this.hintTips) dispose();
|
|
11408
11539
|
this.hintTips = [];
|
|
@@ -18843,7 +18974,11 @@ var NativeRenderer = class {
|
|
|
18843
18974
|
}
|
|
18844
18975
|
this.settingsDialog.setTheme(this.theme);
|
|
18845
18976
|
this.settingsDialog.setHostSections(this.hostSettingsSections);
|
|
18846
|
-
this.settingsDialog.setMarkGroups(
|
|
18977
|
+
this.settingsDialog.setMarkGroups(
|
|
18978
|
+
this.markGroupsForEventsTab(),
|
|
18979
|
+
(id) => markGroupVisible2(this.scene.marks, id, this.scene.markGroups),
|
|
18980
|
+
(id) => markGroupOwnVisible(this.scene.marks.groups, id, this.scene.markGroups)
|
|
18981
|
+
);
|
|
18847
18982
|
this.settingsDialog.setHiddenSettings(this.hiddenSettings);
|
|
18848
18983
|
this.syncThemeControl();
|
|
18849
18984
|
this.settingsDialog.toggle(
|
|
@@ -18851,13 +18986,24 @@ var NativeRenderer = class {
|
|
|
18851
18986
|
(patch) => this.applyConfig(patch),
|
|
18852
18987
|
(json) => this.applyConfig(json),
|
|
18853
18988
|
() => {
|
|
18854
|
-
if (this.factoryConfig) this.applyConfig(
|
|
18855
|
-
this.settingsDialog?.
|
|
18856
|
-
this.openSettingsDialog();
|
|
18989
|
+
if (this.factoryConfig) this.applyConfig(this.factoryResetDocument(this.factoryConfig));
|
|
18990
|
+
this.settingsDialog?.refresh(this.getConfig());
|
|
18857
18991
|
},
|
|
18858
18992
|
section
|
|
18859
18993
|
);
|
|
18860
18994
|
}
|
|
18995
|
+
/**
|
|
18996
|
+
* The document "Reset defaults" applies: every setting back to its first-run value,
|
|
18997
|
+
* with two things that are NOT settings held or resolved here — the price style
|
|
18998
|
+
* stays the one the user is looking at, and the timeline-mark groups (an additive
|
|
18999
|
+
* merge, like the type bags) are named back to their host-declared visibility.
|
|
19000
|
+
*/
|
|
19001
|
+
factoryResetDocument(factory) {
|
|
19002
|
+
const doc = factoryResetConfig(factory, this.scene.priceStyle);
|
|
19003
|
+
const groups = { ...doc.marks.groups };
|
|
19004
|
+
for (const g of this.markGroupsInUse()) groups[g.id] = g.visible !== false;
|
|
19005
|
+
return { ...doc, marks: { ...doc.marks, groups } };
|
|
19006
|
+
}
|
|
18861
19007
|
/** Close the in-chart dialogs (indicator settings + chart-settings gear). No-op when none are open. */
|
|
18862
19008
|
closeDialogs() {
|
|
18863
19009
|
this.inputsUI?.closeOpenDialog();
|
|
@@ -19920,6 +20066,15 @@ var NativeRenderer = class {
|
|
|
19920
20066
|
markGroupsInUse() {
|
|
19921
20067
|
return effectiveMarkGroups(this.scene.timelineMarks, this.scene.markGroups);
|
|
19922
20068
|
}
|
|
20069
|
+
/**
|
|
20070
|
+
* The groups as the Events tab lists them: nested only under a DEFINED parent. The
|
|
20071
|
+
* painter's visibility chain resolves parents against the defined groups alone, so a
|
|
20072
|
+
* parent that marks merely name must not nest (and dim) a child the painter still shows.
|
|
20073
|
+
*/
|
|
20074
|
+
markGroupsForEventsTab() {
|
|
20075
|
+
const defined = new Set(this.scene.markGroups.map((g) => g.id));
|
|
20076
|
+
return this.markGroupsInUse().map((g) => g.parent !== void 0 && !defined.has(g.parent) ? { ...g, parent: void 0 } : g);
|
|
20077
|
+
}
|
|
19923
20078
|
onViewportChange(cb) {
|
|
19924
20079
|
this.viewportCbs.add(cb);
|
|
19925
20080
|
return () => this.viewportCbs.delete(cb);
|
|
@@ -21791,6 +21946,7 @@ var MarksController = class {
|
|
|
21791
21946
|
defineGroup(group) {
|
|
21792
21947
|
if (!group || typeof group.id !== "string" || group.id.length === 0) throw new Error("[vela] marks.defineGroup: `id` must be a non-empty string");
|
|
21793
21948
|
if (typeof group.label !== "string") throw new Error(`[vela] marks.defineGroup: group "${group.id}" needs a string \`label\``);
|
|
21949
|
+
if (group.parent !== void 0 && (typeof group.parent !== "string" || group.parent.length === 0)) throw new Error(`[vela] marks.defineGroup: group "${group.id}" has a \`parent\` that is not a group id`);
|
|
21794
21950
|
this.groups.set(group.id, { ...group });
|
|
21795
21951
|
this.sync();
|
|
21796
21952
|
}
|
|
@@ -21810,12 +21966,16 @@ var MarksController = class {
|
|
|
21810
21966
|
}
|
|
21811
21967
|
this.renderer.applyFeature("marks", { groups: { [id]: visible } });
|
|
21812
21968
|
}
|
|
21813
|
-
/**
|
|
21969
|
+
/**
|
|
21970
|
+
* A group's effective visibility: its own switch — the user's (persisted) choice, else
|
|
21971
|
+
* the declared default, else visible — AND every ancestor's, so a child under a
|
|
21972
|
+
* switched-off parent reads hidden whatever its own choice says.
|
|
21973
|
+
*/
|
|
21814
21974
|
isGroupVisible(id) {
|
|
21815
21975
|
const state = this.renderer.readFeature("marks");
|
|
21816
|
-
const
|
|
21817
|
-
if (typeof
|
|
21818
|
-
return this.groups.
|
|
21976
|
+
const groups = {};
|
|
21977
|
+
for (const [gid, v] of Object.entries(state?.groups ?? {})) if (typeof v === "boolean") groups[gid] = v;
|
|
21978
|
+
return markGroupVisible(groups, id, [...this.groups.values()]);
|
|
21819
21979
|
}
|
|
21820
21980
|
destroy() {
|
|
21821
21981
|
for (const unsub of this.subs) unsub();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-MCLI6B3S.js';
|
|
2
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-BFA32GOU.js';
|
|
3
3
|
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-ZADTVRUO.js';
|
|
4
4
|
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-BKHSQ4YM.js';
|
|
@@ -5644,6 +5644,11 @@ var ChartCell = class {
|
|
|
5644
5644
|
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.deps.timezone())) {
|
|
5645
5645
|
this.deps.setTimezone(normalizeTimezone(zone));
|
|
5646
5646
|
}
|
|
5647
|
+
const style = this.priceStyle;
|
|
5648
|
+
if (style !== (this.state.priceStyle ?? "candles")) {
|
|
5649
|
+
this.state.priceStyle = style;
|
|
5650
|
+
this.deps.onPriceStyleChanged(this.id);
|
|
5651
|
+
}
|
|
5647
5652
|
this.syncStatuslineColors();
|
|
5648
5653
|
this.syncPlotOverlayTokens();
|
|
5649
5654
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-
|
|
2
|
-
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-
|
|
1
|
+
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-DNBoMKkX.js';
|
|
2
|
+
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-DLeFs1gE.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -1391,7 +1391,11 @@ declare class MarksController {
|
|
|
1391
1391
|
* a persisted chart restores — so it warns + no-ops on a renderer without it.
|
|
1392
1392
|
*/
|
|
1393
1393
|
setGroupVisible(id: string, visible: boolean): void;
|
|
1394
|
-
/**
|
|
1394
|
+
/**
|
|
1395
|
+
* A group's effective visibility: its own switch — the user's (persisted) choice, else
|
|
1396
|
+
* the declared default, else visible — AND every ancestor's, so a child under a
|
|
1397
|
+
* switched-off parent reads hidden whatever its own choice says.
|
|
1398
|
+
*/
|
|
1395
1399
|
isGroupVisible(id: string): boolean;
|
|
1396
1400
|
destroy(): void;
|
|
1397
1401
|
private sync;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-
|
|
2
|
-
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-
|
|
1
|
+
import { x as Millis, an as InputSchema, al as IndicatorMeta, P as PriceStyle, O as OHLCV, I as InputValue, l as IndicatorModel, k as MoveTarget, aH as PaneAxis, aW as SeriesSpec, aj as Fill, G as Background, aM as PriceLine, a6 as DrawingLine, a2 as DrawingBox, a5 as DrawingLabel, aa as DrawingPolyline, a7 as DrawingLinefill, af as DrawingTable, h as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, z as DrawingTypeKey, y as SnapMode, a8 as DrawingMode, u as MarkClickEvent, e as IChartRenderer, R as RendererCapabilities, o as LegendActionView, p as LegendCalloutView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, v as DataWindowReadout, n as SymbolPickerFn, W as WallClock, bc as PaneInfo, ai as DrawingsOption, ac as DrawingSeriesGateway, D as Drawing, s as TimelineMark, t as MarkGroup, b as VelaOptions, E as AddIndicatorOptions, aG as MarketSwitch, aF as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-DNBoMKkX.cjs';
|
|
2
|
+
import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-Dut6lXGM.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -1391,7 +1391,11 @@ declare class MarksController {
|
|
|
1391
1391
|
* a persisted chart restores — so it warns + no-ops on a renderer without it.
|
|
1392
1392
|
*/
|
|
1393
1393
|
setGroupVisible(id: string, visible: boolean): void;
|
|
1394
|
-
/**
|
|
1394
|
+
/**
|
|
1395
|
+
* A group's effective visibility: its own switch — the user's (persisted) choice, else
|
|
1396
|
+
* the declared default, else visible — AND every ancestor's, so a child under a
|
|
1397
|
+
* switched-off parent reads hidden whatever its own choice says.
|
|
1398
|
+
*/
|
|
1395
1399
|
isGroupVisible(id: string): boolean;
|
|
1396
1400
|
destroy(): void;
|
|
1397
1401
|
private sync;
|