@luxalgo/vela 0.7.4 → 0.7.6
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-RF1axuy1.d.cts → DataProvider-CGa4KHRa.d.cts} +1 -1
- package/dist/{DataProvider-CVpN5sCq.d.ts → DataProvider-CmWUtDVL.d.ts} +1 -1
- package/dist/{chunk-CSFNKXUW.js → chunk-EMB53WNQ.js} +16 -7
- package/dist/{chunk-DUURH3RN.js → chunk-JSVCWYBF.js} +271 -74
- package/dist/{contributions-CspPrMAJ.d.ts → contributions-C7Wsm_S9.d.ts} +13 -3
- package/dist/{contributions-DpZeu7KP.d.cts → contributions-D6p1RB38.d.cts} +13 -3
- package/dist/index.cjs +271 -74
- 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-D1AJKsn_.d.cts} +18 -0
- package/dist/{options-XVpfr9HV.d.ts → options-D1AJKsn_.d.ts} +18 -0
- package/dist/{plugin-D07HD2GL.d.cts → plugin-CxWfg6vK.d.cts} +3 -3
- package/dist/{plugin-BoLOkblF.d.ts → plugin-SodaQhjQ.d.ts} +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-Bd4qKuD6.d.cts → statusline-model-gWHrsOy3.d.cts} +3 -3
- package/dist/{statusline-model-CPa_hmhd.d.ts → statusline-model-xBiVsKoE.d.ts} +3 -3
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/vela.global.js +271 -74
- package/dist/vela.global.min.js +53 -49
- package/dist/widget.cjs +286 -80
- package/dist/widget.d.cts +6 -6
- package/dist/widget.d.ts +6 -6
- package/dist/widget.js +3 -3
- package/dist/workspace.cjs +286 -80
- package/dist/workspace.d.cts +10 -5
- package/dist/workspace.d.ts +10 -5
- package/dist/workspace.js +2 -2
- package/package.json +1 -1
package/dist/widget.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { V as Vela, W as WidgetContext, K as SidePanelButton } from './contributions-
|
|
2
|
-
export { C as CellStateContext, aA as DEFAULT_PANEL_ORDER, E as ExternalIndicatorEntry, O as OVERRIDABLE_TOPBAR_IDS, Q as SidePanelDescriptor, T as SidePanelHandle, X as StatePersistenceHandler, $ as SymbolRankingHook, a4 as WidgetActionDescriptor, a5 as WidgetActionTarget, a6 as WidgetAttachment, ag as registerSidePanel, ah as registerStatePersistence, ai as registerSymbolRanking, aj as registerWidgetAction, ak as registerWidgetAttachment, am as sidePanels, an as statePersistenceHandlers, ao as symbolRanking, ap as topbarActionOverride, au as unregisterSidePanel, av as unregisterStatePersistence, aw as unregisterWidgetAction, ax as unregisterWidgetAttachment, ay as widgetActions, az as widgetAttachments } from './contributions-
|
|
3
|
-
import { b as VelaOptions, d as MarketSession, T as ThemeName, c as VelaTheme, v as DataWindowReadout } from './options-
|
|
4
|
-
import { c as VelaShellOptions, W as WidgetHistory, b as RangePreset, f as WorkspaceState, j as TopbarComposition, a as StatuslinePart, P as PanelsState } from './statusline-model-
|
|
5
|
-
export { B as Bottombar, k as BottombarOptions, C as CellState, g as ChartState, I as IndicatorLoader, l as IndicatorManifest, m as IndicatorManifestEntry, n as RANGE_PRESETS, R as ResolvedIndicator, o as ResolvedTopbarComposition, p as TOPBAR_BUILTIN_IDS, q as TOPBAR_DEFAULT_LEFT, r as TOPBAR_DEFAULT_RIGHT, V as VelaStorage, t as WidgetStorage, h as decodeState, i as encodeState, u as localStorageAdapter, v as pinnedTopbarActionIds, w as resolveIndicators, x as resolveTopbarComposition, s as sanitizeState, y as topbarHas } from './statusline-model-
|
|
1
|
+
import { V as Vela, W as WidgetContext, K as SidePanelButton } from './contributions-C7Wsm_S9.js';
|
|
2
|
+
export { C as CellStateContext, aA as DEFAULT_PANEL_ORDER, E as ExternalIndicatorEntry, O as OVERRIDABLE_TOPBAR_IDS, Q as SidePanelDescriptor, T as SidePanelHandle, X as StatePersistenceHandler, $ as SymbolRankingHook, a4 as WidgetActionDescriptor, a5 as WidgetActionTarget, a6 as WidgetAttachment, ag as registerSidePanel, ah as registerStatePersistence, ai as registerSymbolRanking, aj as registerWidgetAction, ak as registerWidgetAttachment, am as sidePanels, an as statePersistenceHandlers, ao as symbolRanking, ap as topbarActionOverride, au as unregisterSidePanel, av as unregisterStatePersistence, aw as unregisterWidgetAction, ax as unregisterWidgetAttachment, ay as widgetActions, az as widgetAttachments } from './contributions-C7Wsm_S9.js';
|
|
3
|
+
import { b as VelaOptions, d as MarketSession, T as ThemeName, c as VelaTheme, v as DataWindowReadout } from './options-D1AJKsn_.js';
|
|
4
|
+
import { c as VelaShellOptions, W as WidgetHistory, b as RangePreset, f as WorkspaceState, j as TopbarComposition, a as StatuslinePart, P as PanelsState } from './statusline-model-xBiVsKoE.js';
|
|
5
|
+
export { B as Bottombar, k as BottombarOptions, C as CellState, g as ChartState, I as IndicatorLoader, l as IndicatorManifest, m as IndicatorManifestEntry, n as RANGE_PRESETS, R as ResolvedIndicator, o as ResolvedTopbarComposition, p as TOPBAR_BUILTIN_IDS, q as TOPBAR_DEFAULT_LEFT, r as TOPBAR_DEFAULT_RIGHT, V as VelaStorage, t as WidgetStorage, h as decodeState, i as encodeState, u as localStorageAdapter, v as pinnedTopbarActionIds, w as resolveIndicators, x as resolveTopbarComposition, s as sanitizeState, y as topbarHas } from './statusline-model-xBiVsKoE.js';
|
|
6
6
|
import { K as KeymapManager } from './keymap-CGOz5F5f.js';
|
|
7
|
-
import { a as SymbolDescriptor } from './DataProvider-
|
|
7
|
+
import { a as SymbolDescriptor } from './DataProvider-CmWUtDVL.js';
|
|
8
8
|
import { d as SidePanel } from './side-panel-HF0IAzwf.js';
|
|
9
9
|
export { D as DEFAULT_PANEL_MAX_WIDTH, a as DEFAULT_PANEL_MIN_WIDTH, b as DEFAULT_PANEL_WIDTH, S as SidePanelOptions, c as clampPanelWidth } from './side-panel-HF0IAzwf.js';
|
|
10
10
|
|
package/dist/widget.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { VelaWorkspace } from './chunk-
|
|
2
|
-
export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, localStorageAdapter, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, timeframeLabel, timeframeMs } from './chunk-
|
|
3
|
-
export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-
|
|
1
|
+
import { VelaWorkspace } from './chunk-EMB53WNQ.js';
|
|
2
|
+
export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, localStorageAdapter, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, timeframeLabel, timeframeMs } from './chunk-EMB53WNQ.js';
|
|
3
|
+
export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-JSVCWYBF.js';
|
|
4
4
|
export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, OVERRIDABLE_TOPBAR_IDS, SidePanel, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, clampPanelWidth, pinnedTopbarActionIds, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, resolveTopbarComposition, sidePanels, statePersistenceHandlers, symbolRanking, topbarActionOverride, topbarHas, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-BFA32GOU.js';
|
|
5
5
|
import './chunk-ZADTVRUO.js';
|
|
6
6
|
import './chunk-BKHSQ4YM.js';
|
package/dist/workspace.cjs
CHANGED
|
@@ -5061,6 +5061,17 @@ function hasOwnCandlePaint(style) {
|
|
|
5061
5061
|
for (const t of chartTypes()) if (t.id === style) return (t.basePainting ?? "candles") === "candles";
|
|
5062
5062
|
return false;
|
|
5063
5063
|
}
|
|
5064
|
+
var CANDLE_OVERRIDE_KEYS = [
|
|
5065
|
+
"candleUpColor",
|
|
5066
|
+
"candleDownColor",
|
|
5067
|
+
"candleBodyVisible",
|
|
5068
|
+
"candleBorderVisible",
|
|
5069
|
+
"candleBorderUpColor",
|
|
5070
|
+
"candleBorderDownColor",
|
|
5071
|
+
"candleWickVisible",
|
|
5072
|
+
"candleWickUpColor",
|
|
5073
|
+
"candleWickDownColor"
|
|
5074
|
+
];
|
|
5064
5075
|
function candleOverrideFor(style, bags) {
|
|
5065
5076
|
if (!hasOwnCandlePaint(style)) return null;
|
|
5066
5077
|
const bag = bags[style] ?? {};
|
|
@@ -5132,7 +5143,7 @@ function clampLevel(v) {
|
|
|
5132
5143
|
function clampSpacing(v) {
|
|
5133
5144
|
return v < 0.1 ? 0.1 : v > 10 ? 10 : v;
|
|
5134
5145
|
}
|
|
5135
|
-
function factoryResetConfig(factory) {
|
|
5146
|
+
function factoryResetConfig(factory, priceStyle = factory.series.style) {
|
|
5136
5147
|
const bag = {};
|
|
5137
5148
|
for (const t of chartTypes()) {
|
|
5138
5149
|
const section = t.settings;
|
|
@@ -5154,10 +5165,16 @@ function factoryResetConfig(factory) {
|
|
|
5154
5165
|
if (!section.instances) addRows(section.rows);
|
|
5155
5166
|
bag[t.id] = defaults2;
|
|
5156
5167
|
}
|
|
5168
|
+
for (const t of chartTypes()) {
|
|
5169
|
+
if (!hasOwnCandlePaint(t.id)) continue;
|
|
5170
|
+
const defaults2 = bag[t.id] ?? {};
|
|
5171
|
+
for (const key of CANDLE_OVERRIDE_KEYS) defaults2[key] = null;
|
|
5172
|
+
bag[t.id] = defaults2;
|
|
5173
|
+
}
|
|
5157
5174
|
for (const [typeId, vals] of Object.entries(factory.chartTypes)) {
|
|
5158
5175
|
bag[typeId] = { ...bag[typeId] ?? {}, ...vals };
|
|
5159
5176
|
}
|
|
5160
|
-
return { ...factory, chartTypes: bag };
|
|
5177
|
+
return { ...factory, chartTypes: bag, series: { ...factory.series, style: priceStyle } };
|
|
5161
5178
|
}
|
|
5162
5179
|
function mergeConfig(base, patch) {
|
|
5163
5180
|
const p = asObject(patch);
|
|
@@ -18375,10 +18392,18 @@ var IndicatorRegistry = class {
|
|
|
18375
18392
|
this.records = /* @__PURE__ */ new Map();
|
|
18376
18393
|
this.counter = 0;
|
|
18377
18394
|
}
|
|
18378
|
-
/**
|
|
18379
|
-
|
|
18380
|
-
|
|
18381
|
-
|
|
18395
|
+
/**
|
|
18396
|
+
* Mint a unique per-instance id. Host-supplied ids share the namespace, so a minted
|
|
18397
|
+
* id skips anything already recorded — and anything `taken` reports live elsewhere
|
|
18398
|
+
* (a handle the orchestrator holds outside the records, e.g. a fail-soft native).
|
|
18399
|
+
*/
|
|
18400
|
+
nextId(prefix = "ind", taken = () => false) {
|
|
18401
|
+
let id;
|
|
18402
|
+
do {
|
|
18403
|
+
this.counter += 1;
|
|
18404
|
+
id = `${prefix}-${this.counter}`;
|
|
18405
|
+
} while (this.records.has(id) || taken(id));
|
|
18406
|
+
return id;
|
|
18382
18407
|
}
|
|
18383
18408
|
add(record) {
|
|
18384
18409
|
this.records.set(record.id, record);
|
|
@@ -18585,6 +18610,42 @@ function presetToRange(preset, bars) {
|
|
|
18585
18610
|
return { from: Math.max(first, from), to: last };
|
|
18586
18611
|
}
|
|
18587
18612
|
|
|
18613
|
+
// src/core/marks/visibility.ts
|
|
18614
|
+
function markGroupOwnVisible(choices, groupId, groups) {
|
|
18615
|
+
const chosen = choices[groupId];
|
|
18616
|
+
if (typeof chosen === "boolean") return chosen;
|
|
18617
|
+
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
18618
|
+
}
|
|
18619
|
+
function markGroupVisible(choices, groupId, groups) {
|
|
18620
|
+
if (groupId === void 0) return true;
|
|
18621
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18622
|
+
let id = groupId;
|
|
18623
|
+
while (id !== void 0 && !seen.has(id)) {
|
|
18624
|
+
seen.add(id);
|
|
18625
|
+
if (!markGroupOwnVisible(choices, id, groups)) return false;
|
|
18626
|
+
const parent = groups.find((g) => g.id === id)?.parent;
|
|
18627
|
+
id = parent !== void 0 && groups.some((g) => g.id === parent) ? parent : void 0;
|
|
18628
|
+
}
|
|
18629
|
+
return true;
|
|
18630
|
+
}
|
|
18631
|
+
function markGroupRows(groups) {
|
|
18632
|
+
const ids = new Set(groups.map((g) => g.id));
|
|
18633
|
+
const out = [];
|
|
18634
|
+
const placed = /* @__PURE__ */ new Set();
|
|
18635
|
+
const place = (group, depth) => {
|
|
18636
|
+
if (placed.has(group.id)) return;
|
|
18637
|
+
placed.add(group.id);
|
|
18638
|
+
out.push({ group, depth });
|
|
18639
|
+
for (const child of groups) if (child.parent === group.id && child.id !== group.id) place(child, depth + 1);
|
|
18640
|
+
};
|
|
18641
|
+
for (const g of groups) {
|
|
18642
|
+
const parentKnown = g.parent !== void 0 && ids.has(g.parent) && g.parent !== g.id;
|
|
18643
|
+
if (!parentKnown) place(g, 0);
|
|
18644
|
+
}
|
|
18645
|
+
for (const g of groups) place(g, 0);
|
|
18646
|
+
return out;
|
|
18647
|
+
}
|
|
18648
|
+
|
|
18588
18649
|
// src/core/marks/MarksController.ts
|
|
18589
18650
|
var MarksController = class {
|
|
18590
18651
|
constructor(renderer, events) {
|
|
@@ -18629,6 +18690,7 @@ var MarksController = class {
|
|
|
18629
18690
|
defineGroup(group) {
|
|
18630
18691
|
if (!group || typeof group.id !== "string" || group.id.length === 0) throw new Error("[vela] marks.defineGroup: `id` must be a non-empty string");
|
|
18631
18692
|
if (typeof group.label !== "string") throw new Error(`[vela] marks.defineGroup: group "${group.id}" needs a string \`label\``);
|
|
18693
|
+
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`);
|
|
18632
18694
|
this.groups.set(group.id, { ...group });
|
|
18633
18695
|
this.sync();
|
|
18634
18696
|
}
|
|
@@ -18648,12 +18710,16 @@ var MarksController = class {
|
|
|
18648
18710
|
}
|
|
18649
18711
|
this.renderer.applyFeature("marks", { groups: { [id]: visible } });
|
|
18650
18712
|
}
|
|
18651
|
-
/**
|
|
18713
|
+
/**
|
|
18714
|
+
* A group's effective visibility: its own switch — the user's (persisted) choice, else
|
|
18715
|
+
* the declared default, else visible — AND every ancestor's, so a child under a
|
|
18716
|
+
* switched-off parent reads hidden whatever its own choice says.
|
|
18717
|
+
*/
|
|
18652
18718
|
isGroupVisible(id) {
|
|
18653
18719
|
const state = this.renderer.readFeature("marks");
|
|
18654
|
-
const
|
|
18655
|
-
if (typeof
|
|
18656
|
-
return this.groups.
|
|
18720
|
+
const groups = {};
|
|
18721
|
+
for (const [gid, v] of Object.entries(state?.groups ?? {})) if (typeof v === "boolean") groups[gid] = v;
|
|
18722
|
+
return markGroupVisible(groups, id, [...this.groups.values()]);
|
|
18657
18723
|
}
|
|
18658
18724
|
destroy() {
|
|
18659
18725
|
for (const unsub of this.subs) unsub();
|
|
@@ -19720,7 +19786,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
19720
19786
|
this.engines.set(language, engine);
|
|
19721
19787
|
}
|
|
19722
19788
|
addIndicator(source, options = {}) {
|
|
19723
|
-
const id = this.
|
|
19789
|
+
const id = this.claimIndicatorId(options.id);
|
|
19724
19790
|
const title = options.title ?? "Indicator";
|
|
19725
19791
|
const handle = new IndicatorHandleImpl(id, title, this, source);
|
|
19726
19792
|
this.handles.set(id, handle);
|
|
@@ -19742,7 +19808,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
19742
19808
|
const existing = this.registry.all().find((r) => r.native?.type === type);
|
|
19743
19809
|
if (existing) return this.handles.get(existing.id) ?? new IndicatorHandleImpl(existing.id, existing.title, this, void 0, type);
|
|
19744
19810
|
}
|
|
19745
|
-
const id = this.registry.nextId("native");
|
|
19811
|
+
const id = this.registry.nextId("native", (candidate) => this.handles.has(candidate));
|
|
19746
19812
|
const title = descriptor?.title ?? type;
|
|
19747
19813
|
const handle = new IndicatorHandleImpl(id, title, this, void 0, type);
|
|
19748
19814
|
this.handles.set(id, handle);
|
|
@@ -20020,6 +20086,24 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
20020
20086
|
this.events.clear();
|
|
20021
20087
|
}
|
|
20022
20088
|
// ── internals ───────────────────────────────────────────────
|
|
20089
|
+
/**
|
|
20090
|
+
* The id a new script indicator runs under: the host's when supplied, else a minted
|
|
20091
|
+
* one. A host id is opaque but must be a non-empty string, and it must not be live
|
|
20092
|
+
* on this chart — a duplicate is a programming error surfaced synchronously, never
|
|
20093
|
+
* renamed behind the caller's back (the whole point of supplying one is that
|
|
20094
|
+
* `handle.id` equals what was passed). "Live" reads both the records and the handle
|
|
20095
|
+
* map: a fail-soft handle never enters the registry but still owns its id.
|
|
20096
|
+
*/
|
|
20097
|
+
claimIndicatorId(requested) {
|
|
20098
|
+
if (requested === void 0) return this.registry.nextId("ind", (candidate) => this.handles.has(candidate));
|
|
20099
|
+
if (typeof requested !== "string" || requested.length === 0) {
|
|
20100
|
+
throw new TypeError("[vela] addIndicator: `id` must be a non-empty string");
|
|
20101
|
+
}
|
|
20102
|
+
if (this.handles.has(requested) || this.registry.get(requested)) {
|
|
20103
|
+
throw new Error(`[vela] addIndicator: indicator id "${requested}" is already live on this chart`);
|
|
20104
|
+
}
|
|
20105
|
+
return requested;
|
|
20106
|
+
}
|
|
20023
20107
|
async startIndicator(id, source, options, handle) {
|
|
20024
20108
|
try {
|
|
20025
20109
|
await this.readyPromise;
|
|
@@ -25642,11 +25726,8 @@ function mergeMarksState(base, patch) {
|
|
|
25642
25726
|
for (const [id, v] of Object.entries(g)) if (typeof v === "boolean") groups[id] = v;
|
|
25643
25727
|
return { visible: typeof p.visible === "boolean" ? p.visible : base.visible, groups };
|
|
25644
25728
|
}
|
|
25645
|
-
function
|
|
25646
|
-
|
|
25647
|
-
const chosen = state.groups[groupId];
|
|
25648
|
-
if (typeof chosen === "boolean") return chosen;
|
|
25649
|
-
return groups.find((g) => g.id === groupId)?.visible !== false;
|
|
25729
|
+
function markGroupVisible2(state, groupId, groups) {
|
|
25730
|
+
return markGroupVisible(state.groups, groupId, groups);
|
|
25650
25731
|
}
|
|
25651
25732
|
|
|
25652
25733
|
// src/renderers/native/core/SceneGraph.ts
|
|
@@ -27822,13 +27903,29 @@ function paintMarkLane(ctx, layout, deps) {
|
|
|
27822
27903
|
const img = deps.icons.get(mark.glyph.icon, ink, symbolPx, deps.dpr);
|
|
27823
27904
|
if (img) ctx.drawImage(img, center.x - symbolPx / 2, center.y - symbolPx / 2, symbolPx, symbolPx);
|
|
27824
27905
|
} else if (mark.glyph.letter) {
|
|
27906
|
+
const letter = mark.glyph.letter.slice(0, 2);
|
|
27825
27907
|
ctx.fillStyle = ink;
|
|
27826
|
-
|
|
27827
|
-
ctx.
|
|
27908
|
+
let px = letterFontPx(size, letter);
|
|
27909
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
27910
|
+
if (letter.length > 1) {
|
|
27911
|
+
px = fitLetterPx(px, ctx.measureText(letter).width, symbolInnerWidth(shape, size));
|
|
27912
|
+
ctx.font = `600 ${px}px ${deps.fontFamily}`;
|
|
27913
|
+
}
|
|
27914
|
+
ctx.fillText(letter, center.x, center.y + 0.5);
|
|
27828
27915
|
}
|
|
27829
27916
|
}
|
|
27830
27917
|
ctx.restore();
|
|
27831
27918
|
}
|
|
27919
|
+
function letterFontPx(size, letter) {
|
|
27920
|
+
return Math.round(size * (letter.length > 1 ? 0.38 : 0.58));
|
|
27921
|
+
}
|
|
27922
|
+
function symbolInnerWidth(shape, size) {
|
|
27923
|
+
return (shape === "pin" ? size * 0.82 : size) - 3;
|
|
27924
|
+
}
|
|
27925
|
+
function fitLetterPx(px, width, inner) {
|
|
27926
|
+
if (!(width > inner) || !(width > 0)) return px;
|
|
27927
|
+
return Math.max(4, Math.floor(px * inner / width));
|
|
27928
|
+
}
|
|
27832
27929
|
function traceShape(ctx, shape, x, y, size) {
|
|
27833
27930
|
const r = size / 2;
|
|
27834
27931
|
ctx.beginPath();
|
|
@@ -28030,7 +28127,7 @@ var ChromeRenderer = class {
|
|
|
28030
28127
|
this.markLayout = layoutMarkLane({
|
|
28031
28128
|
marks: scene.timelineMarks,
|
|
28032
28129
|
groups: scene.markGroups,
|
|
28033
|
-
hidden: (groupId) => !
|
|
28130
|
+
hidden: (groupId) => !markGroupVisible2(scene.marks, groupId, scene.markGroups),
|
|
28034
28131
|
barTimes: this.barTimes(scene),
|
|
28035
28132
|
intervalMs: coords.barInterval,
|
|
28036
28133
|
xOf: (bar) => coords.logicalToX(bar),
|
|
@@ -28720,6 +28817,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
28720
28817
|
muted and non-interactive. Applied to each row's children so it survives display:contents;
|
|
28721
28818
|
!important beats the inline opacity on labels. */
|
|
28722
28819
|
.vela-sd-soft>*{opacity:0.4 !important;pointer-events:none !important;}
|
|
28820
|
+
/* A mark group nested under a parent group on the Events tab: indented one step per level
|
|
28821
|
+
(--vela-sd-depth). The indent rides the first child (the switch) as a MARGIN \u2014 padding
|
|
28822
|
+
would push the switch's own tick out of its box. */
|
|
28823
|
+
.vela-sd-nested>*:first-child{margin-left:calc(var(--vela-sd-depth,1)*24px);}
|
|
28723
28824
|
/* \u2500\u2500 mobile presentation (.vela-sd-mobile on the scrim; structural sizes are inline in open()) \u2500\u2500
|
|
28724
28825
|
The tab rail becomes a burger-opened overlay sidebar; the group TOC becomes a sticky
|
|
28725
28826
|
row of horizontally scrollable tabs; the instance strip scrolls instead of wrapping;
|
|
@@ -28768,6 +28869,8 @@ var SettingsDialog = class {
|
|
|
28768
28869
|
this.hostSections = [];
|
|
28769
28870
|
/** The timeline-mark groups (defined + named by marks) — one checkbox each on the Events tab. */
|
|
28770
28871
|
this.markGroups = [];
|
|
28872
|
+
/** A group's OWN switch (what its checkbox shows) — a child under an off parent keeps its own state. */
|
|
28873
|
+
this.markGroupOwnVisible = () => true;
|
|
28771
28874
|
this.markGroupVisible = () => true;
|
|
28772
28875
|
/** The Canvas → Theme row: current app theme + where a pick is raised. The row is a
|
|
28773
28876
|
* host callback, NOT a config patch — the app theme stays out of the persisted
|
|
@@ -28785,6 +28888,9 @@ var SettingsDialog = class {
|
|
|
28785
28888
|
this.activeSection = null;
|
|
28786
28889
|
/** Mobile chrome: fullscreen card, burger-opened section sidebar, TOC as top tabs. */
|
|
28787
28890
|
this.mobileLayout = false;
|
|
28891
|
+
/** Opens/closes the mobile section sidebar of the CURRENT build (the burger in the
|
|
28892
|
+
* shell header outlives pane rebuilds, so it reaches the rail through here). */
|
|
28893
|
+
this.toggleRail = null;
|
|
28788
28894
|
/** The visibility policy: setting ids hidden by the host (subtree semantics). */
|
|
28789
28895
|
this.hiddenSettings = /* @__PURE__ */ new Set();
|
|
28790
28896
|
if (getComputedStyle(container).position === "static") container.style.position = "relative";
|
|
@@ -28794,7 +28900,8 @@ var SettingsDialog = class {
|
|
|
28794
28900
|
this.hostSections = sections;
|
|
28795
28901
|
}
|
|
28796
28902
|
/** The timeline-mark groups and their current visibility — the Events tab's rows on next open. */
|
|
28797
|
-
setMarkGroups(groups, visible) {
|
|
28903
|
+
setMarkGroups(groups, visible, ownVisible = visible) {
|
|
28904
|
+
this.markGroupOwnVisible = ownVisible;
|
|
28798
28905
|
this.markGroups = groups;
|
|
28799
28906
|
this.markGroupVisible = visible;
|
|
28800
28907
|
}
|
|
@@ -28860,7 +28967,6 @@ var SettingsDialog = class {
|
|
|
28860
28967
|
this.onReset = onReset ?? null;
|
|
28861
28968
|
ensureControlStyles();
|
|
28862
28969
|
const mobile = this.mobileLayout;
|
|
28863
|
-
let toggleRail = null;
|
|
28864
28970
|
let burger;
|
|
28865
28971
|
if (mobile) {
|
|
28866
28972
|
burger = document.createElement("button");
|
|
@@ -28868,8 +28974,83 @@ var SettingsDialog = class {
|
|
|
28868
28974
|
burger.className = "vela-sd-burger";
|
|
28869
28975
|
burger.innerHTML = iconAt("burger", 16);
|
|
28870
28976
|
burger.title = "Sections";
|
|
28871
|
-
burger.addEventListener("click", () => toggleRail?.());
|
|
28977
|
+
burger.addEventListener("click", () => this.toggleRail?.());
|
|
28978
|
+
}
|
|
28979
|
+
const ui = new Dialog({
|
|
28980
|
+
host: this.container,
|
|
28981
|
+
title: "Chart settings",
|
|
28982
|
+
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
28983
|
+
// machine locks pointer events on the whole body, killing the chart, the
|
|
28984
|
+
// legend, and the body-portaled popovers (color picker, select lists).
|
|
28985
|
+
modal: false,
|
|
28986
|
+
contained: true,
|
|
28987
|
+
align: "top",
|
|
28988
|
+
draggable: !mobile,
|
|
28989
|
+
flush: true,
|
|
28990
|
+
className: "vela-dialog--settings",
|
|
28991
|
+
headerStart: burger,
|
|
28992
|
+
closeOnBackdrop: true,
|
|
28993
|
+
footer: (foot) => {
|
|
28994
|
+
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
28995
|
+
const resetBtn = document.createElement("button");
|
|
28996
|
+
resetBtn.type = "button";
|
|
28997
|
+
resetBtn.textContent = "Reset defaults";
|
|
28998
|
+
resetBtn.className = "vela-sd-btn";
|
|
28999
|
+
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
29000
|
+
foot.appendChild(resetBtn);
|
|
29001
|
+
},
|
|
29002
|
+
// A close signal may only close ITS OWN dialog: the machine reports the exit
|
|
29003
|
+
// asynchronously, so a close-then-reopen in one tick would otherwise see the
|
|
29004
|
+
// old instance's signal tear down the freshly opened one.
|
|
29005
|
+
onOpenChange: (open2) => {
|
|
29006
|
+
if (!open2 && this.ui === ui) this.close();
|
|
29007
|
+
}
|
|
29008
|
+
});
|
|
29009
|
+
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
29010
|
+
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
29011
|
+
this.root = ui.positioner;
|
|
29012
|
+
this.ui = ui;
|
|
29013
|
+
const panes = this.buildContent(ui, config, section, mobile);
|
|
29014
|
+
ui.show();
|
|
29015
|
+
this.layoutPanes(panes);
|
|
29016
|
+
}
|
|
29017
|
+
/**
|
|
29018
|
+
* Re-seed every control of an OPEN dialog from `config`, in place: the shell stays
|
|
29019
|
+
* (no close/open transition), only the tab rail and panes rebuild, landing back on
|
|
29020
|
+
* the current tab. The reset path — the restored values must show without the
|
|
29021
|
+
* dialog re-entering. No-op while closed.
|
|
29022
|
+
*/
|
|
29023
|
+
refresh(config) {
|
|
29024
|
+
const ui = this.ui;
|
|
29025
|
+
if (!ui) return;
|
|
29026
|
+
closeOpenPopovers();
|
|
29027
|
+
closeWidthPopover();
|
|
29028
|
+
for (const dispose of this.hintTips) dispose();
|
|
29029
|
+
this.hintTips = [];
|
|
29030
|
+
this.config = config;
|
|
29031
|
+
ui.body.replaceChildren();
|
|
29032
|
+
this.layoutPanes(this.buildContent(ui, config, this.activeSection ?? void 0, this.mobileLayout));
|
|
29033
|
+
}
|
|
29034
|
+
/** Structured chart-type panes (instance strip / group TOC) own their layout and
|
|
29035
|
+
* tag their rows hosts instead; each host gets its own field grid. Runs on a SHOWN
|
|
29036
|
+
* dialog — the grids measure their labels. */
|
|
29037
|
+
layoutPanes(panes) {
|
|
29038
|
+
for (const el of panes) {
|
|
29039
|
+
const hosts = [...el.querySelectorAll("[data-sd-rows-host]")];
|
|
29040
|
+
if (hosts.length === 0) {
|
|
29041
|
+
this.layoutSettingsGrids(el);
|
|
29042
|
+
continue;
|
|
29043
|
+
}
|
|
29044
|
+
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
28872
29045
|
}
|
|
29046
|
+
}
|
|
29047
|
+
/**
|
|
29048
|
+
* Build the tab rail + one pane per section into `ui.body` (the linear `body` of
|
|
29049
|
+
* section markers and rows is split afterwards), select `section` (the active
|
|
29050
|
+
* style's own tab when none is asked for), and return the pane elements for
|
|
29051
|
+
* {@link layoutPanes}.
|
|
29052
|
+
*/
|
|
29053
|
+
buildContent(ui, config, section, mobile) {
|
|
28873
29054
|
const body = document.createElement("div");
|
|
28874
29055
|
body.style.cssText = "display:flex;flex-direction:column;gap:0;";
|
|
28875
29056
|
const sid = (el, id) => {
|
|
@@ -29073,9 +29254,28 @@ var SettingsDialog = class {
|
|
|
29073
29254
|
if (this.markGroups.length > 0) {
|
|
29074
29255
|
body.append(sid(this.section("Events"), MARKS_SETTINGS_ID));
|
|
29075
29256
|
body.append(sid(this.sectionTitle("Visible events"), MARKS_GROUPS_SETTINGS_ID));
|
|
29076
|
-
|
|
29077
|
-
|
|
29257
|
+
const rowsById = /* @__PURE__ */ new Map();
|
|
29258
|
+
const rows = markGroupRows(this.markGroups);
|
|
29259
|
+
const refreshDimming = () => {
|
|
29260
|
+
for (const { group } of rows) {
|
|
29261
|
+
const el = rowsById.get(group.id);
|
|
29262
|
+
if (!el || group.parent === void 0) continue;
|
|
29263
|
+
el.classList.toggle("vela-sd-soft", !this.markGroupVisible(group.parent));
|
|
29264
|
+
}
|
|
29265
|
+
};
|
|
29266
|
+
for (const { group: g, depth } of rows) {
|
|
29267
|
+
const row = this.boolRow(g.label, this.markGroupOwnVisible(g.id), (v) => {
|
|
29268
|
+
this.emit({ marks: { groups: { [g.id]: v } } });
|
|
29269
|
+
refreshDimming();
|
|
29270
|
+
});
|
|
29271
|
+
if (depth > 0) {
|
|
29272
|
+
row.classList.add("vela-sd-nested");
|
|
29273
|
+
row.style.setProperty("--vela-sd-depth", String(depth));
|
|
29274
|
+
}
|
|
29275
|
+
rowsById.set(g.id, row);
|
|
29276
|
+
body.append(sid(row, markGroupSettingsId(g.id)));
|
|
29078
29277
|
}
|
|
29278
|
+
refreshDimming();
|
|
29079
29279
|
}
|
|
29080
29280
|
renderChartTypeSections("end");
|
|
29081
29281
|
renderHostSections("end");
|
|
@@ -29103,8 +29303,8 @@ var SettingsDialog = class {
|
|
|
29103
29303
|
if (mobile) {
|
|
29104
29304
|
railScrim = document.createElement("div");
|
|
29105
29305
|
railScrim.className = "vela-sd-railscrim";
|
|
29106
|
-
railScrim.addEventListener("click", () => toggleRail?.());
|
|
29107
|
-
toggleRail = (open2) => {
|
|
29306
|
+
railScrim.addEventListener("click", () => this.toggleRail?.());
|
|
29307
|
+
this.toggleRail = (open2) => {
|
|
29108
29308
|
const on = open2 ?? !rail.classList.contains("open");
|
|
29109
29309
|
rail.classList.toggle("open", on);
|
|
29110
29310
|
railScrim?.classList.toggle("open", on);
|
|
@@ -29144,35 +29344,6 @@ var SettingsDialog = class {
|
|
|
29144
29344
|
});
|
|
29145
29345
|
if (hidActive) activate(0);
|
|
29146
29346
|
};
|
|
29147
|
-
const ui = new Dialog({
|
|
29148
|
-
host: this.container,
|
|
29149
|
-
title: "Chart settings",
|
|
29150
|
-
// Non-modal: a live-edit dialog must leave the page interactive — a modal
|
|
29151
|
-
// machine locks pointer events on the whole body, killing the chart, the
|
|
29152
|
-
// legend, and the body-portaled popovers (color picker, select lists).
|
|
29153
|
-
modal: false,
|
|
29154
|
-
contained: true,
|
|
29155
|
-
align: "top",
|
|
29156
|
-
draggable: !mobile,
|
|
29157
|
-
flush: true,
|
|
29158
|
-
className: "vela-dialog--settings",
|
|
29159
|
-
headerStart: burger,
|
|
29160
|
-
closeOnBackdrop: true,
|
|
29161
|
-
footer: (foot) => {
|
|
29162
|
-
foot.style.cssText = `padding:10px 14px;display:flex;align-items:center;justify-content:flex-start;gap:8px;`;
|
|
29163
|
-
const resetBtn = document.createElement("button");
|
|
29164
|
-
resetBtn.type = "button";
|
|
29165
|
-
resetBtn.textContent = "Reset defaults";
|
|
29166
|
-
resetBtn.className = "vela-sd-btn";
|
|
29167
|
-
resetBtn.addEventListener("click", () => this.onReset?.());
|
|
29168
|
-
foot.appendChild(resetBtn);
|
|
29169
|
-
},
|
|
29170
|
-
onOpenChange: (open2) => {
|
|
29171
|
-
if (!open2) this.close();
|
|
29172
|
-
}
|
|
29173
|
-
});
|
|
29174
|
-
if (mobile) ui.positioner.classList.add("vela-sd-mobile");
|
|
29175
|
-
ui.positioner.style.paddingTop = mobile ? "0" : "8vh";
|
|
29176
29347
|
const activate = (idx) => {
|
|
29177
29348
|
panes.forEach((p, i) => {
|
|
29178
29349
|
p.el.style.display = i === idx ? "block" : "none";
|
|
@@ -29181,7 +29352,7 @@ var SettingsDialog = class {
|
|
|
29181
29352
|
this.activeSection = panes[idx]?.title ?? null;
|
|
29182
29353
|
if (mobile) {
|
|
29183
29354
|
ui.titleEl.textContent = panes[idx]?.title ?? "Chart settings";
|
|
29184
|
-
toggleRail?.(false);
|
|
29355
|
+
this.toggleRail?.(false);
|
|
29185
29356
|
}
|
|
29186
29357
|
};
|
|
29187
29358
|
panes.forEach((p, i) => {
|
|
@@ -29196,17 +29367,7 @@ var SettingsDialog = class {
|
|
|
29196
29367
|
shell.append(rail, paneHost);
|
|
29197
29368
|
if (railScrim) shell.append(railScrim);
|
|
29198
29369
|
ui.body.appendChild(shell);
|
|
29199
|
-
|
|
29200
|
-
this.ui = ui;
|
|
29201
|
-
ui.show();
|
|
29202
|
-
for (const p of panes) {
|
|
29203
|
-
const hosts = [...p.el.querySelectorAll("[data-sd-rows-host]")];
|
|
29204
|
-
if (hosts.length === 0) {
|
|
29205
|
-
this.layoutSettingsGrids(p.el);
|
|
29206
|
-
continue;
|
|
29207
|
-
}
|
|
29208
|
-
for (const h of hosts) this.layoutSettingsGrids(h);
|
|
29209
|
-
}
|
|
29370
|
+
return panes.map((p) => p.el);
|
|
29210
29371
|
}
|
|
29211
29372
|
close() {
|
|
29212
29373
|
closeOpenPopovers();
|
|
@@ -29214,6 +29375,7 @@ var SettingsDialog = class {
|
|
|
29214
29375
|
const ui = this.ui;
|
|
29215
29376
|
this.ui = null;
|
|
29216
29377
|
this.root = null;
|
|
29378
|
+
this.toggleRail = null;
|
|
29217
29379
|
this.tabs = [];
|
|
29218
29380
|
for (const dispose of this.hintTips) dispose();
|
|
29219
29381
|
this.hintTips = [];
|
|
@@ -36532,7 +36694,11 @@ var NativeRenderer = class {
|
|
|
36532
36694
|
}
|
|
36533
36695
|
this.settingsDialog.setTheme(this.theme);
|
|
36534
36696
|
this.settingsDialog.setHostSections(this.hostSettingsSections);
|
|
36535
|
-
this.settingsDialog.setMarkGroups(
|
|
36697
|
+
this.settingsDialog.setMarkGroups(
|
|
36698
|
+
this.markGroupsForEventsTab(),
|
|
36699
|
+
(id) => markGroupVisible2(this.scene.marks, id, this.scene.markGroups),
|
|
36700
|
+
(id) => markGroupOwnVisible(this.scene.marks.groups, id, this.scene.markGroups)
|
|
36701
|
+
);
|
|
36536
36702
|
this.settingsDialog.setHiddenSettings(this.hiddenSettings);
|
|
36537
36703
|
this.syncThemeControl();
|
|
36538
36704
|
this.settingsDialog.toggle(
|
|
@@ -36540,13 +36706,24 @@ var NativeRenderer = class {
|
|
|
36540
36706
|
(patch) => this.applyConfig(patch),
|
|
36541
36707
|
(json) => this.applyConfig(json),
|
|
36542
36708
|
() => {
|
|
36543
|
-
if (this.factoryConfig) this.applyConfig(
|
|
36544
|
-
this.settingsDialog?.
|
|
36545
|
-
this.openSettingsDialog();
|
|
36709
|
+
if (this.factoryConfig) this.applyConfig(this.factoryResetDocument(this.factoryConfig));
|
|
36710
|
+
this.settingsDialog?.refresh(this.getConfig());
|
|
36546
36711
|
},
|
|
36547
36712
|
section
|
|
36548
36713
|
);
|
|
36549
36714
|
}
|
|
36715
|
+
/**
|
|
36716
|
+
* The document "Reset defaults" applies: every setting back to its first-run value,
|
|
36717
|
+
* with two things that are NOT settings held or resolved here — the price style
|
|
36718
|
+
* stays the one the user is looking at, and the timeline-mark groups (an additive
|
|
36719
|
+
* merge, like the type bags) are named back to their host-declared visibility.
|
|
36720
|
+
*/
|
|
36721
|
+
factoryResetDocument(factory) {
|
|
36722
|
+
const doc = factoryResetConfig(factory, this.scene.priceStyle);
|
|
36723
|
+
const groups = { ...doc.marks.groups };
|
|
36724
|
+
for (const g of this.markGroupsInUse()) groups[g.id] = g.visible !== false;
|
|
36725
|
+
return { ...doc, marks: { ...doc.marks, groups } };
|
|
36726
|
+
}
|
|
36550
36727
|
/** Close the in-chart dialogs (indicator settings + chart-settings gear). No-op when none are open. */
|
|
36551
36728
|
closeDialogs() {
|
|
36552
36729
|
this.inputsUI?.closeOpenDialog();
|
|
@@ -37609,6 +37786,15 @@ var NativeRenderer = class {
|
|
|
37609
37786
|
markGroupsInUse() {
|
|
37610
37787
|
return effectiveMarkGroups(this.scene.timelineMarks, this.scene.markGroups);
|
|
37611
37788
|
}
|
|
37789
|
+
/**
|
|
37790
|
+
* The groups as the Events tab lists them: nested only under a DEFINED parent. The
|
|
37791
|
+
* painter's visibility chain resolves parents against the defined groups alone, so a
|
|
37792
|
+
* parent that marks merely name must not nest (and dim) a child the painter still shows.
|
|
37793
|
+
*/
|
|
37794
|
+
markGroupsForEventsTab() {
|
|
37795
|
+
const defined = new Set(this.scene.markGroups.map((g) => g.id));
|
|
37796
|
+
return this.markGroupsInUse().map((g) => g.parent !== void 0 && !defined.has(g.parent) ? { ...g, parent: void 0 } : g);
|
|
37797
|
+
}
|
|
37612
37798
|
onViewportChange(cb) {
|
|
37613
37799
|
this.viewportCbs.add(cb);
|
|
37614
37800
|
return () => this.viewportCbs.delete(cb);
|
|
@@ -41749,6 +41935,7 @@ function registerClassicIndicators() {
|
|
|
41749
41935
|
}
|
|
41750
41936
|
|
|
41751
41937
|
// src/Vela.ts
|
|
41938
|
+
var asError = (err) => err instanceof Error ? err : new Error(String(err));
|
|
41752
41939
|
var Vela = class {
|
|
41753
41940
|
constructor(container, options = {}, deps = {}) {
|
|
41754
41941
|
registerBuiltinChartTypes();
|
|
@@ -41872,7 +42059,12 @@ var Vela = class {
|
|
|
41872
42059
|
* fetch from — the same relationship `script:run` has to `context:changed`.
|
|
41873
42060
|
*/
|
|
41874
42061
|
runScript(source, options) {
|
|
41875
|
-
|
|
42062
|
+
let handle;
|
|
42063
|
+
try {
|
|
42064
|
+
handle = this.addIndicator(source, options);
|
|
42065
|
+
} catch (err) {
|
|
42066
|
+
return Promise.resolve({ ok: false, run: null, error: asError(err), onUpdate: () => () => void 0, remove: () => void 0 });
|
|
42067
|
+
}
|
|
41876
42068
|
const updates = /* @__PURE__ */ new Set();
|
|
41877
42069
|
const drop = () => {
|
|
41878
42070
|
try {
|
|
@@ -41916,7 +42108,12 @@ var Vela = class {
|
|
|
41916
42108
|
});
|
|
41917
42109
|
}
|
|
41918
42110
|
runIndicator(source, options) {
|
|
41919
|
-
|
|
42111
|
+
let handle;
|
|
42112
|
+
try {
|
|
42113
|
+
handle = this.addIndicator(source, options);
|
|
42114
|
+
} catch (err) {
|
|
42115
|
+
return Promise.resolve({ ok: false, handle: null, error: asError(err), context: null });
|
|
42116
|
+
}
|
|
41920
42117
|
return new Promise((resolve) => {
|
|
41921
42118
|
const offReady = handle.on("ready", () => {
|
|
41922
42119
|
offReady();
|
|
@@ -43501,6 +43698,11 @@ var ChartCell = class {
|
|
|
43501
43698
|
if (typeof zone === "string" && normalizeTimezone(zone) !== normalizeTimezone(this.deps.timezone())) {
|
|
43502
43699
|
this.deps.setTimezone(normalizeTimezone(zone));
|
|
43503
43700
|
}
|
|
43701
|
+
const style = this.priceStyle;
|
|
43702
|
+
if (style !== (this.state.priceStyle ?? "candles")) {
|
|
43703
|
+
this.state.priceStyle = style;
|
|
43704
|
+
this.deps.onPriceStyleChanged(this.id);
|
|
43705
|
+
}
|
|
43504
43706
|
this.syncStatuslineColors();
|
|
43505
43707
|
this.syncPlotOverlayTokens();
|
|
43506
43708
|
});
|
|
@@ -44140,16 +44342,19 @@ var ChartCell = class {
|
|
|
44140
44342
|
* a persistence handler's `restore` runs silently, a user-driven call records.
|
|
44141
44343
|
*/
|
|
44142
44344
|
addExternalIndicator(entry) {
|
|
44345
|
+
const { id, inputs, props, hidden, ...script } = entry;
|
|
44143
44346
|
this.addManifestInstance(
|
|
44144
|
-
{ ...
|
|
44145
|
-
{ external: true, ...
|
|
44347
|
+
{ ...script, enabled: true },
|
|
44348
|
+
{ external: true, ...id !== void 0 ? { id } : {}, ...inputs ? { inputs } : {}, ...props ? { props } : {}, ...hidden ? { hidden: true } : {} }
|
|
44146
44349
|
);
|
|
44147
44350
|
}
|
|
44148
44351
|
/** Add ONE instance of a manifest entry (repeatable — duplicates are legitimate). */
|
|
44149
44352
|
addManifestInstance(entry, opts = {}) {
|
|
44150
44353
|
if (this.destroyed) return;
|
|
44151
44354
|
const values = opts.inputs || opts.props ? { inputs: opts.inputs, props: opts.props } : void 0;
|
|
44152
|
-
const
|
|
44355
|
+
const handle = this.addToChart(entry, values, opts.id);
|
|
44356
|
+
if (!handle) return;
|
|
44357
|
+
const it = { entry, handle, id: handle.id, ...opts.external ? { external: true } : {}, ...values ? { values } : {} };
|
|
44153
44358
|
if (opts.hidden) it.handle?.setVisible(false);
|
|
44154
44359
|
this.instances.push(it);
|
|
44155
44360
|
this.deps.onIndicatorsChanged(this.id);
|
|
@@ -44158,7 +44363,7 @@ var ChartCell = class {
|
|
|
44158
44363
|
this.history.push({
|
|
44159
44364
|
undo: () => this.dropInstance(snapshot),
|
|
44160
44365
|
redo: () => {
|
|
44161
|
-
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values);
|
|
44366
|
+
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values, snapshot.id);
|
|
44162
44367
|
this.instances.push(snapshot);
|
|
44163
44368
|
this.deps.onIndicatorsChanged(this.id);
|
|
44164
44369
|
}
|
|
@@ -44171,7 +44376,7 @@ var ChartCell = class {
|
|
|
44171
44376
|
const snapshot = it;
|
|
44172
44377
|
this.history.push({
|
|
44173
44378
|
undo: () => {
|
|
44174
|
-
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values);
|
|
44379
|
+
snapshot.handle = this.addToChart(snapshot.entry, snapshot.values, snapshot.id);
|
|
44175
44380
|
this.instances.push(snapshot);
|
|
44176
44381
|
this.deps.onIndicatorsChanged(this.id);
|
|
44177
44382
|
},
|
|
@@ -44261,9 +44466,10 @@ var ChartCell = class {
|
|
|
44261
44466
|
this.deps.onIndicatorsChanged(this.id);
|
|
44262
44467
|
});
|
|
44263
44468
|
}
|
|
44264
|
-
addToChart(entry, values) {
|
|
44469
|
+
addToChart(entry, values, id) {
|
|
44265
44470
|
try {
|
|
44266
44471
|
return this.inner?.addIndicator(entry.script, {
|
|
44472
|
+
...id !== void 0 ? { id } : {},
|
|
44267
44473
|
...entry.language !== void 0 ? { language: entry.language } : {},
|
|
44268
44474
|
...values?.inputs ? { inputs: values.inputs } : {},
|
|
44269
44475
|
...values?.props ? { props: values.props } : {}
|