@luxalgo/vela 0.8.1 → 0.8.3
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/README.md +1 -1
- package/dist/{DataProvider-DwFIoV4r.d.ts → DataProvider-oH78tYXL.d.ts} +1 -1
- package/dist/{DataProvider-BrlxntPN.d.cts → DataProvider-wbtJ3-Sa.d.cts} +1 -1
- package/dist/{chunk-DBDXKZUF.js → chunk-2IPXYM4B.js} +306 -177
- package/dist/{chunk-NELQJCGK.js → chunk-G7B7ZCBF.js} +167 -10
- package/dist/{chunk-ATGTCWHJ.js → chunk-HMHA733L.js} +473 -196
- package/dist/{chunk-EZ5FWVLA.js → chunk-KWI3YDBW.js} +343 -17
- package/dist/{chunk-LMBYEGUR.js → chunk-TO3GIK7Z.js} +71 -6
- package/dist/{chunk-BZQM2XO7.js → chunk-VHGACEHO.js} +62 -1
- package/dist/{contributions-tjNExo1o.d.ts → contributions-BhOBRenr.d.cts} +79 -12
- package/dist/{contributions-CtlptxR8.d.cts → contributions-HGqnNb_P.d.ts} +79 -12
- package/dist/index.cjs +733 -113
- package/dist/index.d.cts +34 -14
- package/dist/index.d.ts +34 -14
- package/dist/index.js +5 -5
- package/dist/{options-BnEPUuVV.d.ts → options-lMUwmRwh.d.cts} +69 -4
- package/dist/{options-BnEPUuVV.d.cts → options-lMUwmRwh.d.ts} +69 -4
- package/dist/{plugin-e2WUEtiI.d.ts → plugin-Cr2Pj8q8.d.ts} +4 -4
- package/dist/{plugin-BWxJRKzS.d.cts → plugin-Do5J5xuF.d.cts} +4 -4
- package/dist/plugin.cjs +38 -6
- package/dist/plugin.d.cts +5 -5
- package/dist/plugin.d.ts +5 -5
- package/dist/plugin.js +3 -3
- 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/{side-panel-HF0IAzwf.d.cts → side-panel-_2UK1gSm.d.cts} +58 -3
- package/dist/{side-panel-HF0IAzwf.d.ts → side-panel-_2UK1gSm.d.ts} +58 -3
- package/dist/{statusline-model-DFY7tuHj.d.cts → statusline-model-B-2xGlB_.d.cts} +3 -3
- package/dist/{statusline-model-zKXtGIjj.d.ts → statusline-model-CY1wzxHg.d.ts} +3 -3
- package/dist/ui.cjs +298 -13
- package/dist/ui.d.cts +132 -74
- package/dist/ui.d.ts +132 -74
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +734 -114
- package/dist/vela.global.min.js +86 -52
- package/dist/widget.cjs +1227 -211
- package/dist/widget.d.cts +36 -12
- package/dist/widget.d.ts +36 -12
- package/dist/widget.js +7 -7
- package/dist/workspace.cjs +1226 -211
- package/dist/workspace.d.cts +47 -20
- package/dist/workspace.d.ts +47 -20
- package/dist/workspace.js +6 -6
- package/package.json +2 -2
- /package/dist/{chunk-JU4CWEBF.js → chunk-W5YPYZ2P.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-
|
|
1
|
+
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl, announceSurface, holdForExit } from './chunk-VHGACEHO.js';
|
|
2
2
|
|
|
3
3
|
// src/core/model/series.ts
|
|
4
4
|
function isLineLikeSeries(spec) {
|
|
@@ -2778,6 +2778,10 @@ var FibRatios = class extends Drawing {
|
|
|
2778
2778
|
|
|
2779
2779
|
// src/core/drawings/types/FibLevels.ts
|
|
2780
2780
|
var FibLevels = class extends FibRatios {
|
|
2781
|
+
/** Price of a level for the two anchor prices; subclasses override to change which anchor ratio 0 sits on. */
|
|
2782
|
+
levelPrice(ratio, p1, p2) {
|
|
2783
|
+
return p1 + ratio * (p2 - p1);
|
|
2784
|
+
}
|
|
2781
2785
|
/** Per-level pixel line + price for the ENABLED levels, spanning the anchors' time range. */
|
|
2782
2786
|
levelLines(proj) {
|
|
2783
2787
|
const a = this.anchors[0];
|
|
@@ -2787,11 +2791,10 @@ var FibLevels = class extends FibRatios {
|
|
|
2787
2791
|
const xb = proj.xOf(b.time);
|
|
2788
2792
|
const x1 = Math.min(xa, xb);
|
|
2789
2793
|
const x2 = Math.max(xa, xb);
|
|
2790
|
-
const delta = b.price - a.price;
|
|
2791
2794
|
const out = [];
|
|
2792
2795
|
for (const lv of this.levels) {
|
|
2793
2796
|
if (!lv.enabled) continue;
|
|
2794
|
-
const price =
|
|
2797
|
+
const price = this.levelPrice(lv.ratio, a.price, b.price);
|
|
2795
2798
|
const y = proj.yOf(price, this.paneId);
|
|
2796
2799
|
if (y == null) continue;
|
|
2797
2800
|
out.push({ ratio: lv.ratio, color: lv.color, label: lv.label, price, x1, x2, y });
|
|
@@ -2831,8 +2834,7 @@ var FibLevels = class extends FibRatios {
|
|
|
2831
2834
|
const a = this.anchors[0];
|
|
2832
2835
|
const b = this.anchors[1];
|
|
2833
2836
|
if (!a || !b) return null;
|
|
2834
|
-
const
|
|
2835
|
-
const prices = this.levels.filter((l) => l.enabled).map((l) => a.price + l.ratio * delta);
|
|
2837
|
+
const prices = this.levels.filter((l) => l.enabled).map((l) => this.levelPrice(l.ratio, a.price, b.price));
|
|
2836
2838
|
if (prices.length === 0) return null;
|
|
2837
2839
|
return { min: Math.min(...prices), max: Math.max(...prices) };
|
|
2838
2840
|
}
|
|
@@ -2918,13 +2920,24 @@ function cycleLevels(count, enabledCount = count) {
|
|
|
2918
2920
|
// src/core/drawings/types/FibRetracement.ts
|
|
2919
2921
|
var LEVELS = fibLevels([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]);
|
|
2920
2922
|
var FibRetracement = class extends FibLevels {
|
|
2921
|
-
constructor() {
|
|
2922
|
-
super(
|
|
2923
|
+
constructor(init) {
|
|
2924
|
+
super(init);
|
|
2923
2925
|
this.type = "fibretracement";
|
|
2926
|
+
if (this.reverse === void 0) this.reverse = false;
|
|
2924
2927
|
}
|
|
2925
2928
|
defaultLevels() {
|
|
2926
2929
|
return LEVELS;
|
|
2927
2930
|
}
|
|
2931
|
+
levelPrice(ratio, p1, p2) {
|
|
2932
|
+
return this.reverse ? p1 + ratio * (p2 - p1) : p2 + ratio * (p1 - p2);
|
|
2933
|
+
}
|
|
2934
|
+
writeProps() {
|
|
2935
|
+
return { ...super.writeProps(), reverse: this.reverse };
|
|
2936
|
+
}
|
|
2937
|
+
readProps(props) {
|
|
2938
|
+
super.readProps(props);
|
|
2939
|
+
this.reverse = typeof props.reverse === "boolean" ? props.reverse : true;
|
|
2940
|
+
}
|
|
2928
2941
|
};
|
|
2929
2942
|
|
|
2930
2943
|
// src/core/drawings/types/FibExtension.ts
|
|
@@ -5892,6 +5905,100 @@ function inputDeltas(schema, values) {
|
|
|
5892
5905
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
5893
5906
|
}
|
|
5894
5907
|
|
|
5908
|
+
// src/core/timezones.ts
|
|
5909
|
+
var TIMEZONES = [
|
|
5910
|
+
{ value: "Etc/UTC", label: "UTC" },
|
|
5911
|
+
{ value: "Etc/GMT+12", label: "International Date Line West" },
|
|
5912
|
+
{ value: "Pacific/Pago_Pago", label: "Pago Pago" },
|
|
5913
|
+
{ value: "Pacific/Honolulu", label: "Honolulu" },
|
|
5914
|
+
{ value: "Pacific/Marquesas", label: "Marquesas Islands" },
|
|
5915
|
+
{ value: "America/Anchorage", label: "Anchorage" },
|
|
5916
|
+
{ value: "America/Los_Angeles", label: "Los Angeles" },
|
|
5917
|
+
{ value: "America/Phoenix", label: "Phoenix" },
|
|
5918
|
+
{ value: "America/Denver", label: "Denver" },
|
|
5919
|
+
{ value: "America/Chicago", label: "Chicago" },
|
|
5920
|
+
{ value: "America/Mexico_City", label: "Mexico City" },
|
|
5921
|
+
{ value: "America/New_York", label: "New York" },
|
|
5922
|
+
{ value: "America/Bogota", label: "Bogot\xE1" },
|
|
5923
|
+
{ value: "America/Caracas", label: "Caracas" },
|
|
5924
|
+
{ value: "America/Santiago", label: "Santiago" },
|
|
5925
|
+
{ value: "America/St_Johns", label: "St. John's" },
|
|
5926
|
+
{ value: "America/Sao_Paulo", label: "S\xE3o Paulo" },
|
|
5927
|
+
{ value: "America/Argentina/Buenos_Aires", label: "Buenos Aires" },
|
|
5928
|
+
{ value: "America/Noronha", label: "Fernando de Noronha" },
|
|
5929
|
+
{ value: "Atlantic/Azores", label: "Azores" },
|
|
5930
|
+
{ value: "Atlantic/Reykjavik", label: "Reykjavik" },
|
|
5931
|
+
{ value: "Europe/London", label: "London" },
|
|
5932
|
+
{ value: "Europe/Paris", label: "Paris" },
|
|
5933
|
+
{ value: "Europe/Berlin", label: "Berlin" },
|
|
5934
|
+
{ value: "Europe/Athens", label: "Athens" },
|
|
5935
|
+
{ value: "Africa/Cairo", label: "Cairo" },
|
|
5936
|
+
{ value: "Africa/Johannesburg", label: "Johannesburg" },
|
|
5937
|
+
{ value: "Europe/Moscow", label: "Moscow" },
|
|
5938
|
+
{ value: "Europe/Istanbul", label: "Istanbul" },
|
|
5939
|
+
{ value: "Asia/Tehran", label: "Tehran" },
|
|
5940
|
+
{ value: "Asia/Dubai", label: "Dubai" },
|
|
5941
|
+
{ value: "Asia/Kabul", label: "Kabul" },
|
|
5942
|
+
{ value: "Asia/Karachi", label: "Karachi" },
|
|
5943
|
+
{ value: "Asia/Kolkata", label: "Mumbai" },
|
|
5944
|
+
{ value: "Asia/Kathmandu", label: "Kathmandu" },
|
|
5945
|
+
{ value: "Asia/Dhaka", label: "Dhaka" },
|
|
5946
|
+
{ value: "Asia/Yangon", label: "Yangon" },
|
|
5947
|
+
{ value: "Asia/Bangkok", label: "Bangkok" },
|
|
5948
|
+
{ value: "Asia/Shanghai", label: "Shanghai" },
|
|
5949
|
+
{ value: "Asia/Hong_Kong", label: "Hong Kong" },
|
|
5950
|
+
{ value: "Asia/Singapore", label: "Singapore" },
|
|
5951
|
+
{ value: "Australia/Eucla", label: "Eucla" },
|
|
5952
|
+
{ value: "Asia/Tokyo", label: "Tokyo" },
|
|
5953
|
+
{ value: "Asia/Seoul", label: "Seoul" },
|
|
5954
|
+
{ value: "Australia/Adelaide", label: "Adelaide" },
|
|
5955
|
+
{ value: "Australia/Sydney", label: "Sydney" },
|
|
5956
|
+
{ value: "Australia/Lord_Howe", label: "Lord Howe Island" },
|
|
5957
|
+
{ value: "Pacific/Noumea", label: "Noum\xE9a" },
|
|
5958
|
+
{ value: "Pacific/Auckland", label: "Auckland" },
|
|
5959
|
+
{ value: "Pacific/Chatham", label: "Chatham Islands" },
|
|
5960
|
+
{ value: "Pacific/Apia", label: "Apia" },
|
|
5961
|
+
{ value: "Pacific/Kiritimati", label: "Kiritimati" }
|
|
5962
|
+
];
|
|
5963
|
+
var EXCHANGE_TIMEZONE = "exchange";
|
|
5964
|
+
function isExchangeTimezone(zone) {
|
|
5965
|
+
return zone === EXCHANGE_TIMEZONE;
|
|
5966
|
+
}
|
|
5967
|
+
function resolveTimezone(zone, exchangeZone) {
|
|
5968
|
+
if (!isExchangeTimezone(zone)) return zone;
|
|
5969
|
+
return exchangeZone && exchangeZone !== "" ? exchangeZone : "Etc/UTC";
|
|
5970
|
+
}
|
|
5971
|
+
function normalizeTimezone(zone) {
|
|
5972
|
+
return zone === "UTC" || zone === "Etc/UTC" || zone === "Etc/GMT" ? "Etc/UTC" : zone;
|
|
5973
|
+
}
|
|
5974
|
+
function timezoneMenuRows(current) {
|
|
5975
|
+
const active = normalizeTimezone(current);
|
|
5976
|
+
const [utc, ...zones] = TIMEZONES.map((t) => ({ value: t.value, label: tzMenuLabel(t.value, t.label), checked: t.value === active }));
|
|
5977
|
+
return [utc, { value: EXCHANGE_TIMEZONE, label: "Exchange", checked: isExchangeTimezone(current) }, ...zones];
|
|
5978
|
+
}
|
|
5979
|
+
function tzOffset(zone, date = /* @__PURE__ */ new Date()) {
|
|
5980
|
+
try {
|
|
5981
|
+
const parts = new Intl.DateTimeFormat("en-US", { timeZone: zone, timeZoneName: "shortOffset" }).formatToParts(date);
|
|
5982
|
+
const raw = parts.find((p) => p.type === "timeZoneName")?.value ?? "";
|
|
5983
|
+
const m = raw.match(/GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?/);
|
|
5984
|
+
if (!m || !m[1]) return "UTC";
|
|
5985
|
+
const sign = m[1] === "-" ? "-" : "+";
|
|
5986
|
+
const hrs = m[2] ?? "0";
|
|
5987
|
+
const mins = m[3] ?? "";
|
|
5988
|
+
return mins ? `UTC${sign}${hrs}:${mins}` : `UTC${sign}${hrs}`;
|
|
5989
|
+
} catch {
|
|
5990
|
+
return "UTC";
|
|
5991
|
+
}
|
|
5992
|
+
}
|
|
5993
|
+
function tzMenuLabel(zone, location) {
|
|
5994
|
+
if (normalizeTimezone(zone) === "Etc/UTC") return location;
|
|
5995
|
+
return `(${tzOffset(zone)}) ${location}`;
|
|
5996
|
+
}
|
|
5997
|
+
function tzButtonLabel(zone) {
|
|
5998
|
+
if (normalizeTimezone(zone) === "Etc/UTC") return "UTC";
|
|
5999
|
+
return tzOffset(zone);
|
|
6000
|
+
}
|
|
6001
|
+
|
|
5895
6002
|
// src/renderers/native/layers.ts
|
|
5896
6003
|
function foldBaseModulation(acc, next) {
|
|
5897
6004
|
if (next == null) return acc;
|
|
@@ -6023,10 +6130,12 @@ function legendActions() {
|
|
|
6023
6130
|
}
|
|
6024
6131
|
function legendActionsProviderFor(chart, context) {
|
|
6025
6132
|
return (indicatorId) => {
|
|
6026
|
-
const
|
|
6133
|
+
const find = () => chart.indicators().find((h) => h.id === indicatorId);
|
|
6134
|
+
const infoOf = (h) => ({ id: h.id, title: h.title, ...h.source !== void 0 ? { source: h.source } : {} });
|
|
6135
|
+
const handle = find();
|
|
6027
6136
|
if (!handle) return [];
|
|
6028
|
-
const info =
|
|
6029
|
-
return legendActions().filter((d) => !d.when || d.when(info)).map((d) => ({ id: d.id, icon: d.icon, tooltip: d.tooltip, run: () => d.run(context(),
|
|
6137
|
+
const info = infoOf(handle);
|
|
6138
|
+
return legendActions().filter((d) => !d.when || d.when(info)).map((d) => ({ id: d.id, icon: d.icon, tooltip: d.tooltip, run: () => d.run(context(), infoOf(find() ?? handle)) }));
|
|
6030
6139
|
};
|
|
6031
6140
|
}
|
|
6032
6141
|
var calloutRegistry = /* @__PURE__ */ new Map();
|
|
@@ -6113,6 +6222,127 @@ function resolveEngines(overrides) {
|
|
|
6113
6222
|
return { ...Object.fromEntries(defaultEngines), ...overrides };
|
|
6114
6223
|
}
|
|
6115
6224
|
|
|
6225
|
+
// src/widget/context-menu-model.ts
|
|
6226
|
+
var SETTINGS_SECTION = {
|
|
6227
|
+
body: "Canvas",
|
|
6228
|
+
"price-axis": "Scales and lines",
|
|
6229
|
+
"time-axis": "Scales and lines"
|
|
6230
|
+
};
|
|
6231
|
+
function settingsItem(zone, label, icon) {
|
|
6232
|
+
return { id: `settings:${SETTINGS_SECTION[zone]}`, label, ...icon ? { icon } : {}, separatorBefore: true };
|
|
6233
|
+
}
|
|
6234
|
+
function settingsSectionOf(id) {
|
|
6235
|
+
return id.slice("settings:".length) || void 0;
|
|
6236
|
+
}
|
|
6237
|
+
var SCALE_CHOICES = [
|
|
6238
|
+
["regular", "Regular"],
|
|
6239
|
+
["percent", "Percent"],
|
|
6240
|
+
["indexed", "Indexed to 100"],
|
|
6241
|
+
["log", "Logarithmic"]
|
|
6242
|
+
];
|
|
6243
|
+
function paneScaleAt(panes, y) {
|
|
6244
|
+
return panes.find((p) => y >= p.top && y < p.top + p.height) ?? panes[0] ?? null;
|
|
6245
|
+
}
|
|
6246
|
+
function scaleChoiceOf(scale) {
|
|
6247
|
+
if (scale.log) return "log";
|
|
6248
|
+
if (scale.mode === "percent") return "percent";
|
|
6249
|
+
if (scale.mode === "indexed") return "indexed";
|
|
6250
|
+
return "regular";
|
|
6251
|
+
}
|
|
6252
|
+
function mainScale(pane) {
|
|
6253
|
+
return pane === null || pane.kind === "price";
|
|
6254
|
+
}
|
|
6255
|
+
function scaleWrites(choice, pane) {
|
|
6256
|
+
const mode = choice === "percent" ? "percent" : choice === "indexed" ? "indexed" : "price";
|
|
6257
|
+
const log = choice === "log";
|
|
6258
|
+
if (mainScale(pane)) {
|
|
6259
|
+
return [
|
|
6260
|
+
["scaleMode", mode],
|
|
6261
|
+
["logScale", log]
|
|
6262
|
+
];
|
|
6263
|
+
}
|
|
6264
|
+
return [
|
|
6265
|
+
["scaleMode", { pane: pane.id, mode }],
|
|
6266
|
+
["logScale", { pane: pane.id, value: log }]
|
|
6267
|
+
];
|
|
6268
|
+
}
|
|
6269
|
+
function invertWrite(next, pane) {
|
|
6270
|
+
return mainScale(pane) ? ["invertScale", next] : ["invertScale", { pane: pane.id, value: next }];
|
|
6271
|
+
}
|
|
6272
|
+
function priceAxisItems(s) {
|
|
6273
|
+
return [
|
|
6274
|
+
{ id: "auto", label: "Auto (fits data to screen)", checked: s.auto },
|
|
6275
|
+
{ id: "invert", label: "Invert scale", checked: s.invert },
|
|
6276
|
+
...SCALE_CHOICES.map(([choice, label], i) => ({
|
|
6277
|
+
id: `scale:${choice}`,
|
|
6278
|
+
label,
|
|
6279
|
+
checked: s.choice === choice,
|
|
6280
|
+
separatorBefore: i === 0
|
|
6281
|
+
})),
|
|
6282
|
+
{
|
|
6283
|
+
id: "labels",
|
|
6284
|
+
label: "Labels",
|
|
6285
|
+
separatorBefore: true,
|
|
6286
|
+
submenu: [
|
|
6287
|
+
{ id: "toggle:axisLabels", label: "Price axis labels", checked: s.axisLabels },
|
|
6288
|
+
{ id: "toggle:priceLabel", label: "Last price label", checked: s.priceLabel },
|
|
6289
|
+
{ id: "toggle:countdown", label: "Countdown to bar close", checked: s.countdown }
|
|
6290
|
+
]
|
|
6291
|
+
},
|
|
6292
|
+
{
|
|
6293
|
+
id: "levels",
|
|
6294
|
+
label: "Levels",
|
|
6295
|
+
submenu: [{ id: "toggle:currentPriceLine", label: "Last Price Line", checked: s.priceLine }]
|
|
6296
|
+
},
|
|
6297
|
+
settingsItem("price-axis", "More settings\u2026")
|
|
6298
|
+
];
|
|
6299
|
+
}
|
|
6300
|
+
function timeAxisItems(timezone) {
|
|
6301
|
+
return [
|
|
6302
|
+
{
|
|
6303
|
+
id: "timezone",
|
|
6304
|
+
label: "Time zone",
|
|
6305
|
+
submenu: timezoneMenuRows(timezone).map((r) => ({ id: `tz:${r.value}`, label: r.label, checked: r.checked }))
|
|
6306
|
+
},
|
|
6307
|
+
settingsItem("time-axis", "More settings\u2026")
|
|
6308
|
+
];
|
|
6309
|
+
}
|
|
6310
|
+
function bodyItems(counts) {
|
|
6311
|
+
return [
|
|
6312
|
+
{ id: "reset-view", label: "Reset chart view", icon: "reset" },
|
|
6313
|
+
{ id: "remove-drawings", label: "Remove drawings", icon: "eraser", disabled: counts.drawings === 0, separatorBefore: true },
|
|
6314
|
+
{ id: "remove-indicators", label: "Remove indicators", icon: "indicators", disabled: counts.indicators === 0 },
|
|
6315
|
+
settingsItem("body", "Settings\u2026", "gear")
|
|
6316
|
+
];
|
|
6317
|
+
}
|
|
6318
|
+
var CONTEXT_MENU_BUILTIN_ORDER = {
|
|
6319
|
+
body: { "reset-view": -30, "remove-drawings": -20, "remove-indicators": -10, settings: 1e3 },
|
|
6320
|
+
"price-axis": {
|
|
6321
|
+
auto: -80,
|
|
6322
|
+
invert: -70,
|
|
6323
|
+
"scale:regular": -60,
|
|
6324
|
+
"scale:percent": -50,
|
|
6325
|
+
"scale:indexed": -40,
|
|
6326
|
+
"scale:log": -30,
|
|
6327
|
+
labels: -20,
|
|
6328
|
+
levels: -10,
|
|
6329
|
+
settings: 1e3
|
|
6330
|
+
},
|
|
6331
|
+
"time-axis": { timezone: -10, settings: 1e3 }
|
|
6332
|
+
};
|
|
6333
|
+
function composeMenu(zone, builtin, contributed) {
|
|
6334
|
+
const ranks = CONTEXT_MENU_BUILTIN_ORDER[zone];
|
|
6335
|
+
const rows = [];
|
|
6336
|
+
let group = 0;
|
|
6337
|
+
for (const item of builtin) {
|
|
6338
|
+
if (item.separatorBefore) group += 1;
|
|
6339
|
+
rows.push({ item, rank: ranks[item.id.startsWith("settings") ? "settings" : item.id] ?? 0, group });
|
|
6340
|
+
}
|
|
6341
|
+
for (const { item, order } of contributed) rows.push({ item, rank: order ?? 0, group: -1 });
|
|
6342
|
+
rows.sort((a, b) => a.rank - b.rank);
|
|
6343
|
+
return rows.map(({ item, group: g }, i) => ({ ...item, separatorBefore: i > 0 && rows[i - 1].group !== g }));
|
|
6344
|
+
}
|
|
6345
|
+
|
|
6116
6346
|
// src/widget/side-panel.ts
|
|
6117
6347
|
var STYLE_ID = "vela-widget-sidepanel";
|
|
6118
6348
|
var DEFAULT_PANEL_WIDTH = 280;
|
|
@@ -6177,6 +6407,32 @@ var CSS = `
|
|
|
6177
6407
|
.vela-panel-pin .vela-icon { width: 15px; height: 15px; }
|
|
6178
6408
|
.vela-panel-pin:hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
|
|
6179
6409
|
.vela-panel-pin[data-on='1'] { color: var(--vela-fg-bright); }
|
|
6410
|
+
.vela-panel-max {
|
|
6411
|
+
all: unset;
|
|
6412
|
+
cursor: pointer;
|
|
6413
|
+
width: 26px;
|
|
6414
|
+
height: 26px;
|
|
6415
|
+
flex: none;
|
|
6416
|
+
display: inline-flex;
|
|
6417
|
+
align-items: center;
|
|
6418
|
+
justify-content: center;
|
|
6419
|
+
border-radius: 4px;
|
|
6420
|
+
color: var(--vela-fg-muted);
|
|
6421
|
+
}
|
|
6422
|
+
.vela-panel-max .vela-icon { width: 15px; height: 15px; }
|
|
6423
|
+
.vela-panel-max:hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
|
|
6424
|
+
/* MAXIMIZED: the panel covers the whole dock host \u2014 every chart of the shell \u2014 whatever
|
|
6425
|
+
its placement; the width handle and the pin have nothing to do meanwhile. */
|
|
6426
|
+
.vela-panel[data-maximized] {
|
|
6427
|
+
position: absolute;
|
|
6428
|
+
inset: 0;
|
|
6429
|
+
width: auto;
|
|
6430
|
+
max-width: none;
|
|
6431
|
+
z-index: 26;
|
|
6432
|
+
border-left: none;
|
|
6433
|
+
}
|
|
6434
|
+
.vela-panel[data-maximized] .vela-panel-resizer,
|
|
6435
|
+
.vela-panel[data-maximized] .vela-panel-pin { display: none; }
|
|
6180
6436
|
.vela-panel-body { flex: 1; overflow: auto; padding: 8px; }
|
|
6181
6437
|
.vela-panel-body::-webkit-scrollbar { width: 8px; }
|
|
6182
6438
|
.vela-panel-body::-webkit-scrollbar-thumb { background: var(--vela-scroll); border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; }
|
|
@@ -6229,6 +6485,7 @@ var CSS = `
|
|
|
6229
6485
|
border-left: none;
|
|
6230
6486
|
}
|
|
6231
6487
|
[data-layout='mobile'] .vela-panel-resizer { display: none; }
|
|
6488
|
+
[data-layout='mobile'] .vela-panel-max { display: none; }
|
|
6232
6489
|
`;
|
|
6233
6490
|
function clampPanelWidth(px, min = DEFAULT_PANEL_MIN_WIDTH, max = DEFAULT_PANEL_MAX_WIDTH) {
|
|
6234
6491
|
const lo = Number.isFinite(min) && min > 0 ? min : DEFAULT_PANEL_MIN_WIDTH;
|
|
@@ -6252,6 +6509,15 @@ var SidePanel = class {
|
|
|
6252
6509
|
* never on a programmatic {@link setOverlay}, for the same reason as widths. */
|
|
6253
6510
|
this.onPlacementChange = null;
|
|
6254
6511
|
this.pin = null;
|
|
6512
|
+
this.maxButton = null;
|
|
6513
|
+
this.maximizedOn = false;
|
|
6514
|
+
/** Set while the close is announced, so a listener's own close does not re-enter. */
|
|
6515
|
+
this.closing = false;
|
|
6516
|
+
/** Open as far as the dock and the host are concerned — a closed panel can still be on
|
|
6517
|
+
* screen while its exit animation runs. */
|
|
6518
|
+
this.isOpen = false;
|
|
6519
|
+
/** The exit animation of a close; a reopen cancels it. */
|
|
6520
|
+
this.exit = null;
|
|
6255
6521
|
const doc = host.ownerDocument;
|
|
6256
6522
|
injectStyles(STYLE_ID, CSS, doc);
|
|
6257
6523
|
this.minWidth = opts.resizable ? opts.minWidth ?? DEFAULT_PANEL_MIN_WIDTH : 1;
|
|
@@ -6286,7 +6552,13 @@ var SidePanel = class {
|
|
|
6286
6552
|
});
|
|
6287
6553
|
this.refreshPin();
|
|
6288
6554
|
}
|
|
6289
|
-
|
|
6555
|
+
if (opts.maximizable) {
|
|
6556
|
+
this.maxButton = doc.createElement("button");
|
|
6557
|
+
this.maxButton.className = "vela-panel-max";
|
|
6558
|
+
this.maxButton.addEventListener("click", () => this.setMaximized(!this.maximizedOn));
|
|
6559
|
+
this.refreshMaxButton();
|
|
6560
|
+
}
|
|
6561
|
+
header.append(this.heading, this.slot, ...this.pin ? [this.pin] : [], ...this.maxButton ? [this.maxButton] : [], close);
|
|
6290
6562
|
this.body = doc.createElement("div");
|
|
6291
6563
|
this.body.className = "vela-panel-body";
|
|
6292
6564
|
this.el.append(header, this.body);
|
|
@@ -6294,13 +6566,65 @@ var SidePanel = class {
|
|
|
6294
6566
|
host.appendChild(this.el);
|
|
6295
6567
|
}
|
|
6296
6568
|
get open() {
|
|
6297
|
-
return
|
|
6569
|
+
return this.isOpen;
|
|
6298
6570
|
}
|
|
6299
|
-
/**
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6571
|
+
/**
|
|
6572
|
+
* Open/close the panel — a bare call flips it. The panel reports closed at once, but a
|
|
6573
|
+
* close keeps it on screen, marked `data-closing`, while a host exit animation runs.
|
|
6574
|
+
* `instant` skips that, and also cuts short the exit of a panel already closing: a panel
|
|
6575
|
+
* handing the dock to another leaves at once.
|
|
6576
|
+
*/
|
|
6577
|
+
toggle(open = !this.isOpen, instant = false) {
|
|
6578
|
+
if (open === this.isOpen) {
|
|
6579
|
+
if (!open && instant) this.exit?.finish();
|
|
6580
|
+
return;
|
|
6581
|
+
}
|
|
6582
|
+
if (!open && this.closing) return;
|
|
6583
|
+
if (!open) {
|
|
6584
|
+
this.closing = true;
|
|
6585
|
+
announceSurface(this.el, false, "panel");
|
|
6586
|
+
this.closing = false;
|
|
6587
|
+
}
|
|
6588
|
+
this.isOpen = open;
|
|
6589
|
+
if (open) {
|
|
6590
|
+
if (this.exit) {
|
|
6591
|
+
this.exit.cancel();
|
|
6592
|
+
this.exit = null;
|
|
6593
|
+
this.setMaximized(false);
|
|
6594
|
+
}
|
|
6595
|
+
this.el.hidden = false;
|
|
6596
|
+
} else {
|
|
6597
|
+
const hide = () => {
|
|
6598
|
+
this.exit = null;
|
|
6599
|
+
this.el.hidden = true;
|
|
6600
|
+
this.setMaximized(false);
|
|
6601
|
+
};
|
|
6602
|
+
if (instant) hide();
|
|
6603
|
+
else this.exit = holdForExit(this.el, hide);
|
|
6604
|
+
}
|
|
6303
6605
|
this.onOpenChange?.(open);
|
|
6606
|
+
if (open && this.isOpen) announceSurface(this.el, true, "panel");
|
|
6607
|
+
}
|
|
6608
|
+
/** Whether the panel covers every chart right now. */
|
|
6609
|
+
get maximized() {
|
|
6610
|
+
return this.maximizedOn;
|
|
6611
|
+
}
|
|
6612
|
+
/** Maximize the panel over the shell's charts, or restore it. A no-op on a panel not
|
|
6613
|
+
* declared `maximizable`. */
|
|
6614
|
+
setMaximized(maximized) {
|
|
6615
|
+
if (!this.maxButton || maximized === this.maximizedOn) return;
|
|
6616
|
+
this.maximizedOn = maximized;
|
|
6617
|
+
if (maximized) this.el.dataset.maximized = "1";
|
|
6618
|
+
else delete this.el.dataset.maximized;
|
|
6619
|
+
this.refreshMaxButton();
|
|
6620
|
+
}
|
|
6621
|
+
refreshMaxButton() {
|
|
6622
|
+
if (!this.maxButton) return;
|
|
6623
|
+
const doc = this.maxButton.ownerDocument;
|
|
6624
|
+
this.maxButton.replaceChildren(iconEl(this.maximizedOn ? "restore" : "maximize", doc));
|
|
6625
|
+
this.maxButton.title = this.maximizedOn ? "Restore" : "Maximize";
|
|
6626
|
+
this.maxButton.setAttribute("aria-label", this.maxButton.title);
|
|
6627
|
+
this.maxButton.setAttribute("aria-pressed", this.maximizedOn ? "true" : "false");
|
|
6304
6628
|
}
|
|
6305
6629
|
/** The scrolling body, for a panel filled from OUTSIDE the class — a contributed panel's
|
|
6306
6630
|
* `mount` receives exactly this element. Subclasses use the protected `body`. */
|
|
@@ -6352,6 +6676,8 @@ var SidePanel = class {
|
|
|
6352
6676
|
this.pin.setAttribute("aria-pressed", pinned ? "true" : "false");
|
|
6353
6677
|
}
|
|
6354
6678
|
destroy() {
|
|
6679
|
+
if (this.open) announceSurface(this.el, false, "panel");
|
|
6680
|
+
this.exit?.finish();
|
|
6355
6681
|
this.el.remove();
|
|
6356
6682
|
}
|
|
6357
6683
|
/** The drag handle on the panel's inner (left) edge — the panel is docked right, so dragging
|
|
@@ -6396,4 +6722,4 @@ var SidePanel = class {
|
|
|
6396
6722
|
}
|
|
6397
6723
|
};
|
|
6398
6724
|
|
|
6399
|
-
export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, mobilePlacement, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
6725
|
+
export { AnchoredVwap, ArrowMark, CONTEXT_MENU_BUILTIN_ORDER, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibRetracement, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TIMEZONES, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, bodyItems, chartType, chartTypes, clampPanelWidth, composeMenu, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, invertWrite, isExchangeTimezone, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, mobilePlacement, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, normalizeTimezone, paneScaleAt, pinnedTopbarActionIds, priceAxisItems, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTimezone, resolveTopbarComposition, scaleChoiceOf, scaleWrites, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, settingsSectionOf, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, timeAxisItems, timezoneMenuRows, topbarActionOverride, topbarHas, tzButtonLabel, tzMenuLabel, tzOffset, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-
|
|
2
|
-
import { injectStyles } from './chunk-
|
|
1
|
+
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-G7B7ZCBF.js';
|
|
2
|
+
import { injectStyles, holdForExit, announceSurface } from './chunk-VHGACEHO.js';
|
|
3
3
|
import * as tooltip from '@zag-js/tooltip';
|
|
4
4
|
import * as dialog from '@zag-js/dialog';
|
|
5
5
|
|
|
@@ -343,6 +343,11 @@ function swipeDirection(dx, dy) {
|
|
|
343
343
|
}
|
|
344
344
|
var Drawer = class {
|
|
345
345
|
constructor(opts = {}) {
|
|
346
|
+
this.opener = null;
|
|
347
|
+
this.wasOpen = false;
|
|
348
|
+
/** The sheet and scrim's exit animation after a close; a reopen cancels it. */
|
|
349
|
+
this.exit = null;
|
|
350
|
+
this.destroyed = false;
|
|
346
351
|
const doc = (opts.host ?? document.body).ownerDocument;
|
|
347
352
|
injectStyles(DRAWER_STYLE_ID, DRAWER_CSS, doc);
|
|
348
353
|
const host = opts.host ?? doc.body;
|
|
@@ -370,12 +375,24 @@ var Drawer = class {
|
|
|
370
375
|
const mid = String(this.ctrl.props.id);
|
|
371
376
|
this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => {
|
|
372
377
|
const api = this.ctrl.connect(service);
|
|
378
|
+
const closing = this.wasOpen && !api.open;
|
|
379
|
+
if (closing) this.announce(false);
|
|
373
380
|
spreadProps(this.backdrop, api.getBackdropProps(), mid);
|
|
374
381
|
spreadProps(this.positioner, api.getPositionerProps(), mid);
|
|
375
382
|
spreadProps(this.panel, api.getContentProps(), mid);
|
|
376
383
|
spreadProps(this.titleEl, api.getTitleProps(), mid);
|
|
377
|
-
|
|
378
|
-
|
|
384
|
+
if (api.open) {
|
|
385
|
+
this.exit?.cancel();
|
|
386
|
+
this.exit = null;
|
|
387
|
+
this.setShown(true);
|
|
388
|
+
} else if (closing) {
|
|
389
|
+
this.holdExit();
|
|
390
|
+
} else if (!this.exit) {
|
|
391
|
+
this.setShown(false);
|
|
392
|
+
}
|
|
393
|
+
if (api.open && !this.wasOpen) this.announce(true);
|
|
394
|
+
if (this.wasOpen && !api.open) this.restoreOpener();
|
|
395
|
+
this.wasOpen = api.open;
|
|
379
396
|
});
|
|
380
397
|
}
|
|
381
398
|
/** Any element between `from` and the panel that has already been scrolled down —
|
|
@@ -484,19 +501,67 @@ var Drawer = class {
|
|
|
484
501
|
setTitle(title) {
|
|
485
502
|
this.titleEl.textContent = title;
|
|
486
503
|
}
|
|
504
|
+
setShown(shown) {
|
|
505
|
+
this.backdrop.style.display = shown ? "" : "none";
|
|
506
|
+
this.positioner.style.display = shown ? "" : "none";
|
|
507
|
+
}
|
|
508
|
+
/** Keep the just-closed sheet up through its exit animation, then hide it — or
|
|
509
|
+
* remove it, when it was destroyed meanwhile. `spreadProps` re-applies the close
|
|
510
|
+
* props' `hidden` only when its value changes, so lifting it keeps the sheet and
|
|
511
|
+
* scrim up until the exit ends. The positioner spans the host: inert, it lets
|
|
512
|
+
* clicks through to the page while the sheet animates out. */
|
|
513
|
+
holdExit() {
|
|
514
|
+
const held = [this.panel, this.backdrop];
|
|
515
|
+
for (const el of held) el.hidden = false;
|
|
516
|
+
this.exit = holdForExit(
|
|
517
|
+
held,
|
|
518
|
+
() => {
|
|
519
|
+
this.exit = null;
|
|
520
|
+
if (this.destroyed) {
|
|
521
|
+
this.detach();
|
|
522
|
+
} else if (!this.open) {
|
|
523
|
+
for (const el of held) el.hidden = true;
|
|
524
|
+
this.setShown(false);
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
{ inert: [this.positioner] }
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
detach() {
|
|
531
|
+
this.backdrop.remove();
|
|
532
|
+
this.positioner.remove();
|
|
533
|
+
}
|
|
534
|
+
/** Closing hands focus back to whatever opened it (Escape, the ✕, hide(), or a
|
|
535
|
+
* teardown that outruns the machine's close notification). */
|
|
536
|
+
restoreOpener() {
|
|
537
|
+
const opener = this.opener;
|
|
538
|
+
this.opener = null;
|
|
539
|
+
if (opener?.isConnected) opener.focus({ preventScroll: true });
|
|
540
|
+
}
|
|
541
|
+
announce(open) {
|
|
542
|
+
const opener = this.opener === this.panel.ownerDocument.body ? null : this.opener;
|
|
543
|
+
announceSurface(this.panel, open, "drawer", opener);
|
|
544
|
+
}
|
|
487
545
|
get open() {
|
|
488
546
|
return this.ctrl.connect(this.handle.service).open;
|
|
489
547
|
}
|
|
490
548
|
show() {
|
|
549
|
+
this.opener = this.panel.ownerDocument.activeElement;
|
|
491
550
|
this.ctrl.connect(this.handle.service).setOpen(true);
|
|
492
551
|
}
|
|
493
552
|
hide() {
|
|
494
553
|
this.ctrl.connect(this.handle.service).setOpen(false);
|
|
495
554
|
}
|
|
496
555
|
destroy() {
|
|
556
|
+
if (this.wasOpen && !this.open) this.handle.flush();
|
|
497
557
|
this.handle.stop();
|
|
498
|
-
this.
|
|
499
|
-
this.
|
|
558
|
+
this.destroyed = true;
|
|
559
|
+
if (this.wasOpen) {
|
|
560
|
+
this.wasOpen = false;
|
|
561
|
+
this.announce(false);
|
|
562
|
+
}
|
|
563
|
+
this.restoreOpener();
|
|
564
|
+
if (!this.exit) this.detach();
|
|
500
565
|
}
|
|
501
566
|
};
|
|
502
567
|
|
|
@@ -146,6 +146,7 @@ registerIcon("expand", S('<rect x="2.2" y="2.2" width="11.6" height="11.6" rx="1
|
|
|
146
146
|
registerIcon("plus", S('<path d="M8 2.8v10.4M2.8 8h10.4"/>'));
|
|
147
147
|
registerIcon("minus", S('<path d="M2.8 8h10.4"/>'));
|
|
148
148
|
registerIcon("maximize", S('<path d="M2.5 6V3a.5.5 0 0 1 .5-.5h3M10 2.5h3a.5.5 0 0 1 .5.5v3M13.5 10v3a.5.5 0 0 1-.5.5h-3M6 13.5H3a.5.5 0 0 1-.5-.5v-3"/>'));
|
|
149
|
+
registerIcon("restore", S('<path d="M6 2.5v3a.5.5 0 0 1-.5.5h-3M13.5 6h-3a.5.5 0 0 1-.5-.5v-3M10 13.5v-3a.5.5 0 0 1 .5-.5h3M2.5 10h3a.5.5 0 0 1 .5.5v3"/>'));
|
|
149
150
|
registerIcon("restore", S('<path d="M6.2 2.5v3.7H2.5M9.8 13.5V9.8h3.7M13.5 6.2H9.8V2.5M2.5 9.8h3.7v3.7"/>'));
|
|
150
151
|
registerIcon("star", S('<path d="M8 2.2l1.75 3.55 3.9.55-2.8 2.75.65 3.9L8 11.1l-3.5 1.85.65-3.9-2.8-2.75 3.9-.55z"/>'));
|
|
151
152
|
registerIcon("star-filled", S('<path d="M8 2.2l1.75 3.55 3.9.55-2.8 2.75.65 3.9L8 11.1l-3.5 1.85.65-3.9-2.8-2.75 3.9-.55z"/>', 'fill="currentColor"'));
|
|
@@ -270,4 +271,64 @@ function iconEl(id, doc = document) {
|
|
|
270
271
|
return span;
|
|
271
272
|
}
|
|
272
273
|
|
|
273
|
-
|
|
274
|
+
// src/ui/surface-events.ts
|
|
275
|
+
var SURFACE_OPEN_EVENT = "vela:surface-open";
|
|
276
|
+
var SURFACE_CLOSE_EVENT = "vela:surface-close";
|
|
277
|
+
function announceSurface(el, open, kind, trigger = null) {
|
|
278
|
+
const View = el.ownerDocument.defaultView;
|
|
279
|
+
if (!View) return;
|
|
280
|
+
el.dispatchEvent(
|
|
281
|
+
new View.CustomEvent(open ? SURFACE_OPEN_EVENT : SURFACE_CLOSE_EVENT, { bubbles: true, composed: true, detail: { kind, trigger } })
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/ui/surface-exit.ts
|
|
286
|
+
var CLOSING_ATTR = "data-closing";
|
|
287
|
+
var SURFACE_EXIT_CAP_MS = 1e3;
|
|
288
|
+
function animationsOf(els) {
|
|
289
|
+
return els.flatMap((el) => el.getAnimations({ subtree: true }));
|
|
290
|
+
}
|
|
291
|
+
function ends(a) {
|
|
292
|
+
return Number.isFinite(a.effect?.getComputedTiming().endTime ?? Number.POSITIVE_INFINITY);
|
|
293
|
+
}
|
|
294
|
+
function holdForExit(els, done, opts = {}) {
|
|
295
|
+
const list = Array.isArray(els) ? els : [els];
|
|
296
|
+
if (list.length === 0 || !list.every((el) => typeof el.getAnimations === "function")) {
|
|
297
|
+
done();
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
const before = new Set(animationsOf(list));
|
|
301
|
+
for (const el of list) el.setAttribute(CLOSING_ATTR, "");
|
|
302
|
+
const exit = animationsOf(list).filter((a) => !before.has(a) && ends(a));
|
|
303
|
+
if (exit.length === 0) {
|
|
304
|
+
for (const el of list) el.removeAttribute(CLOSING_ATTR);
|
|
305
|
+
done();
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
const frozen = [...list, ...opts.inert ?? []];
|
|
309
|
+
const wasInert = frozen.map((el) => el.inert);
|
|
310
|
+
for (const el of frozen) el.inert = true;
|
|
311
|
+
let settled = false;
|
|
312
|
+
const settle = (complete) => {
|
|
313
|
+
if (settled) return;
|
|
314
|
+
settled = true;
|
|
315
|
+
clearTimeout(cap);
|
|
316
|
+
for (const el of list) el.removeAttribute(CLOSING_ATTR);
|
|
317
|
+
frozen.forEach((el, i) => {
|
|
318
|
+
el.inert = wasInert[i];
|
|
319
|
+
});
|
|
320
|
+
if (complete) done();
|
|
321
|
+
};
|
|
322
|
+
const cap = setTimeout(() => settle(true), SURFACE_EXIT_CAP_MS);
|
|
323
|
+
let pending = exit.length;
|
|
324
|
+
const one = () => {
|
|
325
|
+
if (--pending === 0) settle(true);
|
|
326
|
+
};
|
|
327
|
+
for (const a of exit) a.finished.then(one, one);
|
|
328
|
+
return {
|
|
329
|
+
cancel: () => settle(false),
|
|
330
|
+
finish: () => settle(true)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, SURFACE_CLOSE_EVENT, SURFACE_OPEN_EVENT, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, announceSurface, categoricalColor, holdForExit, icon, iconAt, iconEl, iconMarkup, injectStyles, isDarkColor, mix, overlayScrollbarCss, registerIcon, svg16, svg24, svg24Solid, withAlpha };
|