@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
package/dist/vela.global.js
CHANGED
|
@@ -7116,6 +7116,42 @@ var Vela = (function (exports) {
|
|
|
7116
7116
|
}
|
|
7117
7117
|
};
|
|
7118
7118
|
|
|
7119
|
+
// src/core/marks/visibility.ts
|
|
7120
|
+
function markGroupOwnVisible(choices, groupId, groups) {
|
|
7121
|
+
const chosen = choices[groupId];
|
|
7122
|
+
if (typeof chosen === "boolean") return chosen;
|
|
7123
|
+
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
7124
|
+
}
|
|
7125
|
+
function markGroupVisible(choices, groupId, groups) {
|
|
7126
|
+
if (groupId === void 0) return true;
|
|
7127
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7128
|
+
let id = groupId;
|
|
7129
|
+
while (id !== void 0 && !seen.has(id)) {
|
|
7130
|
+
seen.add(id);
|
|
7131
|
+
if (!markGroupOwnVisible(choices, id, groups)) return false;
|
|
7132
|
+
const parent = groups.find((g) => g.id === id)?.parent;
|
|
7133
|
+
id = parent !== void 0 && groups.some((g) => g.id === parent) ? parent : void 0;
|
|
7134
|
+
}
|
|
7135
|
+
return true;
|
|
7136
|
+
}
|
|
7137
|
+
function markGroupRows(groups) {
|
|
7138
|
+
const ids = new Set(groups.map((g) => g.id));
|
|
7139
|
+
const out = [];
|
|
7140
|
+
const placed = /* @__PURE__ */ new Set();
|
|
7141
|
+
const place = (group, depth) => {
|
|
7142
|
+
if (placed.has(group.id)) return;
|
|
7143
|
+
placed.add(group.id);
|
|
7144
|
+
out.push({ group, depth });
|
|
7145
|
+
for (const child of groups) if (child.parent === group.id && child.id !== group.id) place(child, depth + 1);
|
|
7146
|
+
};
|
|
7147
|
+
for (const g of groups) {
|
|
7148
|
+
const parentKnown = g.parent !== void 0 && ids.has(g.parent) && g.parent !== g.id;
|
|
7149
|
+
if (!parentKnown) place(g, 0);
|
|
7150
|
+
}
|
|
7151
|
+
for (const g of groups) place(g, 0);
|
|
7152
|
+
return out;
|
|
7153
|
+
}
|
|
7154
|
+
|
|
7119
7155
|
// src/core/marks/MarksController.ts
|
|
7120
7156
|
var MarksController = class {
|
|
7121
7157
|
constructor(renderer, events) {
|
|
@@ -7160,6 +7196,7 @@ var Vela = (function (exports) {
|
|
|
7160
7196
|
defineGroup(group) {
|
|
7161
7197
|
if (!group || typeof group.id !== "string" || group.id.length === 0) throw new Error("[vela] marks.defineGroup: `id` must be a non-empty string");
|
|
7162
7198
|
if (typeof group.label !== "string") throw new Error(`[vela] marks.defineGroup: group "${group.id}" needs a string \`label\``);
|
|
7199
|
+
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`);
|
|
7163
7200
|
this.groups.set(group.id, { ...group });
|
|
7164
7201
|
this.sync();
|
|
7165
7202
|
}
|
|
@@ -7179,12 +7216,16 @@ var Vela = (function (exports) {
|
|
|
7179
7216
|
}
|
|
7180
7217
|
this.renderer.applyFeature("marks", { groups: { [id]: visible } });
|
|
7181
7218
|
}
|
|
7182
|
-
/**
|
|
7219
|
+
/**
|
|
7220
|
+
* A group's effective visibility: its own switch — the user's (persisted) choice, else
|
|
7221
|
+
* the declared default, else visible — AND every ancestor's, so a child under a
|
|
7222
|
+
* switched-off parent reads hidden whatever its own choice says.
|
|
7223
|
+
*/
|
|
7183
7224
|
isGroupVisible(id) {
|
|
7184
7225
|
const state = this.renderer.readFeature("marks");
|
|
7185
|
-
const
|
|
7186
|
-
if (typeof
|
|
7187
|
-
return this.groups.
|
|
7226
|
+
const groups = {};
|
|
7227
|
+
for (const [gid, v] of Object.entries(state?.groups ?? {})) if (typeof v === "boolean") groups[gid] = v;
|
|
7228
|
+
return markGroupVisible(groups, id, [...this.groups.values()]);
|
|
7188
7229
|
}
|
|
7189
7230
|
destroy() {
|
|
7190
7231
|
for (const unsub of this.subs) unsub();
|
|
@@ -23374,6 +23415,17 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23374
23415
|
for (const t of chartTypes()) if (t.id === style) return (t.basePainting ?? "candles") === "candles";
|
|
23375
23416
|
return false;
|
|
23376
23417
|
}
|
|
23418
|
+
var CANDLE_OVERRIDE_KEYS = [
|
|
23419
|
+
"candleUpColor",
|
|
23420
|
+
"candleDownColor",
|
|
23421
|
+
"candleBodyVisible",
|
|
23422
|
+
"candleBorderVisible",
|
|
23423
|
+
"candleBorderUpColor",
|
|
23424
|
+
"candleBorderDownColor",
|
|
23425
|
+
"candleWickVisible",
|
|
23426
|
+
"candleWickUpColor",
|
|
23427
|
+
"candleWickDownColor"
|
|
23428
|
+
];
|
|
23377
23429
|
function candleOverrideFor(style, bags) {
|
|
23378
23430
|
if (!hasOwnCandlePaint(style)) return null;
|
|
23379
23431
|
const bag = bags[style] ?? {};
|
|
@@ -23445,7 +23497,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23445
23497
|
function clampSpacing(v) {
|
|
23446
23498
|
return v < 0.1 ? 0.1 : v > 10 ? 10 : v;
|
|
23447
23499
|
}
|
|
23448
|
-
function factoryResetConfig(factory) {
|
|
23500
|
+
function factoryResetConfig(factory, priceStyle = factory.series.style) {
|
|
23449
23501
|
const bag = {};
|
|
23450
23502
|
for (const t of chartTypes()) {
|
|
23451
23503
|
const section = t.settings;
|
|
@@ -23467,10 +23519,16 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23467
23519
|
if (!section.instances) addRows(section.rows);
|
|
23468
23520
|
bag[t.id] = defaults2;
|
|
23469
23521
|
}
|
|
23522
|
+
for (const t of chartTypes()) {
|
|
23523
|
+
if (!hasOwnCandlePaint(t.id)) continue;
|
|
23524
|
+
const defaults2 = bag[t.id] ?? {};
|
|
23525
|
+
for (const key of CANDLE_OVERRIDE_KEYS) defaults2[key] = null;
|
|
23526
|
+
bag[t.id] = defaults2;
|
|
23527
|
+
}
|
|
23470
23528
|
for (const [typeId, vals] of Object.entries(factory.chartTypes)) {
|
|
23471
23529
|
bag[typeId] = { ...bag[typeId] ?? {}, ...vals };
|
|
23472
23530
|
}
|
|
23473
|
-
return { ...factory, chartTypes: bag };
|
|
23531
|
+
return { ...factory, chartTypes: bag, series: { ...factory.series, style: priceStyle } };
|
|
23474
23532
|
}
|
|
23475
23533
|
function mergeConfig(base, patch) {
|
|
23476
23534
|
const p = asObject(patch);
|
|
@@ -25849,11 +25907,8 @@ void main() {
|
|
|
25849
25907
|
for (const [id, v] of Object.entries(g)) if (typeof v === "boolean") groups[id] = v;
|
|
25850
25908
|
return { visible: typeof p.visible === "boolean" ? p.visible : base.visible, groups };
|
|
25851
25909
|
}
|
|
25852
|
-
function
|
|
25853
|
-
|
|
25854
|
-
const chosen = state.groups[groupId];
|
|
25855
|
-
if (typeof chosen === "boolean") return chosen;
|
|
25856
|
-
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
25910
|
+
function markGroupVisible2(state, groupId, groups) {
|
|
25911
|
+
return markGroupVisible(state.groups, groupId, groups);
|
|
25857
25912
|
}
|
|
25858
25913
|
|
|
25859
25914
|
// src/renderers/native/core/SceneGraph.ts
|
|
@@ -28029,13 +28084,29 @@ void main() {
|
|
|
28029
28084
|
const img = deps.icons.get(mark.glyph.icon, ink, symbolPx, deps.dpr);
|
|
28030
28085
|
if (img) ctx.drawImage(img, center.x - symbolPx / 2, center.y - symbolPx / 2, symbolPx, symbolPx);
|
|
28031
28086
|
} else if (mark.glyph.letter) {
|
|
28087
|
+
const letter = mark.glyph.letter.slice(0, 2);
|
|
28032
28088
|
ctx.fillStyle = ink;
|
|
28033
|
-
|
|
28034
|
-
ctx.
|
|
28089
|
+
let px = letterFontPx(size3, letter);
|
|
28090
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
28091
|
+
if (letter.length > 1) {
|
|
28092
|
+
px = fitLetterPx(px, ctx.measureText(letter).width, symbolInnerWidth(shape, size3));
|
|
28093
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
28094
|
+
}
|
|
28095
|
+
ctx.fillText(letter, center.x, center.y + 0.5);
|
|
28035
28096
|
}
|
|
28036
28097
|
}
|
|
28037
28098
|
ctx.restore();
|
|
28038
28099
|
}
|
|
28100
|
+
function letterFontPx(size3, letter) {
|
|
28101
|
+
return Math.round(size3 * (letter.length > 1 ? 0.38 : 0.58));
|
|
28102
|
+
}
|
|
28103
|
+
function symbolInnerWidth(shape, size3) {
|
|
28104
|
+
return (shape === "pin" ? size3 * 0.82 : size3) - 3;
|
|
28105
|
+
}
|
|
28106
|
+
function fitLetterPx(px, width, inner) {
|
|
28107
|
+
if (!(width > inner) || !(width > 0)) return px;
|
|
28108
|
+
return Math.max(4, Math.floor(px * inner / width));
|
|
28109
|
+
}
|
|
28039
28110
|
function traceShape(ctx, shape, x, y, size3) {
|
|
28040
28111
|
const r = size3 / 2;
|
|
28041
28112
|
ctx.beginPath();
|
|
@@ -28237,7 +28308,7 @@ void main() {
|
|
|
28237
28308
|
this.markLayout = layoutMarkLane({
|
|
28238
28309
|
marks: scene.timelineMarks,
|
|
28239
28310
|
groups: scene.markGroups,
|
|
28240
|
-
hidden: (groupId) => !
|
|
28311
|
+
hidden: (groupId) => !markGroupVisible2(scene.marks, groupId, scene.markGroups),
|
|
28241
28312
|
barTimes: this.barTimes(scene),
|
|
28242
28313
|
intervalMs: coords.barInterval,
|
|
28243
28314
|
xOf: (bar) => coords.logicalToX(bar),
|
|
@@ -29004,6 +29075,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29004
29075
|
muted and non-interactive. Applied to each row's children so it survives display:contents;
|
|
29005
29076
|
!important beats the inline opacity on labels. */
|
|
29006
29077
|
.vela-sd-soft>*{opacity:0.4 !important;pointer-events:none !important;}
|
|
29078
|
+
/* A mark group nested under a parent group on the Events tab: indented one step per level
|
|
29079
|
+
(--vela-sd-depth). The indent rides the first child (the switch) as a MARGIN \u2014 padding
|
|
29080
|
+
would push the switch's own tick out of its box. */
|
|
29081
|
+
.vela-sd-nested>*:first-child{margin-left:calc(var(--vela-sd-depth,1)*24px);}
|
|
29007
29082
|
/* \u2500\u2500 mobile presentation (.vela-sd-mobile on the scrim; structural sizes are inline in open()) \u2500\u2500
|
|
29008
29083
|
The tab rail becomes a burger-opened overlay sidebar; the group TOC becomes a sticky
|
|
29009
29084
|
row of horizontally scrollable tabs; the instance strip scrolls instead of wrapping;
|
|
@@ -29052,6 +29127,8 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29052
29127
|
this.hostSections = [];
|
|
29053
29128
|
/** The timeline-mark groups (defined + named by marks) — one checkbox each on the Events tab. */
|
|
29054
29129
|
this.markGroups = [];
|
|
29130
|
+
/** A group's OWN switch (what its checkbox shows) — a child under an off parent keeps its own state. */
|
|
29131
|
+
this.markGroupOwnVisible = () => true;
|
|
29055
29132
|
this.markGroupVisible = () => true;
|
|
29056
29133
|
/** The Canvas → Theme row: current app theme + where a pick is raised. The row is a
|
|
29057
29134
|
* host callback, NOT a config patch — the app theme stays out of the persisted
|
|
@@ -29069,6 +29146,9 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29069
29146
|
this.activeSection = null;
|
|
29070
29147
|
/** Mobile chrome: fullscreen card, burger-opened section sidebar, TOC as top tabs. */
|
|
29071
29148
|
this.mobileLayout = false;
|
|
29149
|
+
/** Opens/closes the mobile section sidebar of the CURRENT build (the burger in the
|
|
29150
|
+
* shell header outlives pane rebuilds, so it reaches the rail through here). */
|
|
29151
|
+
this.toggleRail = null;
|
|
29072
29152
|
/** The visibility policy: setting ids hidden by the host (subtree semantics). */
|
|
29073
29153
|
this.hiddenSettings = /* @__PURE__ */ new Set();
|
|
29074
29154
|
if (getComputedStyle(container).position === "static") container.style.position = "relative";
|
|
@@ -29078,7 +29158,8 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29078
29158
|
this.hostSections = sections;
|
|
29079
29159
|
}
|
|
29080
29160
|
/** The timeline-mark groups and their current visibility — the Events tab's rows on next open. */
|
|
29081
|
-
setMarkGroups(groups, visible) {
|
|
29161
|
+
setMarkGroups(groups, visible, ownVisible = visible) {
|
|
29162
|
+
this.markGroupOwnVisible = ownVisible;
|
|
29082
29163
|
this.markGroups = groups;
|
|
29083
29164
|
this.markGroupVisible = visible;
|
|
29084
29165
|
}
|
|
@@ -29144,7 +29225,6 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29144
29225
|
this.onReset = onReset ?? null;
|
|
29145
29226
|
ensureControlStyles();
|
|
29146
29227
|
const mobile = this.mobileLayout;
|
|
29147
|
-
let toggleRail = null;
|
|
29148
29228
|
let burger;
|
|
29149
29229
|
if (mobile) {
|
|
29150
29230
|
burger = document.createElement("button");
|
|
@@ -29152,8 +29232,83 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29152
29232
|
burger.className = "vela-sd-burger";
|
|
29153
29233
|
burger.innerHTML = iconAt("burger", 16);
|
|
29154
29234
|
burger.title = "Sections";
|
|
29155
|
-
burger.addEventListener("click", () => toggleRail?.());
|
|
29235
|
+
burger.addEventListener("click", () => this.toggleRail?.());
|
|
29236
|
+
}
|
|
29237
|
+
const ui = new Dialog({
|
|
29238
|
+
host: this.container,
|
|
29239
|
+
title: "Chart settings",
|
|
29240
|
+
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
29241
|
+
// machine locks pointer events on the whole body, killing the chart, the
|
|
29242
|
+
// legend, and the body-portaled popovers (color picker, select lists).
|
|
29243
|
+
modal: false,
|
|
29244
|
+
contained: true,
|
|
29245
|
+
align: "top",
|
|
29246
|
+
draggable: !mobile,
|
|
29247
|
+
flush: true,
|
|
29248
|
+
className: "vela-dialog--settings",
|
|
29249
|
+
headerStart: burger,
|
|
29250
|
+
closeOnBackdrop: true,
|
|
29251
|
+
footer: (foot) => {
|
|
29252
|
+
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
29253
|
+
const resetBtn = document.createElement("button");
|
|
29254
|
+
resetBtn.type = "button";
|
|
29255
|
+
resetBtn.textContent = "Reset defaults";
|
|
29256
|
+
resetBtn.className = "vela-sd-btn";
|
|
29257
|
+
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
29258
|
+
foot.appendChild(resetBtn);
|
|
29259
|
+
},
|
|
29260
|
+
// A close signal may only close ITS OWN dialog: the machine reports the exit
|
|
29261
|
+
// asynchronously, so a close-then-reopen in one tick would otherwise see the
|
|
29262
|
+
// old instance's signal tear down the freshly opened one.
|
|
29263
|
+
onOpenChange: (open2) => {
|
|
29264
|
+
if (!open2 && this.ui === ui) this.close();
|
|
29265
|
+
}
|
|
29266
|
+
});
|
|
29267
|
+
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
29268
|
+
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
29269
|
+
this.root = ui.positioner;
|
|
29270
|
+
this.ui = ui;
|
|
29271
|
+
const panes = this.buildContent(ui, config, section, mobile);
|
|
29272
|
+
ui.show();
|
|
29273
|
+
this.layoutPanes(panes);
|
|
29274
|
+
}
|
|
29275
|
+
/**
|
|
29276
|
+
* Re-seed every control of an OPEN dialog from `config`, in place: the shell stays
|
|
29277
|
+
* (no close/open transition), only the tab rail and panes rebuild, landing back on
|
|
29278
|
+
* the current tab. The reset path — the restored values must show without the
|
|
29279
|
+
* dialog re-entering. No-op while closed.
|
|
29280
|
+
*/
|
|
29281
|
+
refresh(config) {
|
|
29282
|
+
const ui = this.ui;
|
|
29283
|
+
if (!ui) return;
|
|
29284
|
+
closeOpenPopovers();
|
|
29285
|
+
closeWidthPopover();
|
|
29286
|
+
for (const dispose of this.hintTips) dispose();
|
|
29287
|
+
this.hintTips = [];
|
|
29288
|
+
this.config = config;
|
|
29289
|
+
ui.body.replaceChildren();
|
|
29290
|
+
this.layoutPanes(this.buildContent(ui, config, this.activeSection ?? void 0, this.mobileLayout));
|
|
29291
|
+
}
|
|
29292
|
+
/** Structured chart-type panes (instance strip / group TOC) own their layout and
|
|
29293
|
+
* tag their rows hosts instead; each host gets its own field grid. Runs on a SHOWN
|
|
29294
|
+
* dialog — the grids measure their labels. */
|
|
29295
|
+
layoutPanes(panes) {
|
|
29296
|
+
for (const el of panes) {
|
|
29297
|
+
const hosts = [...el.querySelectorAll("[data-sd-rows-host]")];
|
|
29298
|
+
if (hosts.length === 0) {
|
|
29299
|
+
this.layoutSettingsGrids(el);
|
|
29300
|
+
continue;
|
|
29301
|
+
}
|
|
29302
|
+
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
29156
29303
|
}
|
|
29304
|
+
}
|
|
29305
|
+
/**
|
|
29306
|
+
* Build the tab rail + one pane per section into `ui.body` (the linear `body` of
|
|
29307
|
+
* section markers and rows is split afterwards), select `section` (the active
|
|
29308
|
+
* style's own tab when none is asked for), and return the pane elements for
|
|
29309
|
+
* {@link layoutPanes}.
|
|
29310
|
+
*/
|
|
29311
|
+
buildContent(ui, config, section, mobile) {
|
|
29157
29312
|
const body = document.createElement("div");
|
|
29158
29313
|
body.style.cssText = "display:flex;flex-direction:column;gap:0;";
|
|
29159
29314
|
const sid = (el, id) => {
|
|
@@ -29357,9 +29512,28 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29357
29512
|
if (this.markGroups.length > 0) {
|
|
29358
29513
|
body.append(sid(this.section("Events"), MARKS_SETTINGS_ID));
|
|
29359
29514
|
body.append(sid(this.sectionTitle("Visible events"), MARKS_GROUPS_SETTINGS_ID));
|
|
29360
|
-
|
|
29361
|
-
|
|
29515
|
+
const rowsById = /* @__PURE__ */ new Map();
|
|
29516
|
+
const rows = markGroupRows(this.markGroups);
|
|
29517
|
+
const refreshDimming = () => {
|
|
29518
|
+
for (const { group } of rows) {
|
|
29519
|
+
const el = rowsById.get(group.id);
|
|
29520
|
+
if (!el || group.parent === void 0) continue;
|
|
29521
|
+
el.classList.toggle("vela-sd-soft", !this.markGroupVisible(group.parent));
|
|
29522
|
+
}
|
|
29523
|
+
};
|
|
29524
|
+
for (const { group: g, depth } of rows) {
|
|
29525
|
+
const row = this.boolRow(g.label, this.markGroupOwnVisible(g.id), (v) => {
|
|
29526
|
+
this.emit({ marks: { groups: { [g.id]: v } } });
|
|
29527
|
+
refreshDimming();
|
|
29528
|
+
});
|
|
29529
|
+
if (depth > 0) {
|
|
29530
|
+
row.classList.add("vela-sd-nested");
|
|
29531
|
+
row.style.setProperty("--vela-sd-depth", String(depth));
|
|
29532
|
+
}
|
|
29533
|
+
rowsById.set(g.id, row);
|
|
29534
|
+
body.append(sid(row, markGroupSettingsId(g.id)));
|
|
29362
29535
|
}
|
|
29536
|
+
refreshDimming();
|
|
29363
29537
|
}
|
|
29364
29538
|
renderChartTypeSections("end");
|
|
29365
29539
|
renderHostSections("end");
|
|
@@ -29387,8 +29561,8 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29387
29561
|
if (mobile) {
|
|
29388
29562
|
railScrim = document.createElement("div");
|
|
29389
29563
|
railScrim.className = "vela-sd-railscrim";
|
|
29390
|
-
railScrim.addEventListener("click", () => toggleRail?.());
|
|
29391
|
-
toggleRail = (open2) => {
|
|
29564
|
+
railScrim.addEventListener("click", () => this.toggleRail?.());
|
|
29565
|
+
this.toggleRail = (open2) => {
|
|
29392
29566
|
const on = open2 ?? !rail.classList.contains("open");
|
|
29393
29567
|
rail.classList.toggle("open", on);
|
|
29394
29568
|
railScrim?.classList.toggle("open", on);
|
|
@@ -29428,35 +29602,6 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29428
29602
|
});
|
|
29429
29603
|
if (hidActive) activate(0);
|
|
29430
29604
|
};
|
|
29431
|
-
const ui = new Dialog({
|
|
29432
|
-
host: this.container,
|
|
29433
|
-
title: "Chart settings",
|
|
29434
|
-
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
29435
|
-
// machine locks pointer events on the whole body, killing the chart, the
|
|
29436
|
-
// legend, and the body-portaled popovers (color picker, select lists).
|
|
29437
|
-
modal: false,
|
|
29438
|
-
contained: true,
|
|
29439
|
-
align: "top",
|
|
29440
|
-
draggable: !mobile,
|
|
29441
|
-
flush: true,
|
|
29442
|
-
className: "vela-dialog--settings",
|
|
29443
|
-
headerStart: burger,
|
|
29444
|
-
closeOnBackdrop: true,
|
|
29445
|
-
footer: (foot) => {
|
|
29446
|
-
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
29447
|
-
const resetBtn = document.createElement("button");
|
|
29448
|
-
resetBtn.type = "button";
|
|
29449
|
-
resetBtn.textContent = "Reset defaults";
|
|
29450
|
-
resetBtn.className = "vela-sd-btn";
|
|
29451
|
-
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
29452
|
-
foot.appendChild(resetBtn);
|
|
29453
|
-
},
|
|
29454
|
-
onOpenChange: (open2) => {
|
|
29455
|
-
if (!open2) this.close();
|
|
29456
|
-
}
|
|
29457
|
-
});
|
|
29458
|
-
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
29459
|
-
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
29460
29605
|
const activate = (idx) => {
|
|
29461
29606
|
panes.forEach((p, i) => {
|
|
29462
29607
|
p.el.style.display = i === idx ? "block" : "none";
|
|
@@ -29465,7 +29610,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29465
29610
|
this.activeSection = panes[idx]?.title ?? null;
|
|
29466
29611
|
if (mobile) {
|
|
29467
29612
|
ui.titleEl.textContent = panes[idx]?.title ?? "Chart settings";
|
|
29468
|
-
toggleRail?.(false);
|
|
29613
|
+
this.toggleRail?.(false);
|
|
29469
29614
|
}
|
|
29470
29615
|
};
|
|
29471
29616
|
panes.forEach((p, i) => {
|
|
@@ -29480,17 +29625,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29480
29625
|
shell.append(rail, paneHost);
|
|
29481
29626
|
if (railScrim) shell.append(railScrim);
|
|
29482
29627
|
ui.body.appendChild(shell);
|
|
29483
|
-
|
|
29484
|
-
this.ui = ui;
|
|
29485
|
-
ui.show();
|
|
29486
|
-
for (const p of panes) {
|
|
29487
|
-
const hosts = [...p.el.querySelectorAll("[data-sd-rows-host]")];
|
|
29488
|
-
if (hosts.length === 0) {
|
|
29489
|
-
this.layoutSettingsGrids(p.el);
|
|
29490
|
-
continue;
|
|
29491
|
-
}
|
|
29492
|
-
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
29493
|
-
}
|
|
29628
|
+
return panes.map((p) => p.el);
|
|
29494
29629
|
}
|
|
29495
29630
|
close() {
|
|
29496
29631
|
closeOpenPopovers();
|
|
@@ -29498,6 +29633,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
29498
29633
|
const ui = this.ui;
|
|
29499
29634
|
this.ui = null;
|
|
29500
29635
|
this.root = null;
|
|
29636
|
+
this.toggleRail = null;
|
|
29501
29637
|
this.tabs = [];
|
|
29502
29638
|
for (const dispose of this.hintTips) dispose();
|
|
29503
29639
|
this.hintTips = [];
|
|
@@ -37597,7 +37733,11 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37597
37733
|
}
|
|
37598
37734
|
this.settingsDialog.setTheme(this.theme);
|
|
37599
37735
|
this.settingsDialog.setHostSections(this.hostSettingsSections);
|
|
37600
|
-
this.settingsDialog.setMarkGroups(
|
|
37736
|
+
this.settingsDialog.setMarkGroups(
|
|
37737
|
+
this.markGroupsForEventsTab(),
|
|
37738
|
+
(id) => markGroupVisible2(this.scene.marks, id, this.scene.markGroups),
|
|
37739
|
+
(id) => markGroupOwnVisible(this.scene.marks.groups, id, this.scene.markGroups)
|
|
37740
|
+
);
|
|
37601
37741
|
this.settingsDialog.setHiddenSettings(this.hiddenSettings);
|
|
37602
37742
|
this.syncThemeControl();
|
|
37603
37743
|
this.settingsDialog.toggle(
|
|
@@ -37605,13 +37745,24 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37605
37745
|
(patch) => this.applyConfig(patch),
|
|
37606
37746
|
(json) => this.applyConfig(json),
|
|
37607
37747
|
() => {
|
|
37608
|
-
if (this.factoryConfig) this.applyConfig(
|
|
37609
|
-
this.settingsDialog?.
|
|
37610
|
-
this.openSettingsDialog();
|
|
37748
|
+
if (this.factoryConfig) this.applyConfig(this.factoryResetDocument(this.factoryConfig));
|
|
37749
|
+
this.settingsDialog?.refresh(this.getConfig());
|
|
37611
37750
|
},
|
|
37612
37751
|
section
|
|
37613
37752
|
);
|
|
37614
37753
|
}
|
|
37754
|
+
/**
|
|
37755
|
+
* The document "Reset defaults" applies: every setting back to its first-run value,
|
|
37756
|
+
* with two things that are NOT settings held or resolved here — the price style
|
|
37757
|
+
* stays the one the user is looking at, and the timeline-mark groups (an additive
|
|
37758
|
+
* merge, like the type bags) are named back to their host-declared visibility.
|
|
37759
|
+
*/
|
|
37760
|
+
factoryResetDocument(factory) {
|
|
37761
|
+
const doc = factoryResetConfig(factory, this.scene.priceStyle);
|
|
37762
|
+
const groups = { ...doc.marks.groups };
|
|
37763
|
+
for (const g of this.markGroupsInUse()) groups[g.id] = g.visible !== false;
|
|
37764
|
+
return { ...doc, marks: { ...doc.marks, groups } };
|
|
37765
|
+
}
|
|
37615
37766
|
/** Close the in-chart dialogs (indicator settings + chart-settings gear). No-op when none are open. */
|
|
37616
37767
|
closeDialogs() {
|
|
37617
37768
|
this.inputsUI?.closeOpenDialog();
|
|
@@ -38674,6 +38825,15 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
38674
38825
|
markGroupsInUse() {
|
|
38675
38826
|
return effectiveMarkGroups(this.scene.timelineMarks, this.scene.markGroups);
|
|
38676
38827
|
}
|
|
38828
|
+
/**
|
|
38829
|
+
* The groups as the Events tab lists them: nested only under a DEFINED parent. The
|
|
38830
|
+
* painter's visibility chain resolves parents against the defined groups alone, so a
|
|
38831
|
+
* parent that marks merely name must not nest (and dim) a child the painter still shows.
|
|
38832
|
+
*/
|
|
38833
|
+
markGroupsForEventsTab() {
|
|
38834
|
+
const defined = new Set(this.scene.markGroups.map((g) => g.id));
|
|
38835
|
+
return this.markGroupsInUse().map((g) => g.parent !== void 0 && !defined.has(g.parent) ? { ...g, parent: void 0 } : g);
|
|
38836
|
+
}
|
|
38677
38837
|
onViewportChange(cb) {
|
|
38678
38838
|
this.viewportCbs.add(cb);
|
|
38679
38839
|
return () => this.viewportCbs.delete(cb);
|