@luxalgo/vela 0.6.3 → 0.6.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-DHX4x6-r.d.ts → DataProvider-BmHkcwvJ.d.ts} +1 -1
- package/dist/{DataProvider-CNmk84SH.d.cts → DataProvider-DrN7ZIou.d.cts} +1 -1
- package/dist/{chunk-TP56QRMK.js → chunk-2R7BANEM.js} +1 -1
- package/dist/{chunk-7Y7CJ7EN.js → chunk-BEJ57HP4.js} +8 -1
- package/dist/{chunk-7D6YIF34.js → chunk-FQBT4NFM.js} +431 -74
- package/dist/{chunk-U5KCQHAC.js → chunk-N6MBJHMV.js} +129 -41
- package/dist/{chunk-QHZ7IXFL.js → chunk-OICPLNU7.js} +59 -9
- package/dist/{contributions-DDpv7hEL.d.cts → contributions-2bEmCF9S.d.cts} +2 -2
- package/dist/{contributions-ciV6Neyd.d.ts → contributions-DatoAzMx.d.ts} +2 -2
- package/dist/{history-CFqZm5re.d.ts → history-BmyjaVir.d.cts} +6 -6
- package/dist/{history-ChoT34nz.d.cts → history-CvOtsjT5.d.ts} +6 -6
- package/dist/index.cjs +500 -85
- package/dist/index.d.cts +63 -9
- package/dist/index.d.ts +63 -9
- package/dist/index.js +4 -4
- package/dist/{options-BqGeFHtp.d.ts → options-YdiaaVjt.d.cts} +20 -1
- package/dist/{options-BqGeFHtp.d.cts → options-YdiaaVjt.d.ts} +20 -1
- package/dist/{plugin-C97gUCVf.d.ts → plugin-Bcone6Vh.d.ts} +9 -5
- package/dist/{plugin-CSb_sTiN.d.cts → plugin-DO_DX0gp.d.cts} +9 -5
- package/dist/plugin.cjs +8 -0
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/plugin.js +2 -2
- 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/ui.cjs +59 -9
- package/dist/ui.d.cts +10 -2
- package/dist/ui.d.ts +10 -2
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +500 -85
- package/dist/vela.global.min.js +84 -47
- package/dist/widget.cjs +801 -227
- package/dist/widget.d.cts +34 -8
- package/dist/widget.d.ts +34 -8
- package/dist/widget.js +145 -73
- package/dist/workspace.cjs +756 -178
- package/dist/workspace.d.cts +29 -5
- package/dist/workspace.d.ts +29 -5
- package/dist/workspace.js +143 -67
- package/package.json +1 -1
- /package/dist/{chunk-Q3XQHLIH.js → chunk-AOGZBKUE.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel } from './chunk-
|
|
2
|
-
import { chartType, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, getDrawingType } from './chunk-
|
|
3
|
-
import { Tooltip, Drawer } from './chunk-
|
|
4
|
-
import { Menu, Dialog } from './chunk-
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel } from './chunk-FQBT4NFM.js';
|
|
2
|
+
import { chartType, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, getDrawingType } from './chunk-BEJ57HP4.js';
|
|
3
|
+
import { Tooltip, Drawer } from './chunk-2R7BANEM.js';
|
|
4
|
+
import { Menu, Dialog } from './chunk-OICPLNU7.js';
|
|
5
5
|
import { iconMarkup, registerIcon, injectStyles, iconEl, SESSION_PRE, SESSION_POST, SESSION_OFF, icon, categoricalColor } from './chunk-PN5KWFZ4.js';
|
|
6
6
|
|
|
7
7
|
// src/widget/timeframe.ts
|
|
@@ -492,12 +492,14 @@ var CSS2 = `
|
|
|
492
492
|
color: var(--vela-fg-muted);
|
|
493
493
|
}
|
|
494
494
|
.vela-widget-tf-caret:hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
|
|
495
|
+
/* The merged trigger is a plain button (hover feedback only) \u2014 the highlight
|
|
496
|
+
background marks the CURRENT chip among favorites, and a lone trigger with a
|
|
497
|
+
permanent highlight would read as stuck-pressed. */
|
|
495
498
|
.vela-widget-tf-caret[data-solo='1'] {
|
|
496
499
|
width: auto;
|
|
497
500
|
padding: 0 6px 0 9px;
|
|
498
501
|
gap: 4px;
|
|
499
502
|
color: var(--vela-fg-bright);
|
|
500
|
-
background: var(--vela-hover-strong);
|
|
501
503
|
font-size: 13px;
|
|
502
504
|
font-weight: 550;
|
|
503
505
|
white-space: nowrap;
|
|
@@ -1526,7 +1528,8 @@ var Bottombar = class {
|
|
|
1526
1528
|
const session = doc.createElement("span");
|
|
1527
1529
|
session.className = "vela-bb-session";
|
|
1528
1530
|
this.sessionEl = session;
|
|
1529
|
-
session.
|
|
1531
|
+
session.style.display = "none";
|
|
1532
|
+
session.title = "Session \u2014 regular (RTH) vs extended (ETH) hours";
|
|
1530
1533
|
for (const [key, label] of [["regular", "RTH"], ["extended", "ETH"]]) {
|
|
1531
1534
|
const b = doc.createElement("button");
|
|
1532
1535
|
b.className = "vela-bb-session-btn" + (key === "regular" ? " is-active" : "");
|
|
@@ -1577,15 +1580,15 @@ var Bottombar = class {
|
|
|
1577
1580
|
}
|
|
1578
1581
|
/**
|
|
1579
1582
|
* Reflect the ACTIVE chart's session posture. `enabled: false` (a continuous
|
|
1580
|
-
* market, or metadata not landed yet)
|
|
1581
|
-
*
|
|
1582
|
-
*
|
|
1583
|
+
* market, or metadata not landed yet) HIDES the toggle entirely — RTH/ETH is
|
|
1584
|
+
* meaningless there. Enabled, the chips appear and the active one tracks the
|
|
1585
|
+
* chart's current session.
|
|
1583
1586
|
*/
|
|
1584
1587
|
setSession(state) {
|
|
1585
|
-
if (this.sessionEl) this.sessionEl.
|
|
1588
|
+
if (this.sessionEl) this.sessionEl.style.display = state.enabled ? "" : "none";
|
|
1586
1589
|
for (const [key, b] of this.sessionButtons) {
|
|
1587
1590
|
b.disabled = !state.enabled;
|
|
1588
|
-
b.classList.toggle("is-active", state.enabled ?
|
|
1591
|
+
b.classList.toggle("is-active", key === (state.enabled ? state.session : "regular"));
|
|
1589
1592
|
}
|
|
1590
1593
|
}
|
|
1591
1594
|
destroy() {
|
|
@@ -1748,6 +1751,7 @@ var CSS6 = `
|
|
|
1748
1751
|
.vela-sp-badge[data-p='hyperliquid'] { color: #50d2c1; } /* palette-exempt: venue brand mark */
|
|
1749
1752
|
.vela-sp-empty { padding: var(--vela-space-3); color: var(--vela-fg-muted); text-align: center; }
|
|
1750
1753
|
`;
|
|
1754
|
+
var PAGE = 100;
|
|
1751
1755
|
var SymbolPicker = class {
|
|
1752
1756
|
constructor(opts) {
|
|
1753
1757
|
this.source = () => [];
|
|
@@ -1755,6 +1759,7 @@ var SymbolPicker = class {
|
|
|
1755
1759
|
this.highlighted = 0;
|
|
1756
1760
|
this.seed = "";
|
|
1757
1761
|
this.activeTab = "All";
|
|
1762
|
+
this.visible = PAGE;
|
|
1758
1763
|
const doc = (opts.host ?? document.body).ownerDocument;
|
|
1759
1764
|
injectStyles(STYLE_ID6, CSS6, doc);
|
|
1760
1765
|
this.input = doc.createElement("input");
|
|
@@ -1781,6 +1786,12 @@ var SymbolPicker = class {
|
|
|
1781
1786
|
}
|
|
1782
1787
|
this.list = doc.createElement("div");
|
|
1783
1788
|
this.list.className = "vela-sp-list";
|
|
1789
|
+
this.list.addEventListener("scroll", () => {
|
|
1790
|
+
if (this.rows.length < this.visible) return;
|
|
1791
|
+
if (this.list.scrollTop + this.list.clientHeight < this.list.scrollHeight - 200) return;
|
|
1792
|
+
this.visible += PAGE;
|
|
1793
|
+
this.grow();
|
|
1794
|
+
});
|
|
1784
1795
|
this.dialog = new Dialog({
|
|
1785
1796
|
title: "Symbol Search",
|
|
1786
1797
|
host: opts.host,
|
|
@@ -1846,11 +1857,15 @@ var SymbolPicker = class {
|
|
|
1846
1857
|
} else delete el.dataset.highlighted;
|
|
1847
1858
|
});
|
|
1848
1859
|
}
|
|
1849
|
-
|
|
1850
|
-
const doc = this.list.ownerDocument;
|
|
1860
|
+
computeRows() {
|
|
1851
1861
|
const TAB_TYPES = { Crypto: ["crypto"], Stocks: ["stock"], ETFs: ["etf"], Forex: ["forex"], Commodities: ["commodity"] };
|
|
1852
1862
|
const pool = this.activeTab === "All" ? this.source() : this.source().filter((s) => TAB_TYPES[this.activeTab]?.includes((s.type ?? "").toLowerCase()) || this.activeTab === "Crypto" && (s.type ?? "").toLowerCase() === "futures");
|
|
1853
|
-
|
|
1863
|
+
return filterSymbols(pool, this.input.value, this.visible);
|
|
1864
|
+
}
|
|
1865
|
+
refresh() {
|
|
1866
|
+
const doc = this.list.ownerDocument;
|
|
1867
|
+
this.visible = PAGE;
|
|
1868
|
+
this.rows = this.computeRows();
|
|
1854
1869
|
this.highlighted = 0;
|
|
1855
1870
|
this.list.replaceChildren();
|
|
1856
1871
|
if (!this.rows.length) {
|
|
@@ -1860,34 +1875,42 @@ var SymbolPicker = class {
|
|
|
1860
1875
|
this.list.appendChild(empty);
|
|
1861
1876
|
return;
|
|
1862
1877
|
}
|
|
1863
|
-
for (const s of this.rows)
|
|
1864
|
-
const row = doc.createElement("div");
|
|
1865
|
-
row.className = "vela-sp-row";
|
|
1866
|
-
row.dataset.ticker = s.ticker;
|
|
1867
|
-
const venue = s.prefix ?? s.provider;
|
|
1868
|
-
if (venue) row.dataset.venue = venue;
|
|
1869
|
-
const av = tickerIconEl(doc, baseOf(s), s.ticker, "vela-sp-avatar");
|
|
1870
|
-
const main = doc.createElement("span");
|
|
1871
|
-
main.className = "vela-sp-main";
|
|
1872
|
-
const t = doc.createElement("span");
|
|
1873
|
-
t.className = "vela-sp-ticker";
|
|
1874
|
-
t.textContent = s.ticker;
|
|
1875
|
-
const d = doc.createElement("span");
|
|
1876
|
-
d.className = "vela-sp-desc";
|
|
1877
|
-
d.textContent = s.description ?? (s.type ?? "");
|
|
1878
|
-
main.append(t, d);
|
|
1879
|
-
row.append(av, main);
|
|
1880
|
-
if (venue) {
|
|
1881
|
-
const badge = doc.createElement("span");
|
|
1882
|
-
badge.className = "vela-sp-badge";
|
|
1883
|
-
badge.dataset.p = s.provider ?? venue;
|
|
1884
|
-
badge.textContent = venue;
|
|
1885
|
-
row.appendChild(badge);
|
|
1886
|
-
}
|
|
1887
|
-
this.list.appendChild(row);
|
|
1888
|
-
}
|
|
1878
|
+
for (const s of this.rows) this.list.appendChild(this.rowEl(s));
|
|
1889
1879
|
this.renderHighlight();
|
|
1890
1880
|
}
|
|
1881
|
+
/** Append the page the grown `visible` just uncovered — rows already on screen stay put. */
|
|
1882
|
+
grow() {
|
|
1883
|
+
const already = this.rows.length;
|
|
1884
|
+
this.rows = this.computeRows();
|
|
1885
|
+
for (const s of this.rows.slice(already)) this.list.appendChild(this.rowEl(s));
|
|
1886
|
+
}
|
|
1887
|
+
rowEl(s) {
|
|
1888
|
+
const doc = this.list.ownerDocument;
|
|
1889
|
+
const row = doc.createElement("div");
|
|
1890
|
+
row.className = "vela-sp-row";
|
|
1891
|
+
row.dataset.ticker = s.ticker;
|
|
1892
|
+
const venue = s.prefix ?? s.provider;
|
|
1893
|
+
if (venue) row.dataset.venue = venue;
|
|
1894
|
+
const av = tickerIconEl(doc, baseOf(s), s.ticker, "vela-sp-avatar");
|
|
1895
|
+
const main = doc.createElement("span");
|
|
1896
|
+
main.className = "vela-sp-main";
|
|
1897
|
+
const t = doc.createElement("span");
|
|
1898
|
+
t.className = "vela-sp-ticker";
|
|
1899
|
+
t.textContent = s.ticker;
|
|
1900
|
+
const d = doc.createElement("span");
|
|
1901
|
+
d.className = "vela-sp-desc";
|
|
1902
|
+
d.textContent = s.description ?? (s.type ?? "");
|
|
1903
|
+
main.append(t, d);
|
|
1904
|
+
row.append(av, main);
|
|
1905
|
+
if (venue) {
|
|
1906
|
+
const badge = doc.createElement("span");
|
|
1907
|
+
badge.className = "vela-sp-badge";
|
|
1908
|
+
badge.dataset.p = s.provider ?? venue;
|
|
1909
|
+
badge.textContent = venue;
|
|
1910
|
+
row.appendChild(badge);
|
|
1911
|
+
}
|
|
1912
|
+
return row;
|
|
1913
|
+
}
|
|
1891
1914
|
};
|
|
1892
1915
|
|
|
1893
1916
|
// src/widget/object-tree-model.ts
|
|
@@ -3313,6 +3336,9 @@ var CSS8 = `
|
|
|
3313
3336
|
letter-spacing: 0.08em;
|
|
3314
3337
|
}
|
|
3315
3338
|
.vela-dw-group:first-child { border-top: none; margin-top: 0; padding-top: 8px; }
|
|
3339
|
+
/* The readout is DATA, not chrome: selectable (an exception to the UI-wide
|
|
3340
|
+
user-select:none) so values can be copied out. The panel header stays chrome. */
|
|
3341
|
+
.vela-dw-group, .vela-dw-row { user-select: text; -webkit-user-select: text; cursor: text; }
|
|
3316
3342
|
.vela-dw-row {
|
|
3317
3343
|
display: flex;
|
|
3318
3344
|
align-items: center;
|
|
@@ -3775,6 +3801,9 @@ var ChartContextMenu = class {
|
|
|
3775
3801
|
host,
|
|
3776
3802
|
items: [],
|
|
3777
3803
|
placement: "bottom-start",
|
|
3804
|
+
// Pointer-anchored action menu: checked state reads as a leading ✓, not a
|
|
3805
|
+
// washed row (which would read as hover in a menu with no trigger button).
|
|
3806
|
+
checkmarks: true,
|
|
3778
3807
|
onSelect: (id) => this.run(id)
|
|
3779
3808
|
});
|
|
3780
3809
|
host.addEventListener("contextmenu", this.onContextMenu);
|
|
@@ -4506,6 +4535,65 @@ var MarketStatusTracker = class {
|
|
|
4506
4535
|
}
|
|
4507
4536
|
};
|
|
4508
4537
|
|
|
4538
|
+
// src/widget/session-shading.ts
|
|
4539
|
+
function deriveSessionZones(regular, extended) {
|
|
4540
|
+
const pre = [];
|
|
4541
|
+
const post = [];
|
|
4542
|
+
for (const [extStart, extEnd] of extended) {
|
|
4543
|
+
const inside = regular.filter(([s, e]) => e > extStart && s < extEnd).sort((a, b) => a[0] - b[0]);
|
|
4544
|
+
let cursor = extStart;
|
|
4545
|
+
for (const [regStart, regEnd] of inside) {
|
|
4546
|
+
if (regStart > cursor) pre.push([cursor, Math.min(regStart, extEnd)]);
|
|
4547
|
+
cursor = Math.max(cursor, regEnd);
|
|
4548
|
+
}
|
|
4549
|
+
if (cursor < extEnd) post.push([cursor, extEnd]);
|
|
4550
|
+
}
|
|
4551
|
+
return { pre, post };
|
|
4552
|
+
}
|
|
4553
|
+
var FETCH_AHEAD_MS2 = 10 * 864e5;
|
|
4554
|
+
var MIN_LOOKBACK_MS = 3 * 864e5;
|
|
4555
|
+
var MAX_LOOKBACK_MS = 120 * 864e5;
|
|
4556
|
+
var SessionShadingTracker = class {
|
|
4557
|
+
constructor(onZones) {
|
|
4558
|
+
this.onZones = onZones;
|
|
4559
|
+
/** Invalidates detached async work — bumped by every track()/stop(). */
|
|
4560
|
+
this.epoch = 0;
|
|
4561
|
+
}
|
|
4562
|
+
/** (Re)bind to a chart's data surface + market and evaluate once. */
|
|
4563
|
+
track(data, symbol, opts) {
|
|
4564
|
+
const my = ++this.epoch;
|
|
4565
|
+
void this.evaluate(my, data, symbol, opts);
|
|
4566
|
+
}
|
|
4567
|
+
stop() {
|
|
4568
|
+
this.epoch += 1;
|
|
4569
|
+
}
|
|
4570
|
+
async evaluate(my, data, symbol, opts) {
|
|
4571
|
+
const resolved = data.resolve(symbol);
|
|
4572
|
+
const provider = resolved ? data.providerInstance(resolved.provider) : void 0;
|
|
4573
|
+
const si = await data.symbolInfo(symbol).catch(() => void 0);
|
|
4574
|
+
if (my !== this.epoch) return;
|
|
4575
|
+
const hasSessions = typeof si?.session === "string" && si.session !== "" && si.session !== "24x7";
|
|
4576
|
+
if (!provider?.getCalendar || !hasSessions || !resolved) {
|
|
4577
|
+
this.onZones(null);
|
|
4578
|
+
return;
|
|
4579
|
+
}
|
|
4580
|
+
if (opts.session !== "extended") {
|
|
4581
|
+
this.onZones({ pre: [], post: [] });
|
|
4582
|
+
return;
|
|
4583
|
+
}
|
|
4584
|
+
const now = Date.now();
|
|
4585
|
+
const lookback = Math.max(MIN_LOOKBACK_MS, Math.min(MAX_LOOKBACK_MS, opts.lookbackMs));
|
|
4586
|
+
const range = { from: now - lookback, to: now + FETCH_AHEAD_MS2 };
|
|
4587
|
+
const [regular, extended] = await Promise.all([
|
|
4588
|
+
provider.getCalendar(resolved.ticker, { ...range, session: "regular" }).catch(() => null),
|
|
4589
|
+
provider.getCalendar(resolved.ticker, { ...range, session: "extended" }).catch(() => null)
|
|
4590
|
+
]);
|
|
4591
|
+
if (my !== this.epoch) return;
|
|
4592
|
+
if (!regular || !extended) return;
|
|
4593
|
+
this.onZones(deriveSessionZones(regular, extended));
|
|
4594
|
+
}
|
|
4595
|
+
};
|
|
4596
|
+
|
|
4509
4597
|
// src/widget/layout-mode.ts
|
|
4510
4598
|
var MOBILE_BREAKPOINT_PX = 640;
|
|
4511
4599
|
var COARSE_BREAKPOINT_PX = 920;
|
|
@@ -5872,4 +5960,4 @@ var Toast = class {
|
|
|
5872
5960
|
}
|
|
5873
5961
|
};
|
|
5874
5962
|
|
|
5875
|
-
export { Bottombar, ChartContextMenu, DataWindow, DrawingPill, DrawingsDrawer, Glider, IndicatorPicker, LayoutModeController, MarketStatusTracker, MobileBar, MoreDrawer, ObjectTree, PAN_FAST, PanelDock, PriceScaleDrawer, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeDrawer, TimeframeQuick, TimezoneDrawer, Toast, Topbar, Watermark, WidgetHistory, ZOOM_IN, ZOOM_OUT, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, indicatorLedger, legacyWidgetState, loadPersisted, localStorageAdapter, normalizeSession, parsePersisted, parseTimeframe, prefixedSymbol, priceStyleIcon, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, statuslineInkOf, timeframeLabel, timeframeMs, toolShortcutHints };
|
|
5963
|
+
export { Bottombar, ChartContextMenu, DataWindow, DrawingPill, DrawingsDrawer, Glider, IndicatorPicker, LayoutModeController, MarketStatusTracker, MobileBar, MoreDrawer, ObjectTree, PAN_FAST, PanelDock, PriceScaleDrawer, RANGE_PRESETS, SessionShadingTracker, ShortcutsHelp, Statusline, SymbolPicker, TimeframeDrawer, TimeframeQuick, TimezoneDrawer, Toast, Topbar, Watermark, WidgetHistory, ZOOM_IN, ZOOM_OUT, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, indicatorLedger, legacyWidgetState, loadPersisted, localStorageAdapter, normalizeSession, parsePersisted, parseTimeframe, prefixedSymbol, priceStyleIcon, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, statuslineInkOf, timeframeLabel, timeframeMs, toolShortcutHints };
|
|
@@ -86,6 +86,23 @@ var MENU_CSS = `
|
|
|
86
86
|
background: var(--vela-hover-strong);
|
|
87
87
|
color: var(--vela-fg-bright);
|
|
88
88
|
}
|
|
89
|
+
/* Checkmark mode (context/action menus): every row reserves the leading mark column so
|
|
90
|
+
labels align; a checked row fills it with a \u2713 and brightens its ink \u2014 the row surface
|
|
91
|
+
stays free for the hover wash. */
|
|
92
|
+
.vela-menu-item .vela-menu-mark {
|
|
93
|
+
width: 14px;
|
|
94
|
+
flex: none;
|
|
95
|
+
display: inline-flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
}
|
|
99
|
+
.vela-menu-item .vela-menu-mark .vela-icon {
|
|
100
|
+
width: 14px;
|
|
101
|
+
height: 14px;
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
color: var(--vela-fg-bright);
|
|
104
|
+
}
|
|
105
|
+
.vela-menu-item[data-checkmark] { color: var(--vela-fg-bright); }
|
|
89
106
|
/* Switch rows (boolean settings in a dropdown): a right-aligned toggle pill \u2014 the
|
|
90
107
|
same control language as the settings dialog's toggles. */
|
|
91
108
|
.vela-menu-switch {
|
|
@@ -154,6 +171,7 @@ var Surface = class _Surface {
|
|
|
154
171
|
this.host = opts.host;
|
|
155
172
|
this.onSelect = opts.onSelect;
|
|
156
173
|
this.onFavorite = opts.onFavorite;
|
|
174
|
+
this.checkmarks = opts.checkmarks === true;
|
|
157
175
|
this.positioner = doc.createElement("div");
|
|
158
176
|
this.positioner.className = "vela-ui-layer";
|
|
159
177
|
this.list = doc.createElement("ul");
|
|
@@ -232,6 +250,7 @@ var Surface = class _Surface {
|
|
|
232
250
|
build() {
|
|
233
251
|
const doc = this.doc;
|
|
234
252
|
this.list.replaceChildren();
|
|
253
|
+
const markable = this.checkmarks && this.items.some((i) => !(i.submenu && i.submenu.length > 0) && !i.toggle && i.checked !== void 0);
|
|
235
254
|
for (const item of this.items) {
|
|
236
255
|
if (item.separatorBefore) {
|
|
237
256
|
const sep = doc.createElement("li");
|
|
@@ -245,7 +264,16 @@ var Surface = class _Surface {
|
|
|
245
264
|
li.dataset.veiId = item.id;
|
|
246
265
|
if (item.toggle) {
|
|
247
266
|
li.dataset.toggle = "1";
|
|
248
|
-
}
|
|
267
|
+
}
|
|
268
|
+
if (markable) {
|
|
269
|
+
const mark = doc.createElement("span");
|
|
270
|
+
mark.className = "vela-menu-mark";
|
|
271
|
+
if (!branch && !item.toggle && item.checked) {
|
|
272
|
+
mark.appendChild(iconEl("check", doc));
|
|
273
|
+
li.dataset.checkmark = "1";
|
|
274
|
+
}
|
|
275
|
+
li.appendChild(mark);
|
|
276
|
+
} else if (!branch && !item.toggle && item.checked) {
|
|
249
277
|
li.dataset.checked = "1";
|
|
250
278
|
}
|
|
251
279
|
if (item.icon) li.appendChild(iconEl(item.icon, doc));
|
|
@@ -294,6 +322,7 @@ var Surface = class _Surface {
|
|
|
294
322
|
placement: "right-start",
|
|
295
323
|
onSelect: this.onSelect,
|
|
296
324
|
onFavorite: this.onFavorite,
|
|
325
|
+
checkmarks: this.checkmarks,
|
|
297
326
|
id: `${this.mid}--${item.id}`
|
|
298
327
|
});
|
|
299
328
|
sub.setItems(item.submenu ?? []);
|
|
@@ -318,7 +347,8 @@ var Menu = class {
|
|
|
318
347
|
triggerId: opts.triggerId,
|
|
319
348
|
id: opts.id,
|
|
320
349
|
minWidth: opts.minWidth,
|
|
321
|
-
onFavorite: opts.onFavorite
|
|
350
|
+
onFavorite: opts.onFavorite,
|
|
351
|
+
checkmarks: opts.checkmarks
|
|
322
352
|
});
|
|
323
353
|
this.root.setItems(opts.items);
|
|
324
354
|
}
|
|
@@ -435,8 +465,13 @@ var STATIC_CSS = `
|
|
|
435
465
|
${STATIC_DECLS}
|
|
436
466
|
font-family: var(--vela-font, -apple-system, system-ui, sans-serif);
|
|
437
467
|
box-sizing: border-box;
|
|
468
|
+
/* Chrome text (titles, buttons, menus, readouts) is UI, not copy \u2014 never selectable. */
|
|
469
|
+
user-select: none;
|
|
470
|
+
-webkit-user-select: none;
|
|
438
471
|
}
|
|
439
472
|
.vela-ui *, .vela-ui-layer * { box-sizing: border-box; }
|
|
473
|
+
/* Text ENTRY is the one exception: selection is part of editing. */
|
|
474
|
+
.vela-ui :is(input, textarea), .vela-ui-layer :is(input, textarea) { user-select: text; -webkit-user-select: text; }
|
|
440
475
|
.vela-icon { display: inline-flex; align-items: center; flex: none; }
|
|
441
476
|
.vela-icon svg { display: block; }
|
|
442
477
|
`;
|
|
@@ -1438,6 +1473,9 @@ var NUMBER_CSS = `
|
|
|
1438
1473
|
transition: border-color 0.12s ease, box-shadow 0.12s ease;
|
|
1439
1474
|
-moz-appearance: textfield;
|
|
1440
1475
|
appearance: textfield;
|
|
1476
|
+
/* Selectable even under a user-select:none host (chart wrapper, .vela-ui). */
|
|
1477
|
+
user-select: text;
|
|
1478
|
+
-webkit-user-select: text;
|
|
1441
1479
|
}
|
|
1442
1480
|
.vela-num input::-webkit-inner-spin-button, .vela-num input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
|
|
1443
1481
|
.vela-num input:hover { border-color: var(--vela-fg-muted); }
|
|
@@ -1650,6 +1688,9 @@ var TEXT_CSS = `
|
|
|
1650
1688
|
overflow: hidden;
|
|
1651
1689
|
text-overflow: ellipsis;
|
|
1652
1690
|
transition: border-color 0.12s ease, box-shadow 0.12s ease;
|
|
1691
|
+
/* Selectable even under a user-select:none host (chart wrapper, .vela-ui). */
|
|
1692
|
+
user-select: text;
|
|
1693
|
+
-webkit-user-select: text;
|
|
1653
1694
|
}
|
|
1654
1695
|
.vela-text-field:hover { border-color: var(--vela-fg-muted); }
|
|
1655
1696
|
.vela-text-field:focus { border-color: var(--vela-focus); box-shadow: 0 0 0 3px var(--vela-focus-soft); }
|
|
@@ -1743,6 +1784,9 @@ var TEXTAREA_CSS = `
|
|
|
1743
1784
|
resize: vertical;
|
|
1744
1785
|
outline: none;
|
|
1745
1786
|
transition: border-color 0.12s ease, box-shadow 0.12s ease;
|
|
1787
|
+
/* Selectable even under a user-select:none host (chart wrapper, .vela-ui). */
|
|
1788
|
+
user-select: text;
|
|
1789
|
+
-webkit-user-select: text;
|
|
1746
1790
|
}
|
|
1747
1791
|
.vela-textarea-field:hover { border-color: var(--vela-fg-muted); }
|
|
1748
1792
|
.vela-textarea-field:focus { border-color: var(--vela-focus); box-shadow: 0 0 0 3px var(--vela-focus-soft); }
|
|
@@ -2296,6 +2340,8 @@ var FIELD_CSS = `
|
|
|
2296
2340
|
font-size: 14px;
|
|
2297
2341
|
}
|
|
2298
2342
|
.vela-field-label[data-size='sm'] { font-size: inherit; opacity: 0.85; }
|
|
2343
|
+
/* Titles are fully inert: spans, not label[for] \u2014 native labels propagate :hover and
|
|
2344
|
+
clicks onto their control, and both belong to the input alone. */
|
|
2299
2345
|
.vela-field-cell { display: flex; align-items: center; gap: 8px; justify-self: start; }
|
|
2300
2346
|
.vela-field-bool { display: flex; align-items: center; gap: 8px; min-height: 22px; }
|
|
2301
2347
|
.vela-field-stacked { display: flex; flex-direction: column; gap: 8px; }
|
|
@@ -2354,11 +2400,17 @@ function fieldSeparator() {
|
|
|
2354
2400
|
return el;
|
|
2355
2401
|
}
|
|
2356
2402
|
function labelEl(text, opts) {
|
|
2357
|
-
const el =
|
|
2358
|
-
if (opts.id && el instanceof HTMLLabelElement) el.htmlFor = opts.id;
|
|
2403
|
+
const el = document.createElement("span");
|
|
2359
2404
|
el.className = "vela-field-label";
|
|
2360
2405
|
if (opts.size) el.dataset.size = opts.size;
|
|
2361
2406
|
el.textContent = text;
|
|
2407
|
+
const id = opts.id;
|
|
2408
|
+
if (id) {
|
|
2409
|
+
el.id = `${id}--title`;
|
|
2410
|
+
queueMicrotask(() => {
|
|
2411
|
+
el.ownerDocument.getElementById(id)?.setAttribute("aria-labelledby", el.id);
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2362
2414
|
return el;
|
|
2363
2415
|
}
|
|
2364
2416
|
function asList(control) {
|
|
@@ -2387,9 +2439,7 @@ function fieldRow(opts) {
|
|
|
2387
2439
|
it.className = "vela-field-inline-item";
|
|
2388
2440
|
if (item.toggleFirst) it.style.flexDirection = "row-reverse";
|
|
2389
2441
|
if (item.label) {
|
|
2390
|
-
|
|
2391
|
-
if (item.toggleFirst) lbl.style.cursor = "pointer";
|
|
2392
|
-
it.appendChild(lbl);
|
|
2442
|
+
it.appendChild(labelEl(item.label, { id: item.id, size }));
|
|
2393
2443
|
}
|
|
2394
2444
|
if (item.fit) it.appendChild(item.control);
|
|
2395
2445
|
else {
|
|
@@ -2414,7 +2464,7 @@ function fieldRow(opts) {
|
|
|
2414
2464
|
tone: "bright",
|
|
2415
2465
|
onChange: (v) => opts.toggle?.onChange(v)
|
|
2416
2466
|
});
|
|
2417
|
-
wrap2.append(sw.el, labelEl(opts.label, { size }));
|
|
2467
|
+
wrap2.append(sw.el, labelEl(opts.label, { id: opts.toggle?.id ?? opts.id, size }));
|
|
2418
2468
|
if (opts.info) wrap2.appendChild(opts.info);
|
|
2419
2469
|
if (opts.toggle?.get) {
|
|
2420
2470
|
const get = opts.toggle.get;
|
|
@@ -2453,7 +2503,7 @@ function fieldRow(opts) {
|
|
|
2453
2503
|
if (controls.length > 0) dimControls(controls, v);
|
|
2454
2504
|
}
|
|
2455
2505
|
});
|
|
2456
|
-
left.append(sw.el, labelEl(opts.label, { size }));
|
|
2506
|
+
left.append(sw.el, labelEl(opts.label, { id: opts.toggle.id ?? opts.id, size }));
|
|
2457
2507
|
wrap.appendChild(left);
|
|
2458
2508
|
if (controls.length > 0) dimControls(controls, opts.toggle.checked);
|
|
2459
2509
|
if (opts.toggle.get) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as Millis,
|
|
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 { t as Millis, ae as InputSchema, ac as IndicatorMeta, P as PriceStyle, O as OHLCV, m as InputValue, k as IndicatorModel, j as MoveTarget, aB as SeriesSpec, aa as Fill, B as Background, at as PriceLine, a0 as DrawingLine, Y as DrawingBox, $ as DrawingLabel, a4 as DrawingPolyline, a1 as DrawingLinefill, a6 as DrawingTable, g as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, v as DrawingTypeKey, u as SnapMode, a2 as DrawingMode, I as IChartRenderer, R as RendererCapabilities, o as LegendActionView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, r as DataWindowReadout, n as SymbolPickerFn, aO as PaneInfo, a9 as DrawingsOption, D as Drawing, b as VelaOptions, x as AddIndicatorOptions, ap as MarketSwitch, ao as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-YdiaaVjt.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-DrN7ZIou.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as Millis,
|
|
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 { t as Millis, ae as InputSchema, ac as IndicatorMeta, P as PriceStyle, O as OHLCV, m as InputValue, k as IndicatorModel, j as MoveTarget, aB as SeriesSpec, aa as Fill, B as Background, at as PriceLine, a0 as DrawingLine, Y as DrawingBox, $ as DrawingLabel, a4 as DrawingPolyline, a1 as DrawingLinefill, a6 as DrawingTable, g as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, v as DrawingTypeKey, u as SnapMode, a2 as DrawingMode, I as IChartRenderer, R as RendererCapabilities, o as LegendActionView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, r as DataWindowReadout, n as SymbolPickerFn, aO as PaneInfo, a9 as DrawingsOption, D as Drawing, b as VelaOptions, x as AddIndicatorOptions, ap as MarketSwitch, ao as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-YdiaaVjt.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-BmHkcwvJ.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A strategy's broker state at ONE bar — the flat summary a host reads while a script
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { V as VisibleRangePreset } from './options-
|
|
2
|
-
import { D as DataProvider } from './DataProvider-
|
|
3
|
-
import { S as ScriptingEngine, V as Vela } from './contributions-
|
|
1
|
+
import { V as VisibleRangePreset } from './options-YdiaaVjt.cjs';
|
|
2
|
+
import { D as DataProvider } from './DataProvider-DrN7ZIou.cjs';
|
|
3
|
+
import { S as ScriptingEngine, V as Vela } from './contributions-2bEmCF9S.cjs';
|
|
4
4
|
|
|
5
5
|
interface RangePreset {
|
|
6
6
|
/** Button label. */
|
|
@@ -49,9 +49,9 @@ declare class Bottombar {
|
|
|
49
49
|
setActiveRange(id: string | null): void;
|
|
50
50
|
/**
|
|
51
51
|
* Reflect the ACTIVE chart's session posture. `enabled: false` (a continuous
|
|
52
|
-
* market, or metadata not landed yet)
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* market, or metadata not landed yet) HIDES the toggle entirely — RTH/ETH is
|
|
53
|
+
* meaningless there. Enabled, the chips appear and the active one tracks the
|
|
54
|
+
* chart's current session.
|
|
55
55
|
*/
|
|
56
56
|
setSession(state: {
|
|
57
57
|
session: 'regular' | 'extended';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { V as VisibleRangePreset } from './options-
|
|
2
|
-
import { D as DataProvider } from './DataProvider-
|
|
3
|
-
import { S as ScriptingEngine, V as Vela } from './contributions-
|
|
1
|
+
import { V as VisibleRangePreset } from './options-YdiaaVjt.js';
|
|
2
|
+
import { D as DataProvider } from './DataProvider-BmHkcwvJ.js';
|
|
3
|
+
import { S as ScriptingEngine, V as Vela } from './contributions-DatoAzMx.js';
|
|
4
4
|
|
|
5
5
|
interface RangePreset {
|
|
6
6
|
/** Button label. */
|
|
@@ -49,9 +49,9 @@ declare class Bottombar {
|
|
|
49
49
|
setActiveRange(id: string | null): void;
|
|
50
50
|
/**
|
|
51
51
|
* Reflect the ACTIVE chart's session posture. `enabled: false` (a continuous
|
|
52
|
-
* market, or metadata not landed yet)
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* market, or metadata not landed yet) HIDES the toggle entirely — RTH/ETH is
|
|
53
|
+
* meaningless there. Enabled, the chips appear and the active one tracks the
|
|
54
|
+
* chart's current session.
|
|
55
55
|
*/
|
|
56
56
|
setSession(state: {
|
|
57
57
|
session: 'regular' | 'extended';
|