@luxalgo/vela 0.8.4 → 0.9.0

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.
Files changed (139) hide show
  1. package/dist/{DataProvider-Byo8pEv0.d.ts → DataProvider-BGlB1zSc.d.ts} +1 -1
  2. package/dist/{DataProvider-Bw58CjYy.d.cts → DataProvider-zJGp58kb.d.cts} +1 -1
  3. package/dist/{chunk-MOJ4T26N.js → chunk-4WAHYL7Y.js} +1151 -474
  4. package/dist/chunk-O6L27KRB.js +1331 -0
  5. package/dist/{chunk-WY5H4S4I.js → chunk-PZN4RS4T.js} +91 -36
  6. package/dist/{chunk-AUOB7A5Y.js → chunk-WHPQQYH7.js} +29 -13
  7. package/dist/{chunk-UNUVPQFW.js → chunk-XIRSR3D6.js} +2837 -1604
  8. package/dist/{chunk-ALTGHKIM.js → chunk-YRCL3WMD.js} +510 -406
  9. package/dist/{contributions-BY3zSYiZ.d.ts → contributions-BjefWpxQ.d.ts} +106 -25
  10. package/dist/{contributions-DOm40g5-.d.cts → contributions-CpCJisTC.d.cts} +106 -25
  11. package/dist/index.cjs +4485 -2163
  12. package/dist/index.d.cts +67 -25
  13. package/dist/index.d.ts +67 -25
  14. package/dist/index.js +5 -5
  15. package/dist/{keymap-CGOz5F5f.d.ts → keymap-B9_FLhfJ.d.cts} +9 -6
  16. package/dist/{keymap-CGOz5F5f.d.cts → keymap-UolhuXH1.d.ts} +9 -6
  17. package/dist/locales/ar.cjs +2260 -0
  18. package/dist/locales/ar.d.cts +5 -0
  19. package/dist/locales/ar.d.ts +5 -0
  20. package/dist/locales/ar.js +2258 -0
  21. package/dist/locales/de.cjs +2260 -0
  22. package/dist/locales/de.d.cts +5 -0
  23. package/dist/locales/de.d.ts +5 -0
  24. package/dist/locales/de.js +2258 -0
  25. package/dist/locales/en.cjs +2260 -0
  26. package/dist/locales/en.d.cts +5 -0
  27. package/dist/locales/en.d.ts +5 -0
  28. package/dist/locales/en.js +2258 -0
  29. package/dist/locales/es.cjs +2260 -0
  30. package/dist/locales/es.d.cts +5 -0
  31. package/dist/locales/es.d.ts +5 -0
  32. package/dist/locales/es.js +2258 -0
  33. package/dist/locales/fr.cjs +2260 -0
  34. package/dist/locales/fr.d.cts +5 -0
  35. package/dist/locales/fr.d.ts +5 -0
  36. package/dist/locales/fr.js +2258 -0
  37. package/dist/locales/he.cjs +2260 -0
  38. package/dist/locales/he.d.cts +5 -0
  39. package/dist/locales/he.d.ts +5 -0
  40. package/dist/locales/he.js +2258 -0
  41. package/dist/locales/hi.cjs +2260 -0
  42. package/dist/locales/hi.d.cts +5 -0
  43. package/dist/locales/hi.d.ts +5 -0
  44. package/dist/locales/hi.js +2258 -0
  45. package/dist/locales/id.cjs +2260 -0
  46. package/dist/locales/id.d.cts +5 -0
  47. package/dist/locales/id.d.ts +5 -0
  48. package/dist/locales/id.js +2258 -0
  49. package/dist/locales/it.cjs +2260 -0
  50. package/dist/locales/it.d.cts +5 -0
  51. package/dist/locales/it.d.ts +5 -0
  52. package/dist/locales/it.js +2258 -0
  53. package/dist/locales/ja.cjs +2260 -0
  54. package/dist/locales/ja.d.cts +5 -0
  55. package/dist/locales/ja.d.ts +5 -0
  56. package/dist/locales/ja.js +2258 -0
  57. package/dist/locales/ko.cjs +2260 -0
  58. package/dist/locales/ko.d.cts +5 -0
  59. package/dist/locales/ko.d.ts +5 -0
  60. package/dist/locales/ko.js +2258 -0
  61. package/dist/locales/ms.cjs +2260 -0
  62. package/dist/locales/ms.d.cts +5 -0
  63. package/dist/locales/ms.d.ts +5 -0
  64. package/dist/locales/ms.js +2258 -0
  65. package/dist/locales/pl.cjs +2260 -0
  66. package/dist/locales/pl.d.cts +5 -0
  67. package/dist/locales/pl.d.ts +5 -0
  68. package/dist/locales/pl.js +2258 -0
  69. package/dist/locales/pt-BR.cjs +2260 -0
  70. package/dist/locales/pt-BR.d.cts +5 -0
  71. package/dist/locales/pt-BR.d.ts +5 -0
  72. package/dist/locales/pt-BR.js +2258 -0
  73. package/dist/locales/ru.cjs +2260 -0
  74. package/dist/locales/ru.d.cts +5 -0
  75. package/dist/locales/ru.d.ts +5 -0
  76. package/dist/locales/ru.js +2258 -0
  77. package/dist/locales/th.cjs +2260 -0
  78. package/dist/locales/th.d.cts +5 -0
  79. package/dist/locales/th.d.ts +5 -0
  80. package/dist/locales/th.js +2258 -0
  81. package/dist/locales/tr.cjs +2260 -0
  82. package/dist/locales/tr.d.cts +5 -0
  83. package/dist/locales/tr.d.ts +5 -0
  84. package/dist/locales/tr.js +2258 -0
  85. package/dist/locales/vi.cjs +2260 -0
  86. package/dist/locales/vi.d.cts +5 -0
  87. package/dist/locales/vi.d.ts +5 -0
  88. package/dist/locales/vi.js +2258 -0
  89. package/dist/locales/zh-Hans.cjs +2260 -0
  90. package/dist/locales/zh-Hans.d.cts +5 -0
  91. package/dist/locales/zh-Hans.d.ts +5 -0
  92. package/dist/locales/zh-Hans.js +2258 -0
  93. package/dist/locales/zh-Hant.cjs +2260 -0
  94. package/dist/locales/zh-Hant.d.cts +5 -0
  95. package/dist/locales/zh-Hant.d.ts +5 -0
  96. package/dist/locales/zh-Hant.js +2258 -0
  97. package/dist/{options-CSXbjMM5.d.cts → options-CpegHml_.d.cts} +110 -10
  98. package/dist/{options-CSXbjMM5.d.ts → options-D4L3_hv_.d.ts} +110 -10
  99. package/dist/{plugin-BDxUhGO3.d.ts → plugin-DTmulpKM.d.ts} +92 -40
  100. package/dist/{plugin-CiQVyETg.d.cts → plugin-DpNp4aBi.d.cts} +92 -40
  101. package/dist/plugin.cjs +1267 -319
  102. package/dist/plugin.d.cts +7 -6
  103. package/dist/plugin.d.ts +7 -6
  104. package/dist/plugin.js +3 -3
  105. package/dist/providers/binance.cjs +1 -1
  106. package/dist/providers/binance.d.cts +3 -2
  107. package/dist/providers/binance.d.ts +3 -2
  108. package/dist/providers/binance.js +1 -1
  109. package/dist/providers/coinbase.cjs +1 -1
  110. package/dist/providers/coinbase.d.cts +3 -2
  111. package/dist/providers/coinbase.d.ts +3 -2
  112. package/dist/providers/coinbase.js +1 -1
  113. package/dist/providers/hyperliquid.cjs +1 -1
  114. package/dist/providers/hyperliquid.d.cts +3 -2
  115. package/dist/providers/hyperliquid.d.ts +3 -2
  116. package/dist/providers/hyperliquid.js +1 -1
  117. package/dist/{side-panel-_2UK1gSm.d.ts → side-panel-BqUnpfev.d.cts} +13 -2
  118. package/dist/{side-panel-_2UK1gSm.d.cts → side-panel-CYmH1Opm.d.ts} +13 -2
  119. package/dist/{statusline-model-C9tYXuux.d.ts → statusline-model-C3yIY9WE.d.ts} +11 -3
  120. package/dist/{statusline-model-DUBX6Fib.d.cts → statusline-model-pGs3Xvp-.d.cts} +11 -3
  121. package/dist/types-BlrXRLIR.d.cts +2515 -0
  122. package/dist/types-BlrXRLIR.d.ts +2515 -0
  123. package/dist/ui.cjs +1008 -56
  124. package/dist/ui.d.cts +21 -2
  125. package/dist/ui.d.ts +21 -2
  126. package/dist/ui.js +3 -3
  127. package/dist/vela.global.js +4451 -2131
  128. package/dist/vela.global.min.js +57 -57
  129. package/dist/widget.cjs +5819 -2780
  130. package/dist/widget.d.cts +100 -26
  131. package/dist/widget.d.ts +100 -26
  132. package/dist/widget.js +19 -11
  133. package/dist/workspace.cjs +5808 -2787
  134. package/dist/workspace.d.cts +63 -15
  135. package/dist/workspace.d.ts +63 -15
  136. package/dist/workspace.js +6 -6
  137. package/package.json +9 -2
  138. package/dist/chunk-I2U4NZD2.js +0 -340
  139. /package/dist/{chunk-W5YPYZ2P.js → chunk-3EYCX2L4.js} +0 -0
@@ -0,0 +1,1331 @@
1
+ // src/core/i18n/locale.ts
2
+ function canonicalLocale(tag) {
3
+ const raw = typeof tag === "string" ? tag.trim() : "";
4
+ if (!raw) return "en";
5
+ try {
6
+ return Intl.getCanonicalLocales(raw)[0] ?? raw;
7
+ } catch {
8
+ return raw;
9
+ }
10
+ }
11
+ function parseLocale(tag) {
12
+ try {
13
+ return new Intl.Locale(tag);
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function languageOf(tag) {
19
+ return (parseLocale(tag)?.language ?? tag.split(/[-_]/)[0] ?? tag).toLowerCase();
20
+ }
21
+ function fallbackChain(tag) {
22
+ const out = [];
23
+ const add = (t) => {
24
+ if (t && !out.includes(t)) out.push(t);
25
+ };
26
+ add(tag);
27
+ const loc = parseLocale(tag);
28
+ if (loc) {
29
+ const base = loc.baseName;
30
+ add(base);
31
+ const parts = base.split("-");
32
+ let impliedScript;
33
+ if (!loc.script) {
34
+ try {
35
+ impliedScript = loc.maximize().script;
36
+ } catch {
37
+ impliedScript = void 0;
38
+ }
39
+ }
40
+ for (let i = parts.length - 1; i >= 1; i -= 1) {
41
+ if (i === 1 && impliedScript && loc.region) add(`${loc.language}-${impliedScript}`);
42
+ add(parts.slice(0, i).join("-"));
43
+ }
44
+ if (impliedScript && !loc.region) add(`${loc.language}-${impliedScript}`);
45
+ try {
46
+ const usual = new Intl.Locale(loc.language).maximize();
47
+ if (usual.region && usual.script === (loc.script ?? impliedScript)) add(`${loc.language}-${usual.region}`);
48
+ } catch {
49
+ }
50
+ }
51
+ add("en");
52
+ return out;
53
+ }
54
+ var RTL_SCRIPTS = /* @__PURE__ */ new Set(["Arab", "Hebr", "Thaa", "Syrc", "Nkoo", "Adlm", "Rohg", "Mand", "Samr", "Yezi"]);
55
+ var RTL_LANGUAGES = /* @__PURE__ */ new Set(["ar", "he", "iw", "fa", "ur", "ps", "sd", "ug", "yi", "dv", "ckb", "ks"]);
56
+ function localeDirection(tag) {
57
+ const loc = parseLocale(tag);
58
+ if (loc) {
59
+ try {
60
+ const tl = loc;
61
+ const info = typeof tl.getTextInfo === "function" ? tl.getTextInfo() : tl.textInfo;
62
+ if (info?.direction === "rtl" || info?.direction === "ltr") return info.direction;
63
+ } catch {
64
+ }
65
+ try {
66
+ const script = loc.script ?? loc.maximize().script;
67
+ if (script) return RTL_SCRIPTS.has(script) ? "rtl" : "ltr";
68
+ } catch {
69
+ }
70
+ }
71
+ return RTL_LANGUAGES.has(languageOf(tag)) ? "rtl" : "ltr";
72
+ }
73
+ var numberingCache = /* @__PURE__ */ new Map();
74
+ function resolveNumberingSystem(tag, requested) {
75
+ const key = `${tag}|${requested ?? ""}`;
76
+ const cached = numberingCache.get(key);
77
+ if (cached) return cached;
78
+ let nu = "latn";
79
+ try {
80
+ if (requested === "locale") nu = new Intl.NumberFormat(tag).resolvedOptions().numberingSystem;
81
+ else if (requested) nu = new Intl.NumberFormat(tag, { numberingSystem: requested }).resolvedOptions().numberingSystem;
82
+ else {
83
+ const ext = parseLocale(tag)?.numberingSystem;
84
+ if (ext) nu = new Intl.NumberFormat(tag).resolvedOptions().numberingSystem;
85
+ }
86
+ } catch {
87
+ nu = "latn";
88
+ }
89
+ numberingCache.set(key, nu);
90
+ return nu;
91
+ }
92
+
93
+ // src/core/i18n/registry.ts
94
+ var entries = [];
95
+ var version = 0;
96
+ var merged = /* @__PURE__ */ new Map();
97
+ function registerLocale(pack) {
98
+ if (!pack || typeof pack.locale !== "string" || !pack.messages || typeof pack.messages !== "object") {
99
+ throw new TypeError("[vela] registerLocale expects { locale: string, messages: Record<string, string> }");
100
+ }
101
+ const entry = { tag: canonicalLocale(pack.locale), messages: pack.messages };
102
+ entries.push(entry);
103
+ version += 1;
104
+ let disposed = false;
105
+ return () => {
106
+ if (disposed) return;
107
+ disposed = true;
108
+ const i = entries.indexOf(entry);
109
+ if (i >= 0) {
110
+ entries.splice(i, 1);
111
+ version += 1;
112
+ }
113
+ };
114
+ }
115
+ function registeredLocales() {
116
+ return [...new Set(entries.map((e) => e.tag))];
117
+ }
118
+ function messagesFor(chain) {
119
+ const key = chain.join("|");
120
+ const hit = merged.get(key);
121
+ if (hit && hit.version === version) return hit.map;
122
+ const map = /* @__PURE__ */ new Map();
123
+ for (let c = chain.length - 1; c >= 0; c -= 1) {
124
+ const tag = chain[c];
125
+ for (const e of entries) {
126
+ if (e.tag !== tag) continue;
127
+ for (const [id, text] of Object.entries(e.messages)) {
128
+ if (typeof text === "string") map.set(id, text);
129
+ }
130
+ }
131
+ }
132
+ merged.set(key, { version, map });
133
+ return map;
134
+ }
135
+
136
+ // src/core/format/numbers.ts
137
+ var BIDI_MARKS = /[‎‏؜]/g;
138
+ function stripBidiMarks(text) {
139
+ return text.replace(BIDI_MARKS, "");
140
+ }
141
+ var numberFormats = /* @__PURE__ */ new Map();
142
+ function numberFormat(settings, options) {
143
+ const key = `${settings.locale}|${settings.numberingSystem}|${JSON.stringify(options)}`;
144
+ let nf = numberFormats.get(key);
145
+ if (!nf) {
146
+ try {
147
+ nf = new Intl.NumberFormat(settings.locale, { ...options, numberingSystem: settings.numberingSystem });
148
+ } catch {
149
+ nf = new Intl.NumberFormat("en", options);
150
+ }
151
+ numberFormats.set(key, nf);
152
+ }
153
+ return nf;
154
+ }
155
+ var symbolCache = /* @__PURE__ */ new Map();
156
+ function numberSymbols(settings) {
157
+ const key = `${settings.locale}|${settings.numberingSystem}`;
158
+ let sym = symbolCache.get(key);
159
+ if (sym) return sym;
160
+ const parts = numberFormat(settings, { useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 1 }).formatToParts(-1.5);
161
+ const decimal = stripBidiMarks(parts.find((p) => p.type === "decimal")?.value ?? ".") || ".";
162
+ const minus = stripBidiMarks(parts.find((p) => p.type === "minusSign")?.value ?? "-") || "-";
163
+ const plain = numberFormat(settings, { useGrouping: false, maximumFractionDigits: 0 });
164
+ const digits = Array.from({ length: 10 }, (_, d) => stripBidiMarks(plain.format(d)));
165
+ const ascii = decimal === "." && minus === "-" && digits.every((d, i) => d === String(i));
166
+ sym = { ascii, decimal, minus, digits };
167
+ symbolCache.set(key, sym);
168
+ return sym;
169
+ }
170
+ function localizeAscii(text, settings) {
171
+ const sym = numberSymbols(settings);
172
+ if (sym.ascii) return text;
173
+ let out = "";
174
+ for (const ch of text) {
175
+ const code = ch.charCodeAt(0);
176
+ if (code >= 48 && code <= 57) out += sym.digits[code - 48];
177
+ else if (ch === ".") out += sym.decimal;
178
+ else if (ch === "-") out += sym.minus;
179
+ else out += ch;
180
+ }
181
+ return out;
182
+ }
183
+ function localizeDigits(text, settings) {
184
+ const sym = numberSymbols(settings);
185
+ if (sym.digits.every((d, i) => d === String(i))) return text;
186
+ return text.replace(/[0-9]/g, (d) => sym.digits[Number(d)]);
187
+ }
188
+ var clampDecimals = (d) => Number.isFinite(d) ? Math.max(0, Math.min(20, Math.trunc(d))) : 2;
189
+ function formatFixed(value, decimals, settings) {
190
+ return localizeAscii(value.toFixed(clampDecimals(decimals)), settings);
191
+ }
192
+ function formatGrouped(value, decimals, settings) {
193
+ const d = clampDecimals(decimals);
194
+ return stripBidiMarks(numberFormat(settings, { minimumFractionDigits: d, maximumFractionDigits: d }).format(value));
195
+ }
196
+ function formatMessageNumber(value, settings, style) {
197
+ if (style === "integer") return stripBidiMarks(numberFormat(settings, { maximumFractionDigits: 0 }).format(value));
198
+ if (style === "percent") return stripBidiMarks(numberFormat(settings, { style: "percent" }).format(value));
199
+ return stripBidiMarks(numberFormat(settings, {}).format(value));
200
+ }
201
+ function formatPercent(value, options, settings) {
202
+ const d = clampDecimals(options?.decimals ?? 2);
203
+ const signed = options?.signed ?? true;
204
+ if (settings.english) {
205
+ const text = signed ? `${value >= 0 ? "+" : "-"}${Math.abs(value).toFixed(d)}%` : `${value.toFixed(d)}%`;
206
+ return localizeAscii(text, settings);
207
+ }
208
+ const nf = numberFormat(settings, { style: "percent", minimumFractionDigits: d, maximumFractionDigits: d, signDisplay: signed ? "always" : "auto" });
209
+ return stripBidiMarks(nf.format(value / 100));
210
+ }
211
+ function formatPrice(value, options, settings) {
212
+ const mode = options.mode ?? "price";
213
+ if (mode === "percent") return formatPercent(value, { decimals: options.decimals, signed: true }, settings);
214
+ if (mode === "indexed" || !options.grouping) return formatFixed(value, options.decimals, settings);
215
+ return formatGrouped(value, options.decimals, settings);
216
+ }
217
+ var COMPACT_STEPS = [
218
+ [1e9, "B"],
219
+ [1e6, "M"],
220
+ [1e3, "K"]
221
+ ];
222
+ function formatCompact(value, options, settings) {
223
+ const d = clampDecimals(options?.decimals ?? 2);
224
+ const trim = options?.trimZeros ?? true;
225
+ if (settings.english) {
226
+ const a = Math.abs(value);
227
+ let div = 1;
228
+ let suffix = "";
229
+ for (const [step, s] of COMPACT_STEPS) {
230
+ if (a >= step) {
231
+ div = step;
232
+ suffix = s;
233
+ break;
234
+ }
235
+ }
236
+ const scaled = value / div;
237
+ const text = trim ? Number(scaled.toFixed(d)).toString() : scaled.toFixed(d);
238
+ return localizeAscii(text, settings) + suffix;
239
+ }
240
+ const nf = numberFormat(settings, { notation: "compact", compactDisplay: "short", maximumFractionDigits: d, minimumFractionDigits: trim ? 0 : d });
241
+ return stripBidiMarks(nf.format(value));
242
+ }
243
+
244
+ // src/core/format/dates.ts
245
+ var EN_MONTHS_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
246
+ var EN_WEEKDAYS_SHORT = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
247
+ var pad2 = (n) => n < 10 ? `0${n}` : String(n);
248
+ var DAY_MS = 864e5;
249
+ var zoneParsers = /* @__PURE__ */ new Map();
250
+ function zoneOffsetMs(ms, timeZone) {
251
+ if (!timeZone || timeZone === "UTC") return 0;
252
+ let dtf = zoneParsers.get(timeZone);
253
+ if (dtf === void 0) {
254
+ try {
255
+ dtf = new Intl.DateTimeFormat("en-US", {
256
+ timeZone,
257
+ hourCycle: "h23",
258
+ year: "numeric",
259
+ month: "2-digit",
260
+ day: "2-digit",
261
+ hour: "2-digit",
262
+ minute: "2-digit",
263
+ second: "2-digit"
264
+ });
265
+ } catch {
266
+ dtf = null;
267
+ }
268
+ zoneParsers.set(timeZone, dtf);
269
+ }
270
+ if (!dtf) return 0;
271
+ try {
272
+ const parts = dtf.formatToParts(new Date(ms));
273
+ const get = (t) => Number(parts.find((p) => p.type === t)?.value);
274
+ const asUTC = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
275
+ return asUTC - ms;
276
+ } catch {
277
+ return 0;
278
+ }
279
+ }
280
+ var dateFormats = /* @__PURE__ */ new Map();
281
+ function dateFormat(settings, options) {
282
+ const key = `${settings.locale}|${settings.numberingSystem}|${JSON.stringify(options)}`;
283
+ let dtf = dateFormats.get(key);
284
+ if (!dtf) {
285
+ const full = { ...options, timeZone: "UTC", calendar: "gregory", numberingSystem: settings.numberingSystem };
286
+ try {
287
+ dtf = new Intl.DateTimeFormat(settings.locale, full);
288
+ } catch {
289
+ dtf = new Intl.DateTimeFormat("en", { ...options, timeZone: "UTC", calendar: "gregory" });
290
+ }
291
+ dateFormats.set(key, dtf);
292
+ }
293
+ return dtf;
294
+ }
295
+ function clockOptions(settings) {
296
+ if (settings.hourCycle === "h23") return { hour: "2-digit", minute: "2-digit", hourCycle: "h23" };
297
+ if (settings.hourCycle === "h12") return { hour: "numeric", minute: "2-digit", hourCycle: "h12" };
298
+ return { hour: "numeric", minute: "2-digit" };
299
+ }
300
+ function englishClock(wall, settings) {
301
+ if (settings.hourCycle === "h23") return localizeAscii(`${pad2(wall.getUTCHours())}:${pad2(wall.getUTCMinutes())}`, settings);
302
+ return stripBidiMarks(dateFormat(settings, clockOptions(settings)).format(wall));
303
+ }
304
+ var TICK_OPTIONS = {
305
+ year: { year: "numeric" },
306
+ month: { month: "short" },
307
+ day: { month: "short", day: "numeric" }
308
+ };
309
+ var isClockUnit = (unit) => unit === "hour" || unit === "minute" || unit === "second";
310
+ function formatTimeTick(ms, options, settings) {
311
+ const wall = new Date(ms + (options.offsetMs ?? 0));
312
+ const unit = options.unit;
313
+ if (settings.english) {
314
+ if (isClockUnit(unit)) return englishClock(wall, settings);
315
+ const month = EN_MONTHS_SHORT[wall.getUTCMonth()];
316
+ if (unit === "year") return localizeAscii(String(wall.getUTCFullYear()), settings);
317
+ if (unit === "month") return month;
318
+ return localizeAscii(`${month} ${wall.getUTCDate()}`, settings);
319
+ }
320
+ const opts = isClockUnit(unit) ? clockOptions(settings) : TICK_OPTIONS[unit];
321
+ return stripBidiMarks(dateFormat(settings, opts).format(wall));
322
+ }
323
+ function formatTimeStamp(ms, options, settings) {
324
+ const wall = new Date(ms + zoneOffsetMs(ms, options?.timeZone ?? "UTC"));
325
+ const withTime = options?.withTime ?? true;
326
+ if (settings.english) {
327
+ const date = localizeAscii(
328
+ `${EN_WEEKDAYS_SHORT[wall.getUTCDay()]} ${wall.getUTCDate()} ${EN_MONTHS_SHORT[wall.getUTCMonth()]} '${pad2(wall.getUTCFullYear() % 100)}`,
329
+ settings
330
+ );
331
+ return withTime ? `${date} ${englishClock(wall, settings)}` : date;
332
+ }
333
+ const opts = { weekday: "short", day: "numeric", month: "short", year: "2-digit", ...withTime ? clockOptions(settings) : {} };
334
+ return stripBidiMarks(dateFormat(settings, opts).format(wall));
335
+ }
336
+ function countdownText(ms) {
337
+ const total = Math.max(0, Math.ceil(ms / 1e3));
338
+ const s = total % 60;
339
+ const m = Math.floor(total / 60) % 60;
340
+ const h = Math.floor(total / 3600);
341
+ const pad = (v) => String(v).padStart(2, "0");
342
+ return h > 0 ? `${h}:${pad(m)}:${pad(s)}` : `${pad(m)}:${pad(s)}`;
343
+ }
344
+ function spanParts(ms) {
345
+ const m = Math.abs(ms);
346
+ const HR = 36e5;
347
+ const MIN = 6e4;
348
+ if (m >= DAY_MS) {
349
+ const d = Math.floor(m / DAY_MS);
350
+ const h = Math.round(m % DAY_MS / HR);
351
+ return h ? [[d, "day"], [h, "hour"]] : [[d, "day"]];
352
+ }
353
+ if (m >= HR) {
354
+ const h = Math.floor(m / HR);
355
+ const mn = Math.round(m % HR / MIN);
356
+ return mn ? [[h, "hour"], [mn, "minute"]] : [[h, "hour"]];
357
+ }
358
+ if (m >= MIN) return [[Math.round(m / MIN), "minute"]];
359
+ return [[Math.round(m / 1e3), "second"]];
360
+ }
361
+ var EN_UNIT = { day: "d", hour: "h", minute: "m", second: "s" };
362
+ function formatDuration(ms, options, settings) {
363
+ if ((options?.style ?? "countdown") === "countdown") return localizeDigits(countdownText(ms), settings);
364
+ const parts = spanParts(ms);
365
+ if (settings.english) return localizeDigits(parts.map(([n, u]) => `${n}${EN_UNIT[u]}`).join(" "), settings);
366
+ return parts.map(([n, unit]) => stripBidiMarks(numberFormat(settings, { style: "unit", unit, unitDisplay: "narrow" }).format(n))).join(" ");
367
+ }
368
+ var clockFormats = /* @__PURE__ */ new Map();
369
+ function formatClock(ms, options, settings) {
370
+ const timeZone = options?.timeZone ?? "UTC";
371
+ const seconds = options?.seconds ?? true;
372
+ const english2 = settings.english && settings.hourCycle === "h23";
373
+ const key = `${english2 ? "en-GB" : settings.locale}|${settings.numberingSystem}|${settings.hourCycle}|${timeZone}|${seconds}`;
374
+ let dtf = clockFormats.get(key);
375
+ if (dtf === void 0) {
376
+ const base = { hour: "2-digit", minute: "2-digit", ...seconds ? { second: "2-digit" } : {}, timeZone };
377
+ try {
378
+ dtf = english2 ? new Intl.DateTimeFormat("en-GB", { ...base, hour12: false }) : new Intl.DateTimeFormat(settings.locale, {
379
+ ...base,
380
+ calendar: "gregory",
381
+ numberingSystem: settings.numberingSystem,
382
+ ...settings.hourCycle === "locale" ? {} : { hourCycle: settings.hourCycle }
383
+ });
384
+ } catch {
385
+ dtf = null;
386
+ }
387
+ clockFormats.set(key, dtf);
388
+ }
389
+ if (!dtf) return "";
390
+ try {
391
+ return stripBidiMarks(dtf.format(new Date(ms)));
392
+ } catch {
393
+ return "";
394
+ }
395
+ }
396
+
397
+ // src/core/format/calendar.ts
398
+ var EN_MONTHS_LONG = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
399
+ var EN_MONTHS_SHORT_PICKER = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
400
+ var EN_WEEKDAYS_MIN = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
401
+ function monthNames(settings, width) {
402
+ if (settings.english) return [...width === "long" ? EN_MONTHS_LONG : EN_MONTHS_SHORT_PICKER];
403
+ const dtf = dateFormat(settings, { month: width });
404
+ return Array.from({ length: 12 }, (_, m) => stripBidiMarks(dtf.format(Date.UTC(2e3, m, 15))));
405
+ }
406
+ function weekdayNames(settings) {
407
+ if (settings.english) return [...EN_WEEKDAYS_MIN];
408
+ const dtf = dateFormat(settings, { weekday: "short" });
409
+ return Array.from({ length: 7 }, (_, d) => stripBidiMarks(dtf.format(Date.UTC(2e3, 0, 2 + d))));
410
+ }
411
+ function yearLabel(settings, year) {
412
+ if (settings.english) return localizeAscii(String(year), settings);
413
+ return stripBidiMarks(dateFormat(settings, { year: "numeric" }).format(Date.UTC(year, 6, 1)));
414
+ }
415
+ function plainInteger(settings, n) {
416
+ return localizeAscii(String(Math.trunc(n)), settings);
417
+ }
418
+ var yearFirstCache = /* @__PURE__ */ new Map();
419
+ function yearBeforeMonth(settings) {
420
+ if (settings.english) return false;
421
+ const key = `${settings.locale}|${settings.numberingSystem}`;
422
+ let first = yearFirstCache.get(key);
423
+ if (first === void 0) {
424
+ const types = dateFormat(settings, { year: "numeric", month: "long" }).formatToParts(Date.UTC(2026, 8, 15)).map((p) => p.type);
425
+ first = types.indexOf("year") < types.indexOf("month");
426
+ yearFirstCache.set(key, first);
427
+ }
428
+ return first;
429
+ }
430
+ var SUNDAY_REGIONS = /* @__PURE__ */ new Set([
431
+ "AG",
432
+ "AS",
433
+ "BD",
434
+ "BR",
435
+ "BS",
436
+ "BT",
437
+ "BW",
438
+ "BZ",
439
+ "CA",
440
+ "CN",
441
+ "CO",
442
+ "DM",
443
+ "DO",
444
+ "ET",
445
+ "GT",
446
+ "GU",
447
+ "HK",
448
+ "HN",
449
+ "ID",
450
+ "IL",
451
+ "IN",
452
+ "JM",
453
+ "JP",
454
+ "KE",
455
+ "KH",
456
+ "KR",
457
+ "LA",
458
+ "MH",
459
+ "MM",
460
+ "MO",
461
+ "MT",
462
+ "MX",
463
+ "MZ",
464
+ "NI",
465
+ "NP",
466
+ "PA",
467
+ "PE",
468
+ "PH",
469
+ "PK",
470
+ "PR",
471
+ "PT",
472
+ "PY",
473
+ "SA",
474
+ "SG",
475
+ "SV",
476
+ "TH",
477
+ "TT",
478
+ "TW",
479
+ "UM",
480
+ "US",
481
+ "VE",
482
+ "VI",
483
+ "WS",
484
+ "YE",
485
+ "ZA",
486
+ "ZW"
487
+ ]);
488
+ var SATURDAY_REGIONS = /* @__PURE__ */ new Set(["AE", "AF", "BH", "DJ", "DZ", "EG", "IQ", "IR", "JO", "KW", "LY", "OM", "QA", "SD", "SY"]);
489
+ function localeWeekStart(locale) {
490
+ let loc;
491
+ try {
492
+ loc = new Intl.Locale(locale);
493
+ } catch {
494
+ return 1;
495
+ }
496
+ try {
497
+ const wl = loc;
498
+ const info = typeof wl.getWeekInfo === "function" ? wl.getWeekInfo() : wl.weekInfo;
499
+ const firstDay = info?.firstDay;
500
+ if (typeof firstDay === "number") return firstDay === 7 ? 0 : firstDay === 6 ? 6 : 1;
501
+ } catch {
502
+ }
503
+ let region = loc.region;
504
+ if (!region) {
505
+ try {
506
+ region = loc.maximize().region;
507
+ } catch {
508
+ region = void 0;
509
+ }
510
+ }
511
+ if (region && SUNDAY_REGIONS.has(region)) return 0;
512
+ if (region && SATURDAY_REGIONS.has(region)) return 6;
513
+ return 1;
514
+ }
515
+
516
+ // src/core/format/formatters.ts
517
+ function builtinFormatters(settings) {
518
+ return {
519
+ price: (value, options) => formatPrice(value, options, settings),
520
+ percent: (value, options) => formatPercent(value, options, settings),
521
+ compact: (value, options) => formatCompact(value, options, settings),
522
+ timeTick: (ms, options) => formatTimeTick(ms, options, settings),
523
+ timeStamp: (ms, options) => formatTimeStamp(ms, options, settings),
524
+ duration: (ms, options) => formatDuration(ms, options, settings),
525
+ clock: (ms, options) => formatClock(ms, options, settings)
526
+ };
527
+ }
528
+ var ENGLISH_SETTINGS = Object.freeze({ locale: "en", numberingSystem: "latn", hourCycle: "h23", english: true });
529
+ var ENGLISH_FORMAT = builtinFormatters(ENGLISH_SETTINGS);
530
+ var warned = false;
531
+ function viaHost(host, value, ctx, fallback) {
532
+ try {
533
+ const out = host(value, ctx);
534
+ if (typeof out === "string") return out;
535
+ } catch (err) {
536
+ if (!warned) {
537
+ warned = true;
538
+ console.warn("[vela] a host formatter threw; the built-in formatting is used instead.", err);
539
+ }
540
+ }
541
+ return fallback();
542
+ }
543
+ function resolveFormatters(settings, overrides) {
544
+ const base = builtinFormatters(settings);
545
+ if (!overrides) return base;
546
+ const ctx = (surface, defaultSurface, timeZone, fallback) => ({
547
+ locale: settings.locale,
548
+ timeZone: timeZone ?? "UTC",
549
+ surface: surface ?? defaultSurface,
550
+ fallback
551
+ });
552
+ const o = overrides;
553
+ return {
554
+ price(value, options) {
555
+ const fallback = () => base.price(value, options);
556
+ if (typeof o.price !== "function") return fallback();
557
+ return viaHost(o.price, value, { ...ctx(options.surface, "priceAxis", void 0, fallback), decimals: options.decimals, mintick: options.mintick, mode: options.mode ?? "price", paneId: options.paneId, grouping: options.grouping ?? false }, fallback);
558
+ },
559
+ percent(value, options) {
560
+ const fallback = () => base.percent(value, options);
561
+ if (typeof o.percent !== "function") return fallback();
562
+ return viaHost(o.percent, value, { ...ctx(options?.surface, "statusLine", void 0, fallback), decimals: options?.decimals ?? 2, signed: options?.signed ?? true }, fallback);
563
+ },
564
+ compact(value, options) {
565
+ const fallback = () => base.compact(value, options);
566
+ if (typeof o.compact !== "function") return fallback();
567
+ return viaHost(o.compact, value, { ...ctx(options?.surface, "priceAxis", void 0, fallback), decimals: options?.decimals ?? 2, trimZeros: options?.trimZeros ?? true }, fallback);
568
+ },
569
+ timeTick(ms, options) {
570
+ const fallback = () => base.timeTick(ms, options);
571
+ if (typeof o.timeTick !== "function") return fallback();
572
+ return viaHost(o.timeTick, ms, { ...ctx(options.surface, "timeAxis", options.timeZone, fallback), unit: options.unit, major: options.major, offsetMs: options.offsetMs ?? 0 }, fallback);
573
+ },
574
+ timeStamp(ms, options) {
575
+ const fallback = () => base.timeStamp(ms, options);
576
+ if (typeof o.timeStamp !== "function") return fallback();
577
+ return viaHost(o.timeStamp, ms, { ...ctx(options?.surface, "crosshair", options?.timeZone, fallback), withTime: options?.withTime ?? true }, fallback);
578
+ },
579
+ duration(ms, options) {
580
+ const fallback = () => base.duration(ms, options);
581
+ if (typeof o.duration !== "function") return fallback();
582
+ return viaHost(o.duration, ms, { ...ctx(options?.surface, "lastPrice", void 0, fallback), style: options?.style ?? "countdown" }, fallback);
583
+ },
584
+ clock(ms, options) {
585
+ const fallback = () => base.clock(ms, options);
586
+ if (typeof o.clock !== "function") return fallback();
587
+ return viaHost(o.clock, ms, { ...ctx(options?.surface, "clock", options?.timeZone, fallback), seconds: options?.seconds ?? true }, fallback);
588
+ }
589
+ };
590
+ }
591
+
592
+ // src/core/i18n/icu.ts
593
+ var Parser = class {
594
+ constructor(src) {
595
+ this.src = src;
596
+ this.i = 0;
597
+ }
598
+ parse() {
599
+ const nodes = this.message(false, 0);
600
+ if (this.i < this.src.length) throw this.error("unmatched }");
601
+ return nodes;
602
+ }
603
+ error(what) {
604
+ return new SyntaxError(`[vela] message syntax: ${what} at ${this.i} in "${this.src}"`);
605
+ }
606
+ /** Text and arguments up to an unmatched `}` (left unread) or the end. */
607
+ message(inPlural, depth) {
608
+ if (depth > 8) throw this.error("nesting too deep");
609
+ const src = this.src;
610
+ const out = [];
611
+ let text = "";
612
+ const flush = () => {
613
+ if (text) out.push(text);
614
+ text = "";
615
+ };
616
+ while (this.i < src.length) {
617
+ const ch = src[this.i];
618
+ if (ch === "'") {
619
+ const next = src[this.i + 1];
620
+ if (next === "'") {
621
+ text += "'";
622
+ this.i += 2;
623
+ } else if (next === "{" || next === "}" || inPlural && next === "#") {
624
+ this.i += 1;
625
+ while (this.i < src.length) {
626
+ const c = src[this.i];
627
+ if (c === "'") {
628
+ if (src[this.i + 1] === "'") {
629
+ text += "'";
630
+ this.i += 2;
631
+ continue;
632
+ }
633
+ this.i += 1;
634
+ break;
635
+ }
636
+ text += c;
637
+ this.i += 1;
638
+ }
639
+ } else {
640
+ text += "'";
641
+ this.i += 1;
642
+ }
643
+ } else if (ch === "{") {
644
+ flush();
645
+ this.i += 1;
646
+ out.push(this.argument(depth));
647
+ } else if (ch === "}") {
648
+ break;
649
+ } else if (ch === "#" && inPlural) {
650
+ flush();
651
+ out.push({ kind: "pound" });
652
+ this.i += 1;
653
+ } else {
654
+ text += ch;
655
+ this.i += 1;
656
+ }
657
+ }
658
+ flush();
659
+ return out;
660
+ }
661
+ skipSpace() {
662
+ while (this.i < this.src.length && /\s/.test(this.src[this.i])) this.i += 1;
663
+ }
664
+ word() {
665
+ this.skipSpace();
666
+ const start = this.i;
667
+ while (this.i < this.src.length && !/[\s,{}]/.test(this.src[this.i])) this.i += 1;
668
+ return this.src.slice(start, this.i);
669
+ }
670
+ expect(ch) {
671
+ this.skipSpace();
672
+ if (this.src[this.i] !== ch) throw this.error(`expected "${ch}"`);
673
+ this.i += 1;
674
+ }
675
+ /** After a `{`: the argument through its closing `}`. */
676
+ argument(depth) {
677
+ const name = this.word();
678
+ if (!name) throw this.error("empty argument name");
679
+ this.skipSpace();
680
+ if (this.src[this.i] === "}") {
681
+ this.i += 1;
682
+ return { kind: "arg", name };
683
+ }
684
+ this.expect(",");
685
+ const type = this.word();
686
+ this.skipSpace();
687
+ if (type === "number") {
688
+ let style;
689
+ if (this.src[this.i] === ",") {
690
+ this.i += 1;
691
+ style = this.word() || void 0;
692
+ }
693
+ this.expect("}");
694
+ return { kind: "arg", name, format: "number", style };
695
+ }
696
+ if (type === "plural" || type === "selectordinal" || type === "select") {
697
+ this.expect(",");
698
+ let offset = 0;
699
+ this.skipSpace();
700
+ if (type !== "select" && this.src.startsWith("offset:", this.i)) {
701
+ this.i += "offset:".length;
702
+ offset = Number(this.word());
703
+ if (!Number.isFinite(offset)) throw this.error("bad offset");
704
+ }
705
+ const options = {};
706
+ for (; ; ) {
707
+ this.skipSpace();
708
+ if (this.src[this.i] === "}") {
709
+ this.i += 1;
710
+ break;
711
+ }
712
+ const key = this.word();
713
+ if (!key) throw this.error("expected a selector");
714
+ this.expect("{");
715
+ options[key] = this.message(type !== "select", depth + 1);
716
+ this.expect("}");
717
+ }
718
+ if (!options.other) throw this.error(`"${name}" has no "other" option`);
719
+ return type === "select" ? { kind: "select", name, options } : { kind: "plural", name, ordinal: type === "selectordinal", offset, options };
720
+ }
721
+ throw this.error(`unknown argument type "${type}"`);
722
+ }
723
+ };
724
+ var parsed = /* @__PURE__ */ new Map();
725
+ var PARSE_CACHE_CAP = 2e3;
726
+ function parseMessage(source) {
727
+ let nodes = parsed.get(source);
728
+ if (!nodes) {
729
+ nodes = new Parser(source).parse();
730
+ if (parsed.size >= PARSE_CACHE_CAP) parsed.clear();
731
+ parsed.set(source, nodes);
732
+ }
733
+ return nodes;
734
+ }
735
+ var pluralRules = /* @__PURE__ */ new Map();
736
+ function rulesFor(locale, ordinal) {
737
+ const key = `${locale}|${ordinal ? "o" : "c"}`;
738
+ let pr = pluralRules.get(key);
739
+ if (!pr) {
740
+ try {
741
+ pr = new Intl.PluralRules(locale, { type: ordinal ? "ordinal" : "cardinal" });
742
+ } catch {
743
+ pr = new Intl.PluralRules("en", { type: ordinal ? "ordinal" : "cardinal" });
744
+ }
745
+ pluralRules.set(key, pr);
746
+ }
747
+ return pr;
748
+ }
749
+ function render(nodes, values, rt, pound) {
750
+ let out = "";
751
+ for (const node of nodes) {
752
+ if (typeof node === "string") {
753
+ out += node;
754
+ continue;
755
+ }
756
+ if (node.kind === "pound") {
757
+ out += pound == null ? "#" : rt.formatNumber(pound);
758
+ continue;
759
+ }
760
+ const raw = values?.[node.name];
761
+ if (node.kind === "arg") {
762
+ if (raw === void 0) out += `{${node.name}}`;
763
+ else if (typeof raw === "number") out += rt.formatNumber(raw, node.format === "number" ? node.style : void 0);
764
+ else if (node.format === "number" && raw.trim() !== "" && Number.isFinite(Number(raw))) out += rt.formatNumber(Number(raw), node.style);
765
+ else out += raw;
766
+ continue;
767
+ }
768
+ if (node.kind === "select") {
769
+ const branch2 = node.options[String(raw)] ?? node.options.other;
770
+ out += render(branch2, values, rt, pound);
771
+ continue;
772
+ }
773
+ const n = typeof raw === "number" ? raw : Number(raw);
774
+ let branch;
775
+ if (Number.isFinite(n)) {
776
+ branch = node.options[`=${n}`] ?? node.options[rulesFor(rt.locale, node.ordinal).select(n - node.offset)];
777
+ }
778
+ out += render(branch ?? node.options.other, values, rt, Number.isFinite(n) ? n - node.offset : null);
779
+ }
780
+ return out;
781
+ }
782
+ function formatMessage(source, values, rt) {
783
+ if (source.indexOf("{") < 0 && source.indexOf("'") < 0) return source;
784
+ return render(parseMessage(source), values, rt, null);
785
+ }
786
+
787
+ // src/core/i18n/translator.ts
788
+ function isMessageDescriptor(m) {
789
+ return typeof m === "object" && m !== null && typeof m.id === "string" && typeof m.defaultMessage === "string";
790
+ }
791
+ var LOCALIZATION_KEYS = ["locale", "direction", "messages", "numberingSystem", "hourCycle", "weekStart", "formatters"];
792
+ function pickLocalization(options) {
793
+ const out = {};
794
+ for (const key of LOCALIZATION_KEYS) if (key in options) out[key] = options[key];
795
+ return out;
796
+ }
797
+ var warnedSyntax = false;
798
+ function resolveArgs(args, resolve) {
799
+ if (!args) return void 0;
800
+ let out = null;
801
+ for (const key of Object.keys(args)) {
802
+ const v = args[key];
803
+ if (typeof v === "object" && v !== null) {
804
+ out ?? (out = { ...args });
805
+ out[key] = resolve(v);
806
+ }
807
+ }
808
+ return out ?? args;
809
+ }
810
+ var LocaleState = class {
811
+ constructor(options = {}) {
812
+ this.runtime = {
813
+ locale: "en",
814
+ formatNumber: (value, style) => formatMessageNumber(value, this.settings, style)
815
+ };
816
+ this.opts = { ...options };
817
+ this.resolve();
818
+ }
819
+ /** The options as last set (unresolved). */
820
+ get options() {
821
+ return this.opts;
822
+ }
823
+ /** Whether the host chose a locale; Vela stamps `lang` only then. */
824
+ get localeExplicit() {
825
+ return this.opts.locale !== void 0;
826
+ }
827
+ /** Whether the host chose a direction; Vela stamps `dir` only then. */
828
+ get directionExplicit() {
829
+ return this.opts.direction !== void 0;
830
+ }
831
+ /** Apply a change: fields present in `next` replace (an explicit `undefined` restores
832
+ * the default), absent fields keep their current value. */
833
+ update(next) {
834
+ const patch = typeof next === "string" ? { locale: next } : next;
835
+ this.opts = { ...this.opts, ...patch };
836
+ for (const key of Object.keys(this.opts)) {
837
+ if (this.opts[key] === void 0) delete this.opts[key];
838
+ }
839
+ this.resolve();
840
+ }
841
+ resolve() {
842
+ const o = this.opts;
843
+ const locale = canonicalLocale(o.locale);
844
+ const numberingSystem = resolveNumberingSystem(locale, o.numberingSystem);
845
+ const hourCycle = o.hourCycle === "h12" || o.hourCycle === "locale" ? o.hourCycle : "h23";
846
+ this.settings = { locale, numberingSystem, hourCycle, english: languageOf(locale) === "en" };
847
+ this.chain = fallbackChain(locale);
848
+ this.resolvedDirection = o.direction === "rtl" || o.direction === "ltr" ? o.direction : o.direction === "auto" ? localeDirection(locale) : "ltr";
849
+ this.resolvedWeekStart = o.weekStart === 0 || o.weekStart === 1 || o.weekStart === 6 ? o.weekStart : localeWeekStart(locale);
850
+ this.runtime.locale = locale;
851
+ this.formatters = resolveFormatters(this.settings, o.formatters);
852
+ }
853
+ get locale() {
854
+ return this.settings.locale;
855
+ }
856
+ get direction() {
857
+ return this.resolvedDirection;
858
+ }
859
+ get numberingSystem() {
860
+ return this.settings.numberingSystem;
861
+ }
862
+ get hourCycle() {
863
+ return this.settings.hourCycle;
864
+ }
865
+ get weekStart() {
866
+ return this.resolvedWeekStart;
867
+ }
868
+ get format() {
869
+ return this.formatters;
870
+ }
871
+ /** The resolved settings the built-in formatters and calendar helpers read. */
872
+ get formatSettings() {
873
+ return this.settings;
874
+ }
875
+ t(message, args) {
876
+ if (typeof message === "string") return message;
877
+ if (!isMessageDescriptor(message)) return message == null ? "" : String(message);
878
+ const { id, defaultMessage } = message;
879
+ const bound = message.values;
880
+ const values = resolveArgs(bound ? args ? { ...bound, ...args } : bound : args, (m) => this.t(m));
881
+ const override = this.opts.messages?.[id];
882
+ const source = typeof override === "string" ? override : messagesFor(this.chain).get(id) ?? defaultMessage;
883
+ try {
884
+ return formatMessage(source, values, this.runtime);
885
+ } catch (err) {
886
+ if (!warnedSyntax) {
887
+ warnedSyntax = true;
888
+ console.warn(`[vela] message "${id}" could not be formatted; the English text is used instead.`, err);
889
+ }
890
+ if (source === defaultMessage) return defaultMessage;
891
+ try {
892
+ return formatMessage(defaultMessage, values, this.runtime);
893
+ } catch {
894
+ return defaultMessage;
895
+ }
896
+ }
897
+ }
898
+ };
899
+ function createTranslator(options) {
900
+ return new LocaleState(options);
901
+ }
902
+ var english = null;
903
+ function englishTranslator() {
904
+ english ?? (english = new LocaleState());
905
+ return english;
906
+ }
907
+ function formatSettingsOf(i18n) {
908
+ if (i18n instanceof LocaleState) return i18n.formatSettings;
909
+ if (!i18n) return englishTranslator().formatSettings;
910
+ return { locale: i18n.locale, numberingSystem: i18n.numberingSystem, hourCycle: i18n.hourCycle, english: languageOf(i18n.locale) === "en" };
911
+ }
912
+
913
+ // src/core/i18n/message.ts
914
+ function msg(id, defaultMessage) {
915
+ return Object.freeze({ id, defaultMessage });
916
+ }
917
+ function withValues(message, values) {
918
+ return Object.freeze({ id: message.id, defaultMessage: message.defaultMessage, values: { ...message.values, ...values } });
919
+ }
920
+
921
+ // src/core/palette.ts
922
+ var ACCENT = "#2962ff";
923
+ var ACCENT_BRIGHT = "#38c0fd";
924
+ var BULLISH = "#089981";
925
+ var BEARISH = "#f23645";
926
+ var NEUTRAL = "#787b86";
927
+ var HIGHLIGHT = "#e0b400";
928
+ var WARNING = "#ff9800";
929
+ var INFO = "#5b9cf6";
930
+ var MARKER = "#ff5d00";
931
+ var VALID = "#0ecb81";
932
+ var INVALID = "#f6465d";
933
+ var SESSION_PRE = "#f97316";
934
+ var SESSION_POST = "#0ea5e9";
935
+ var SESSION_OFF = "#9ca3af";
936
+ var SERIES_LINE = "#3b82f6";
937
+ var CROSSHAIR = "#9aa0ad";
938
+ var SLATE_DEEP = "#1e293b";
939
+ var SLATE = "#475569";
940
+ var CHIP_PLATE = "#595959";
941
+ var TRADE_LONG = ACCENT;
942
+ var TRADE_SHORT = BEARISH;
943
+ var TRADE_EXIT = "#d500f9";
944
+ var CATEGORICAL = [ACCENT, BULLISH, BEARISH, WARNING, "#7e57c2", "#26a69a", INFO, "#e573b5"];
945
+ function categoricalColor(key) {
946
+ let h = 0;
947
+ for (let i = 0; i < key.length; i++) h = h * 31 + key.charCodeAt(i) >>> 0;
948
+ return CATEGORICAL[h % CATEGORICAL.length];
949
+ }
950
+
951
+ // src/core/icons.ts
952
+ var registry = /* @__PURE__ */ new Map();
953
+ function registerIcon(id, svg) {
954
+ registry.set(id, svg);
955
+ }
956
+ function iconMarkup(id) {
957
+ return registry.get(id) ?? null;
958
+ }
959
+ function icon(id) {
960
+ return registry.get(id) ?? "";
961
+ }
962
+ function iconAt(id, px) {
963
+ return icon(id).replace("<svg ", `<svg width="${px}" height="${px}" `);
964
+ }
965
+ function svg16(body, extra = "") {
966
+ return `<svg viewBox="0 0 16 16" width="1em" height="1em" ${extra ? extra + " " : ""}fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`;
967
+ }
968
+ function svg24(body, extra = "") {
969
+ return `<svg viewBox="0 0 24 24" width="1em" height="1em" ${extra ? extra + " " : ""}fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`;
970
+ }
971
+ function svg24Solid(body) {
972
+ return `<svg viewBox="0 0 24 24" width="1em" height="1em" fill="currentColor" stroke="none">${body}</svg>`;
973
+ }
974
+ var S = svg16;
975
+ registerIcon(
976
+ "style-candles",
977
+ S('<path d="M4.5 2v2M4.5 12v2M11.5 2v1.5M11.5 11v3"/><rect x="2.8" y="4" width="3.4" height="8" rx="0.6" fill="currentColor" fill-opacity="0.25"/><rect x="9.8" y="3.5" width="3.4" height="7.5" rx="0.6" fill="currentColor"/>')
978
+ );
979
+ registerIcon(
980
+ "style-bars",
981
+ S('<path d="M4.5 2.5v11M2.5 5h2M4.5 11h2"/><path d="M11.5 2.5v11M9.5 4.5h2M11.5 10.5h2"/>')
982
+ );
983
+ registerIcon("style-line", S('<path d="M1.5 11.5 5.5 7l3 2.5 5-6"/>'));
984
+ registerIcon(
985
+ "style-area",
986
+ S('<path d="M1.5 11.5 5.5 7l3 2.5 5-6"/><path d="M1.5 11.5 5.5 7l3 2.5 5-6V13.5h-12z" fill="currentColor" fill-opacity="0.25" stroke="none"/>')
987
+ );
988
+ registerIcon(
989
+ "style-baseline",
990
+ S('<path d="M1.5 8h13" stroke-dasharray="2 2"/><path d="M2.5 8 5.25 4.5 8 8h-5.5z" fill="currentColor" fill-opacity="0.25" stroke="none"/><path d="M2.5 8 5.25 4.5 8 8"/><path d="M8 8l2.75 3.5L13.5 8h-5.5z" fill="currentColor" fill-opacity="0.25" stroke="none"/><path d="M8 8l2.75 3.5L13.5 8"/>')
991
+ );
992
+ registerIcon(
993
+ "style-heikinashi",
994
+ S('<path d="M4.5 12v2M11.5 2v2"/><rect x="2.8" y="5" width="3.4" height="7" rx="0.6" fill="currentColor" fill-opacity="0.25"/><rect x="9.8" y="4" width="3.4" height="7" rx="0.6" fill="currentColor"/>')
995
+ );
996
+ registerIcon("indicators", S('<path d="M1.5 12.5 5 7l2.5 3.5L11 4l3.5 5"/><circle cx="11" cy="4" r="1.4" fill="currentColor" stroke="none"/>'));
997
+ registerIcon("undo", S('<path d="M6.2 9.5 2.7 6l3.5-3.5"/><path d="M2.7 6h6.8a3.65 3.65 0 0 1 0 7.3H7.5"/>'));
998
+ registerIcon("redo", S('<path d="M9.8 9.5 13.3 6 9.8 2.5"/><path d="M13.3 6H6.5a3.65 3.65 0 0 0 0 7.3h2"/>'));
999
+ registerIcon(
1000
+ "objects",
1001
+ S('<path d="M8 1.8 14 5 8 8.2 2 5z"/><path d="M2 8l6 3.2L14 8" opacity="0.7"/><path d="M2 11l6 3.2 6-3.2" opacity="0.4"/>')
1002
+ );
1003
+ registerIcon("clock", S('<circle cx="8" cy="8" r="6.2"/><path d="M8 4.8V8l2.4 1.6"/>'));
1004
+ registerIcon(
1005
+ "calendar",
1006
+ S('<rect x="2.2" y="3.2" width="11.6" height="10.6" rx="1.4"/><path d="M5.2 1.8v2.8M10.8 1.8v2.8M2.2 6.8h11.6"/>')
1007
+ );
1008
+ registerIcon("datawindow", S('<rect x="1.8" y="2.5" width="12.4" height="11" rx="1.5"/><path d="M4.5 5.5h4M4.5 8h7M4.5 10.5h5.5"/>'));
1009
+ registerIcon("camera", S('<path d="M5.5 4 6.5 2.5h3L10.5 4h3A1 1 0 0 1 14.5 5v7.5a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z"/><circle cx="8" cy="8.5" r="2.6"/>'));
1010
+ registerIcon(
1011
+ "gear",
1012
+ S('<path d="M6.55 1.4h2.9l.32 1.72c.48.14.92.38 1.3.7l1.66-.55 1.45 2.5-1.35 1.1c.08.34.12.7.12 1.07s-.04.73-.12 1.07l1.35 1.1-1.45 2.5-1.66-.55a4.3 4.3 0 0 1-1.3.7L9.45 14.6h-2.9l-.32-1.72a4.3 4.3 0 0 1-1.3-.7l-1.66.55-1.45-2.5 1.35-1.1A4.4 4.4 0 0 1 3.05 7.94c0-.37.04-.73.12-1.07l-1.35-1.1 1.45-2.5 1.66.55c.38-.32.82-.56 1.3-.7L6.55 1.4z"/><circle cx="8" cy="8" r="2.2"/>')
1013
+ );
1014
+ registerIcon("search", S('<circle cx="7" cy="7" r="4.5"/><path d="m10.5 10.5 3.5 3.5"/>'));
1015
+ registerIcon("bell", S('<path d="M8 2a4 4 0 0 0-4 4v2.5L2.5 11v1h11v-1L12 8.5V6a4 4 0 0 0-4-4z"/><path d="M6.5 13.5a1.5 1.5 0 0 0 3 0"/>'));
1016
+ registerIcon(
1017
+ "market-open",
1018
+ svg24('<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>')
1019
+ );
1020
+ registerIcon(
1021
+ "market-pre",
1022
+ svg24('<path d="M12 2v8"/><path d="m4.93 10.93 1.41 1.41"/><path d="M2 18h2"/><path d="M20 18h2"/><path d="m19.07 10.93-1.41 1.41"/><path d="M22 22H2"/><path d="m8 6 4-4 4 4"/><path d="M16 18a4 4 0 0 0-8 0"/>')
1023
+ );
1024
+ registerIcon(
1025
+ "market-post",
1026
+ svg24('<path d="M12 10V2"/><path d="m4.93 10.93 1.41 1.41"/><path d="M2 18h2"/><path d="M20 18h2"/><path d="m19.07 10.93-1.41 1.41"/><path d="M22 22H2"/><path d="m16 14-4 4-4-4"/><path d="M16 6a4 4 0 0 0-8 0"/>')
1027
+ );
1028
+ registerIcon(
1029
+ "market-extended",
1030
+ svg24('<path d="M22 22H2"/><path d="M12 3a5 5 0 0 0 7.5 7.5A7.5 7.5 0 1 1 12 3Z"/>')
1031
+ );
1032
+ registerIcon("market-closed", svg24('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>'));
1033
+ registerIcon(
1034
+ "market-holiday",
1035
+ svg24('<path d="m10 20-1.25-2.5L6 16"/><path d="M10 4 8.75 6.5 6 8"/><path d="m14 20 1.25-2.5L18 16"/><path d="m14 4 1.25 2.5L18 8"/><path d="m17 10-5 5-5-5"/><path d="M4 12h16"/>')
1036
+ );
1037
+ registerIcon("chevron-right", S('<path d="m6 3.5 4.5 4.5L6 12.5"/>'));
1038
+ registerIcon("chevron-left", S('<path d="M10 3.5 5.5 8l4.5 4.5"/>'));
1039
+ registerIcon("chevron-down", S('<path d="M3.5 6 8 10.5 12.5 6"/>'));
1040
+ registerIcon("chevron-up", S('<path d="M3.5 10 8 5.5 12.5 10"/>'));
1041
+ registerIcon("chevrons-right", S('<path d="m4 3.5 4.5 4.5L4 12.5"/><path d="m8.5 3.5 4.5 4.5-4.5 4.5"/>'));
1042
+ registerIcon("chevrons-left", S('<path d="M12 3.5 7.5 8l4.5 4.5"/><path d="M7.5 3.5 3 8l4.5 4.5"/>'));
1043
+ registerIcon("replay", S('<path d="M14 4.2v7.6L8.6 8z"/><path d="M7.4 4.2v7.6L2 8z"/>'));
1044
+ registerIcon("check", S('<path d="m2.8 8.4 3.4 3.4 7-7.6"/>'));
1045
+ registerIcon("close", S('<path d="m3.8 3.8 8.4 8.4M12.2 3.8l-8.4 8.4"/>'));
1046
+ registerIcon("pin", S('<path d="M5.6 2.5h4.8M6.4 2.5v3.6L4.4 8.4v.9h7.2v-.9L9.6 6.1V2.5M8 9.3v4.2"/>'));
1047
+ registerIcon("pin-filled", S('<path d="M5.6 2.5h4.8M6.4 2.5v3.6L4.4 8.4v.9h7.2v-.9L9.6 6.1V2.5M8 9.3v4.2"/><path d="M6.4 2.5h3.2v3.6l2 2.3v.9H4.4v-.9l2-2.3z" fill="currentColor" stroke="none"/>'));
1048
+ registerIcon("eye", S('<path d="M1.5 8s2.5-5.4 6.5-5.4S14.5 8 14.5 8 12 13.4 8 13.4 1.5 8 1.5 8z"/><circle cx="8" cy="8" r="1.8"/>'));
1049
+ registerIcon("eye-off", S('<path d="M1.5 8s2.5-5.4 6.5-5.4S14.5 8 14.5 8 12 13.4 8 13.4 1.5 8 1.5 8z" opacity="0.45"/><path d="m3 13 10-10"/>'));
1050
+ registerIcon("lock", S('<rect x="3.2" y="7" width="9.6" height="6.6" rx="1.2"/><path d="M5.6 7V5.2a2.4 2.4 0 0 1 4.8 0V7"/>'));
1051
+ registerIcon("unlock", S('<rect x="3.2" y="7" width="9.6" height="6.6" rx="1.2"/><path d="M5.6 7V5.2a2.4 2.4 0 0 1 4.7-.7"/>'));
1052
+ registerIcon("trash", S('<path d="M2.5 4.3h11M6.2 4.3V3.1a1 1 0 0 1 1-1h1.6a1 1 0 0 1 1 1v1.2M4.2 4.3l.5 9.1a1.15 1.15 0 0 0 1.15 1.1h4.3a1.15 1.15 0 0 0 1.15-1.1l.5-9.1M6.5 7v4.5M9.5 7v4.5"/>'));
1053
+ registerIcon("group", S('<path d="M1.8 4.5V2.4a.6.6 0 0 1 .6-.6h2.1M11.5 1.8h2.1a.6.6 0 0 1 .6.6v2.1M14.2 11.5v2.1a.6.6 0 0 1-.6.6h-2.1M4.5 14.2H2.4a.6.6 0 0 1-.6-.6v-2.1"/><rect x="4" y="4" width="4.2" height="4.2" rx="0.7"/><rect x="7.8" y="7.8" width="4.2" height="4.2" rx="0.7"/>'));
1054
+ registerIcon("ungroup", S('<rect x="1.6" y="1.6" width="6.2" height="6.2" rx="0.9"/><rect x="8.2" y="8.2" width="6.2" height="6.2" rx="0.9" stroke-dasharray="2 1.5"/>'));
1055
+ registerIcon("clone", S('<rect x="5.5" y="5.5" width="9" height="9" rx="1.2"/><path d="M11 5.5v-3a1 1 0 0 0-1-1H2.5a1 1 0 0 0-1 1V10a1 1 0 0 0 1 1h3"/>'));
1056
+ registerIcon("arrow-up", S('<path d="M8 13.2V3M4.2 6.8 8 3l3.8 3.8"/>'));
1057
+ registerIcon("arrow-down", S('<path d="M8 2.8V13M4.2 9.2 8 13l3.8-3.8"/>'));
1058
+ registerIcon("move-vertical", S('<path d="M8 2.5v11M5 5.5 8 2.5l3 3M5 10.5l3 3 3-3"/>'));
1059
+ registerIcon("move", S('<path d="M8 1.8v12.4M1.8 8h12.4M5.6 4.2 8 1.8l2.4 2.4M5.6 11.8 8 14.2l2.4-2.4M4.2 5.6 1.8 8l2.4 2.4M11.8 5.6 14.2 8l-2.4 2.4"/>'));
1060
+ registerIcon("pen", S('<path d="m10.8 2.2 3 3-8 8-3.6.6.6-3.6z"/><path d="m9.2 3.8 3 3"/>'));
1061
+ registerIcon("wave", S('<path d="M1.5 10.4c1.6 0 1.9-4.8 3.4-4.8s1.8 4.8 3.4 4.8 1.8-4.8 3.4-4.8 1.6 4.8 2.8 4.8"/>'));
1062
+ registerIcon("folder-plus", S('<path d="M1.6 4.4a1 1 0 0 1 1-1h2.7l1.3 1.7h6.8a1 1 0 0 1 1 1v6.5a1 1 0 0 1-1 1h-10.8a1 1 0 0 1-1-1z"/><path d="M8 7.6v3.6M6.2 9.4h3.6"/>'));
1063
+ registerIcon("folder-minus", S('<path d="M1.6 4.4a1 1 0 0 1 1-1h2.7l1.3 1.7h6.8a1 1 0 0 1 1 1v6.5a1 1 0 0 1-1 1h-10.8a1 1 0 0 1-1-1z"/><path d="M6.2 9.4h3.6"/>'));
1064
+ registerIcon("collapse", S('<path d="M3 8h10"/>'));
1065
+ registerIcon("expand", S('<rect x="2.2" y="2.2" width="11.6" height="11.6" rx="1.4"/><path d="M8 5.4v5.2M5.4 8h5.2"/>'));
1066
+ registerIcon("plus", S('<path d="M8 2.8v10.4M2.8 8h10.4"/>'));
1067
+ registerIcon("minus", S('<path d="M2.8 8h10.4"/>'));
1068
+ 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"/>'));
1069
+ 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"/>'));
1070
+ 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"/>'));
1071
+ 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"/>'));
1072
+ 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"'));
1073
+ registerIcon("grip", S('<circle cx="6" cy="3.5" r="1"/><circle cx="10" cy="3.5" r="1"/><circle cx="6" cy="8" r="1"/><circle cx="10" cy="8" r="1"/><circle cx="6" cy="12.5" r="1"/><circle cx="10" cy="12.5" r="1"/>', 'fill="currentColor" stroke="none"'));
1074
+ registerIcon("kebab", S('<circle cx="8" cy="3.2" r="1.2"/><circle cx="8" cy="8" r="1.2"/><circle cx="8" cy="12.8" r="1.2"/>', 'fill="currentColor" stroke="none"'));
1075
+ registerIcon("burger", S('<path d="M2.5 4.5h11M2.5 8h11M2.5 11.5h11"/>'));
1076
+ registerIcon("info", S('<path d="M8 7.4v4.4"/><circle cx="8" cy="4.6" r="0.9" fill="currentColor" stroke="none"/>'));
1077
+ registerIcon("reset", S('<path d="M2 8a6 6 0 1 0 6-6 6.5 6.5 0 0 0-4.5 1.83L2 5.33"/><path d="M2 2v3.33h3.33"/>'));
1078
+ registerIcon("pane-collapse", S('<path d="M2.6 9.4h4v4M13.4 6.6h-4v-4"/><path d="m9.4 6.6 4.2-4.2M2.4 13.6l4.2-4.2"/>'));
1079
+ registerIcon("pane-expand", S('<path d="M9.8 2.4h3.8v3.8M6.2 13.6H2.4V9.8"/><path d="m13.6 2.4-4.4 4.4M2.4 13.6l4.4-4.4"/>'));
1080
+ registerIcon("cursor", svg24('<path d="M5 3l6 16 2-6 6-2z"/>', 'fill="currentColor" stroke="none"'));
1081
+ registerIcon(
1082
+ "ruler",
1083
+ svg24('<path d="M21.3 15.3 8.7 2.7a1 1 0 0 0-1.4 0L2.7 7.3a1 1 0 0 0 0 1.4l12.6 12.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4Z"/><path d="m7.5 10.5 2 2"/><path d="m10.5 7.5 2 2"/><path d="m13.5 4.5 2 2"/><path d="m4.5 13.5 2 2"/>')
1084
+ );
1085
+ registerIcon(
1086
+ "magnet",
1087
+ svg24('<path d="m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"/><path d="m5 8 4 4"/><path d="m12 15 4 4"/>')
1088
+ );
1089
+ registerIcon(
1090
+ "eraser",
1091
+ svg24('<path d="m7 21-4.3-4.3a1 1 0 0 1 0-1.4L13 5a2 2 0 0 1 2.8 0l4.2 4.2a2 2 0 0 1 0 2.8L12 20"/><path d="M22 21H7"/><path d="m5 11 9 9"/>')
1092
+ );
1093
+ registerIcon(
1094
+ "pen-lock",
1095
+ svg24('<path d="M13.8 4.2a2.1 2.1 0 0 1 3 3L8.5 15.5l-3.5 1 1-3.5Z"/><rect x="13" y="14.5" width="8" height="6" rx="1.2"/><path d="M15 14.5v-1.6a2 2 0 0 1 4 0v1.6"/>')
1096
+ );
1097
+ registerIcon(
1098
+ "pen-sync",
1099
+ // Pen + two stacked panes — drawing onto every linked chart at once.
1100
+ svg24('<path d="M13.8 4.2a2.1 2.1 0 0 1 3 3L8.5 15.5l-3.5 1 1-3.5Z"/><rect x="12.5" y="13.5" width="6" height="4.8" rx="1"/><path d="M15.5 18.3v1a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-2.8a1 1 0 0 0-1-1h-1"/>')
1101
+ );
1102
+ registerIcon("brush", svg24('<path d="M9.5 12 17 4.5a2.12 2.12 0 0 1 3 3L12.5 15"/><path d="M7 14a3 3 0 0 0-3 3c0 1.3-1.2 1.5-1.5 2 .8.9 2 1.5 3.5 1.5a3.5 3.5 0 0 0 3.5-3.5 3 3 0 0 0-2.5-3Z"/>'));
1103
+ registerIcon(
1104
+ "bucket",
1105
+ svg24('<path d="m18.5 11.5-7-7L4 12a1.8 1.8 0 0 0 0 2.5l5 5a1.8 1.8 0 0 0 2.5 0Z"/><path d="m5 5 4 4"/><path d="M3.5 13.5h13"/><path d="M21 17.5c0 1.1-.9 2-2 2s-2-.9-2-2c0-1 1.2-1.7 2-3 .8 1.3 2 2 2 3Z"/>')
1106
+ );
1107
+ registerIcon("type", svg24('<path d="M5 6V4.5h14V6"/><path d="M12 4.5v15"/><path d="M9.5 19.5h5"/>'));
1108
+ registerIcon("bold", svg24('<path d="M7 5h6a3.5 3.5 0 0 1 0 7H7Z"/><path d="M7 12h7a3.5 3.5 0 0 1 0 7H7Z"/>', 'stroke-width="2.4"'));
1109
+ registerIcon("italic", svg24('<path d="M15 5h-5M14 19H9M14.5 5 10 19"/>', 'stroke-width="2.2"'));
1110
+ registerIcon("price-delta", svg24('<path d="M12 4v16"/><path d="M8 8l4-4 4 4"/><path d="M8 16l4 4 4-4"/>'));
1111
+ registerIcon("date-delta", svg24('<path d="M4 12h16"/><path d="M8 8l-4 4 4 4"/><path d="M16 8l4 4-4 4"/>'));
1112
+ registerIcon("bring-front", svg24('<rect x="8.5" y="8.5" width="7" height="7" rx="1.5"/><path d="M4.5 10.5V6a1.5 1.5 0 0 1 1.5-1.5h4.5"/><path d="M19.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5h-4.5"/>'));
1113
+ registerIcon(
1114
+ "send-back",
1115
+ svg24('<rect x="8.5" y="8.5" width="7" height="7" rx="1.5" fill="currentColor" stroke="none" opacity="0.35"/><path d="M4.5 10.5V6a1.5 1.5 0 0 1 1.5-1.5h4.5"/><path d="M19.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5h-4.5"/><rect x="8.5" y="8.5" width="7" height="7" rx="1.5"/>')
1116
+ );
1117
+ registerIcon("r-squared", '<svg viewBox="0 0 24 24" width="1em" height="1em" fill="currentColor" stroke="none"><text x="2.5" y="17.5" font-size="14" font-family="serif">R²</text></svg>');
1118
+ registerIcon("bands", svg24('<path d="M3 6h18"/><path d="M3 18h18"/><path d="M3 12h18" stroke-dasharray="3 3"/>'));
1119
+ registerIcon("dedekind", svg24('<path d="M2 20h20"/><path d="M4 20a8 8 0 0 1 16 0"/><path d="M8 20a4 4 0 0 1 8 0"/><path d="M12 4v16"/>'));
1120
+ registerIcon("sonic", svg24('<circle cx="15" cy="12" r="4"/><circle cx="12" cy="12" r="2.5"/><path d="M8 5v14"/>'));
1121
+ registerIcon("supersonic", svg24('<circle cx="16" cy="12" r="3.5"/><path d="M6 12 15 6M6 12 15 18"/>'));
1122
+
1123
+ // src/core/color.ts
1124
+ function parseRgb(color) {
1125
+ const s = color.trim();
1126
+ let m = /^#([0-9a-f]{3})$/i.exec(s);
1127
+ if (m) {
1128
+ const h = m[1];
1129
+ return {
1130
+ r: parseInt(h[0] + h[0], 16),
1131
+ g: parseInt(h[1] + h[1], 16),
1132
+ b: parseInt(h[2] + h[2], 16)
1133
+ };
1134
+ }
1135
+ m = /^#([0-9a-f]{6})[0-9a-f]{0,2}$/i.exec(s);
1136
+ if (m) {
1137
+ const h = m[1];
1138
+ return {
1139
+ r: parseInt(h.slice(0, 2), 16),
1140
+ g: parseInt(h.slice(2, 4), 16),
1141
+ b: parseInt(h.slice(4, 6), 16)
1142
+ };
1143
+ }
1144
+ const rgb = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i.exec(s);
1145
+ if (rgb) {
1146
+ return { r: parseFloat(rgb[1]), g: parseFloat(rgb[2]), b: parseFloat(rgb[3]) };
1147
+ }
1148
+ return null;
1149
+ }
1150
+ function withAlpha(color, alpha) {
1151
+ const c = parseRgb(color);
1152
+ if (!c) return color;
1153
+ return `rgba(${c.r},${c.g},${c.b},${alpha})`;
1154
+ }
1155
+ function mix(base, top, alpha) {
1156
+ const b = parseRgb(base);
1157
+ const t = parseRgb(top);
1158
+ if (!b || !t) return base;
1159
+ const c = (x, y) => Math.round(x + (y - x) * alpha);
1160
+ return `rgb(${c(b.r, t.r)},${c(b.g, t.g)},${c(b.b, t.b)})`;
1161
+ }
1162
+ function toHex6(color, fallback = "#888888") {
1163
+ const c = parseRgb(color);
1164
+ if (!c) return fallback;
1165
+ const h = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
1166
+ return `#${h(c.r)}${h(c.g)}${h(c.b)}`;
1167
+ }
1168
+ function isDarkColor(color) {
1169
+ const c = parseRgb(color);
1170
+ if (!c) return true;
1171
+ return 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b < 128;
1172
+ }
1173
+
1174
+ // src/ui/styles.ts
1175
+ function overlayScrollbarCss(selector, width = 8) {
1176
+ return `${selector}::-webkit-scrollbar{width:${width}px;height:${width}px;}${selector}::-webkit-scrollbar-thumb{background:var(--vela-scroll);border-radius:4px;border:2px solid transparent;background-clip:padding-box;}${selector}::-webkit-scrollbar-track{background:transparent;}${selector}::-webkit-scrollbar-button{display:none;width:0;height:0;}`;
1177
+ }
1178
+ var FIELD_FOCUS_CSS = "outline:none;transition:border-color .12s ease,box-shadow .12s ease;";
1179
+ var FIELD_FOCUS_RING = "border-color:var(--vela-focus);box-shadow:0 0 0 3px var(--vela-focus-soft);";
1180
+ function injectStyles(id, css, root = document) {
1181
+ if (typeof document === "undefined") return;
1182
+ const host = root instanceof Document ? root.head : root;
1183
+ if (root.getElementById?.(id) ?? host.querySelector(`#${CSS.escape(id)}`)) return;
1184
+ const s = document.createElement("style");
1185
+ s.id = id;
1186
+ s.textContent = css;
1187
+ host.appendChild(s);
1188
+ }
1189
+
1190
+ // src/ui/icons.ts
1191
+ function iconEl(id, doc = document) {
1192
+ const span = doc.createElement("span");
1193
+ span.className = "vela-icon";
1194
+ span.setAttribute("aria-hidden", "true");
1195
+ const svg = iconMarkup(id);
1196
+ if (svg) span.innerHTML = svg;
1197
+ return span;
1198
+ }
1199
+
1200
+ // src/ui/surface-events.ts
1201
+ var SURFACE_OPEN_EVENT = "vela:surface-open";
1202
+ var SURFACE_CLOSE_EVENT = "vela:surface-close";
1203
+ function announceSurface(el, open, kind, trigger = null) {
1204
+ const View = el.ownerDocument.defaultView;
1205
+ if (!View) return;
1206
+ el.dispatchEvent(
1207
+ new View.CustomEvent(open ? SURFACE_OPEN_EVENT : SURFACE_CLOSE_EVENT, { bubbles: true, composed: true, detail: { kind, trigger } })
1208
+ );
1209
+ }
1210
+
1211
+ // src/core/i18n/text.ts
1212
+ var ENGLISH_RUNTIME = {
1213
+ locale: "en",
1214
+ formatNumber: (value, style) => formatMessageNumber(value, ENGLISH_SETTINGS, style)
1215
+ };
1216
+ function sourceText(message, values) {
1217
+ if (message == null) return "";
1218
+ if (typeof message === "string") return message;
1219
+ if (!isMessageDescriptor(message)) return String(message);
1220
+ const bound = message.values;
1221
+ const all = resolveArgs(bound ? values ? { ...bound, ...values } : bound : values, (m) => sourceText(m));
1222
+ try {
1223
+ return formatMessage(message.defaultMessage, all, ENGLISH_RUNTIME);
1224
+ } catch {
1225
+ return message.defaultMessage;
1226
+ }
1227
+ }
1228
+ function textOf(i18n, message, values) {
1229
+ return (i18n ?? englishTranslator()).t(message, values);
1230
+ }
1231
+ function upperCase(text, locale) {
1232
+ try {
1233
+ return text.toLocaleUpperCase(locale);
1234
+ } catch {
1235
+ return text.toUpperCase();
1236
+ }
1237
+ }
1238
+ function localizeNumberText(text, i18n) {
1239
+ return localizeAscii(text, formatSettingsOf(i18n));
1240
+ }
1241
+ function eventTimeText(ms, i18n) {
1242
+ if (!i18n || i18n instanceof LocaleState && !i18n.localeExplicit) return new Date(ms).toLocaleTimeString();
1243
+ let timeZone;
1244
+ try {
1245
+ timeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
1246
+ } catch {
1247
+ timeZone = void 0;
1248
+ }
1249
+ return i18n.format.clock(ms, { surface: "clock", ...timeZone ? { timeZone } : {} });
1250
+ }
1251
+ function sliceGraphemes(text, count) {
1252
+ if (count <= 0) return "";
1253
+ if (/^[ -~]*$/.test(text)) return text.slice(0, count);
1254
+ const graphemes = textSegmenter(void 0, "grapheme");
1255
+ if (graphemes) {
1256
+ let out = "";
1257
+ let n = 0;
1258
+ for (const { segment } of graphemes.segment(text)) {
1259
+ if (n++ >= count) break;
1260
+ out += segment;
1261
+ }
1262
+ return out;
1263
+ }
1264
+ return Array.from(text).slice(0, count).join("");
1265
+ }
1266
+ var segmenters = /* @__PURE__ */ new Map();
1267
+ function textSegmenter(locale, granularity) {
1268
+ const key = `${locale ?? ""}|${granularity}`;
1269
+ let s = segmenters.get(key);
1270
+ if (s === void 0) {
1271
+ const Ctor = Intl.Segmenter;
1272
+ try {
1273
+ s = Ctor ? new Ctor(locale, { granularity }) : null;
1274
+ } catch {
1275
+ s = null;
1276
+ }
1277
+ segmenters.set(key, s);
1278
+ }
1279
+ return s;
1280
+ }
1281
+
1282
+ // src/ui/surface-exit.ts
1283
+ var CLOSING_ATTR = "data-closing";
1284
+ var SURFACE_EXIT_CAP_MS = 1e3;
1285
+ function animationsOf(els) {
1286
+ return els.flatMap((el) => el.getAnimations({ subtree: true }));
1287
+ }
1288
+ function ends(a) {
1289
+ return Number.isFinite(a.effect?.getComputedTiming().endTime ?? Number.POSITIVE_INFINITY);
1290
+ }
1291
+ function holdForExit(els, done, opts = {}) {
1292
+ const list = Array.isArray(els) ? els : [els];
1293
+ if (list.length === 0 || !list.every((el) => typeof el.getAnimations === "function")) {
1294
+ done();
1295
+ return null;
1296
+ }
1297
+ const before = new Set(animationsOf(list));
1298
+ for (const el of list) el.setAttribute(CLOSING_ATTR, "");
1299
+ const exit = animationsOf(list).filter((a) => !before.has(a) && ends(a));
1300
+ if (exit.length === 0) {
1301
+ for (const el of list) el.removeAttribute(CLOSING_ATTR);
1302
+ done();
1303
+ return null;
1304
+ }
1305
+ const frozen = [...list, ...opts.inert ?? []];
1306
+ const wasInert = frozen.map((el) => el.inert);
1307
+ for (const el of frozen) el.inert = true;
1308
+ let settled = false;
1309
+ const settle = (complete) => {
1310
+ if (settled) return;
1311
+ settled = true;
1312
+ clearTimeout(cap);
1313
+ for (const el of list) el.removeAttribute(CLOSING_ATTR);
1314
+ frozen.forEach((el, i) => {
1315
+ el.inert = wasInert[i];
1316
+ });
1317
+ if (complete) done();
1318
+ };
1319
+ const cap = setTimeout(() => settle(true), SURFACE_EXIT_CAP_MS);
1320
+ let pending = exit.length;
1321
+ const one = () => {
1322
+ if (--pending === 0) settle(true);
1323
+ };
1324
+ for (const a of exit) a.finished.then(one, one);
1325
+ return {
1326
+ cancel: () => settle(false),
1327
+ finish: () => settle(true)
1328
+ };
1329
+ }
1330
+
1331
+ export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CHIP_PLATE, CROSSHAIR, ENGLISH_FORMAT, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, HIGHLIGHT, INFO, INVALID, LocaleState, 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, createTranslator, englishTranslator, eventTimeText, formatSettingsOf, holdForExit, icon, iconAt, iconEl, iconMarkup, injectStyles, isDarkColor, localizeNumberText, mix, monthNames, msg, overlayScrollbarCss, pickLocalization, plainInteger, registerIcon, registerLocale, registeredLocales, sliceGraphemes, sourceText, svg16, svg24, svg24Solid, textOf, textSegmenter, toHex6, upperCase, weekdayNames, withAlpha, withValues, yearBeforeMonth, yearLabel, zoneOffsetMs };