@luxalgo/vela 0.8.0 → 0.8.1
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/NOTICE +1 -1
- package/README.md +15 -7
- package/dist/{chunk-QBPUT5SU.js → chunk-ATGTCWHJ.js} +41 -23
- package/dist/{chunk-E3GU6AUI.js → chunk-DBDXKZUF.js} +18 -13
- package/dist/{chunk-KA77UTRF.js → chunk-LMBYEGUR.js} +1 -1
- package/dist/{chunk-2IAETM2I.js → chunk-NELQJCGK.js} +38 -3
- package/dist/index.cjs +78 -25
- package/dist/index.js +2 -2
- package/dist/ui.cjs +38 -3
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +78 -25
- package/dist/vela.global.min.js +51 -58
- package/dist/widget.cjs +93 -35
- package/dist/widget.js +5 -5
- package/dist/workspace.cjs +93 -35
- package/dist/workspace.d.cts +1 -1
- package/dist/workspace.d.ts +1 -1
- package/dist/workspace.js +4 -4
- package/package.json +2 -2
package/NOTICE
CHANGED
package/README.md
CHANGED
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
<
|
|
5
|
+
<a href="https://velacharts.dev">
|
|
6
|
+
<picture>
|
|
7
|
+
<source media="(prefers-color-scheme: dark)" srcset=".github/banner.png">
|
|
8
|
+
<source media="(prefers-color-scheme: light)" srcset=".github/banner-light.png">
|
|
9
|
+
<img src=".github/banner.png" alt="Vela™ by LuxAlgo" width="100%">
|
|
10
|
+
</picture>
|
|
11
|
+
</a>
|
|
12
|
+
|
|
13
|
+
# Vela™
|
|
6
14
|
|
|
7
15
|
<p><strong>Fast, extensible financial charts for the web.</strong><br>
|
|
8
16
|
Headless core · native WebGL2 renderer · batteries-included workspace · plugin SDK</p>
|
|
@@ -12,9 +20,9 @@
|
|
|
12
20
|
[![License][license-img]][license-link]
|
|
13
21
|
|
|
14
22
|
<p>
|
|
15
|
-
<a href="https://
|
|
23
|
+
<a href="https://velacharts.dev">Homepage</a> ·
|
|
16
24
|
<a href="#quick-start">Quick start</a> ·
|
|
17
|
-
<a href="docs/
|
|
25
|
+
<a href="https://docs.luxalgo.com/vela">Documentation</a> ·
|
|
18
26
|
<a href="#extending-plugin-sdk">Plugin SDK</a> ·
|
|
19
27
|
<a href="CHANGELOG.md">Changelog</a> ·
|
|
20
28
|
<a href="#license-and-attribution">License</a>
|
|
@@ -41,7 +49,7 @@ touching the rest.
|
|
|
41
49
|
- **`@luxalgo/vela/workspace`**: the full chart app. One chart or a grid of them under
|
|
42
50
|
one shared topbar (symbol / timeframe / style / indicators), status line, symbol
|
|
43
51
|
watermark, bottom bar (ranges, clock, timezone), object tree, keyboard-first UX
|
|
44
|
-
(type a letter for symbol search, a digit for timeframe entry, `?` for the shortcuts
|
|
52
|
+
(type a letter or `0` for symbol search, a digit 1–9 for timeframe entry, `?` for the shortcuts
|
|
45
53
|
panel), named cells, sync groups, and one persisted state document.
|
|
46
54
|
- **`@luxalgo/vela/ui`**: the component kit the app is built on. Design tokens, overlay
|
|
47
55
|
chrome ([Zag.js](https://zagjs.com) menu/dialog/drawer/tooltip), form primitives, and
|
|
@@ -108,7 +116,7 @@ alongside them.
|
|
|
108
116
|
|
|
109
117
|
Custom scripts still run through pluggable engines. Vela™ **ships none**: install the
|
|
110
118
|
addon for the language you want, or write one against the public `ScriptingEngine` port.
|
|
111
|
-
Pine Script lives in [`@luxalgo/vela-pinets`](https://github.com/LuxAlgo/Vela-pinets)
|
|
119
|
+
Pine Script® lives in [`@luxalgo/vela-pinets`](https://github.com/LuxAlgo/Vela-pinets)
|
|
112
120
|
(`npm i @luxalgo/vela-pinets pinets`), which is **AGPL-3.0** because the PineTS runtime it
|
|
113
121
|
executes is. Vela™ itself stays Apache-2.0 and carries no Pine code:
|
|
114
122
|
|
|
@@ -198,10 +206,10 @@ include it per Apache-2.0 §4(d):
|
|
|
198
206
|
This is the same licensing model used by other popular charting libraries, and we're
|
|
199
207
|
grateful when the watermark stays in a visible spot.
|
|
200
208
|
|
|
201
|
-
No scripting engine ships with this package; the Pine Script addon
|
|
209
|
+
No scripting engine ships with this package; the Pine Script® addon
|
|
202
210
|
(`@luxalgo/vela-pinets`) is AGPL-3.0 and licensed separately (see *Indicators*).
|
|
203
211
|
|
|
204
|
-
[homepage]: https://
|
|
212
|
+
[homepage]: https://velacharts.dev
|
|
205
213
|
|
|
206
214
|
[npm-version-img]: https://img.shields.io/npm/v/%40luxalgo%2Fvela.svg
|
|
207
215
|
[npm-downloads-img]: https://img.shields.io/npm/dm/%40luxalgo%2Fvela.svg
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { deserializeDrawing, chartTypes, rendererLayers, isLineLikeSeries, seriesShownOn, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, Magnifier, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, nativeInstanceChannel, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, DEFAULT_DRAWING_COLOR, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, magnifierTimeframeLabel, lineSegmentIntersection, MAGNIFIER_TIMEFRAME_OPTIONS, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, seriesInScale, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS, stableSeriesId } from './chunk-EZ5FWVLA.js';
|
|
2
|
-
import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-
|
|
2
|
+
import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-NELQJCGK.js';
|
|
3
3
|
import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, INFO, BULLISH, BEARISH, isDarkColor, injectStyles, SERIES_LINE, CHIP_PLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, iconMarkup, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, SLATE, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-BZQM2XO7.js';
|
|
4
4
|
|
|
5
5
|
// src/core/events/EventBus.ts
|
|
@@ -7239,6 +7239,12 @@ var InputController = class {
|
|
|
7239
7239
|
this.lastTapT = 0;
|
|
7240
7240
|
this.lastTapX = 0;
|
|
7241
7241
|
this.lastTapY = 0;
|
|
7242
|
+
// Whether the last two primary presses were claimed by the drawings layer. A double-click
|
|
7243
|
+
// is the last press plus the one before it; a tool-driven click pair must never fall through
|
|
7244
|
+
// to the pane maximize toggle, even when the tool disarmed itself between the two clicks
|
|
7245
|
+
// (a finished placement leaves plain cursor mode for the second click).
|
|
7246
|
+
this.lastPressDrawing = false;
|
|
7247
|
+
this.prevPressDrawing = false;
|
|
7242
7248
|
this.onTouchContextMenu = (e) => {
|
|
7243
7249
|
if (this.touches.size === 0) return;
|
|
7244
7250
|
if (!(e.target instanceof Node) || !this.el?.contains(e.target)) return;
|
|
@@ -7293,19 +7299,24 @@ var InputController = class {
|
|
|
7293
7299
|
this.moved = false;
|
|
7294
7300
|
this.startX = x;
|
|
7295
7301
|
this.startY = y;
|
|
7302
|
+
this.prevPressDrawing = this.lastPressDrawing;
|
|
7303
|
+
this.lastPressDrawing = false;
|
|
7296
7304
|
if (this.deps.drawingsClaim?.(x, y)) {
|
|
7297
7305
|
this.region = "drawing";
|
|
7306
|
+
this.lastPressDrawing = true;
|
|
7298
7307
|
this.deps.drawingsPointerDown?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey);
|
|
7299
7308
|
this.capture(e.pointerId);
|
|
7300
7309
|
return;
|
|
7301
7310
|
}
|
|
7302
7311
|
if (e.shiftKey && this.regionAt(x, y) === "data" && this.deps.drawingsMeasureStart?.(x, y, this.snapMode(e))) {
|
|
7303
7312
|
this.region = "drawing";
|
|
7313
|
+
this.lastPressDrawing = true;
|
|
7304
7314
|
this.capture(e.pointerId);
|
|
7305
7315
|
return;
|
|
7306
7316
|
}
|
|
7307
7317
|
if ((e.ctrlKey || e.metaKey) && this.regionAt(x, y) === "data" && this.deps.drawingsMarqueeStart?.(x, y)) {
|
|
7308
7318
|
this.region = "drawing";
|
|
7319
|
+
this.lastPressDrawing = true;
|
|
7309
7320
|
this.capture(e.pointerId);
|
|
7310
7321
|
return;
|
|
7311
7322
|
}
|
|
@@ -7627,6 +7638,7 @@ var InputController = class {
|
|
|
7627
7638
|
if (region === "price") this.deps.resetPriceScale(x, y);
|
|
7628
7639
|
else if (region === "separator") this.deps.resetPaneSize(y);
|
|
7629
7640
|
else if (region === "time") this.deps.resetView();
|
|
7641
|
+
else if (this.lastPressDrawing || this.prevPressDrawing) return;
|
|
7630
7642
|
else this.deps.dataDblClick(x, y);
|
|
7631
7643
|
}
|
|
7632
7644
|
};
|
|
@@ -9828,6 +9840,7 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
9828
9840
|
const step = pickStep(span / Math.max(1, target));
|
|
9829
9841
|
const zFrom = fromMs + offsetMs;
|
|
9830
9842
|
const zTo = toMs + offsetMs;
|
|
9843
|
+
if (step >= MONTH) return calendarTicks(zFrom, zTo, step >= YEAR ? 12 : step >= 3 * MONTH ? 3 : 1, offsetMs);
|
|
9831
9844
|
const first = Math.ceil(zFrom / step) * step;
|
|
9832
9845
|
const out = [];
|
|
9833
9846
|
for (let zt = first; zt <= zTo; zt += step) {
|
|
@@ -9858,6 +9871,18 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
9858
9871
|
}
|
|
9859
9872
|
return out;
|
|
9860
9873
|
}
|
|
9874
|
+
function calendarTicks(zFrom, zTo, months, offsetMs) {
|
|
9875
|
+
const d0 = new Date(zFrom);
|
|
9876
|
+
let idx = d0.getUTCFullYear() * 12 + d0.getUTCMonth();
|
|
9877
|
+
if (Date.UTC(Math.floor(idx / 12), idx % 12, 1) < zFrom) idx += 1;
|
|
9878
|
+
idx = Math.ceil(idx / months) * months;
|
|
9879
|
+
const out = [];
|
|
9880
|
+
for (let zt = Date.UTC(Math.floor(idx / 12), idx % 12, 1); zt <= zTo; idx += months, zt = Date.UTC(Math.floor(idx / 12), idx % 12, 1)) {
|
|
9881
|
+
const label = months === 12 ? String(Math.floor(idx / 12)) : MONTHS[idx % 12];
|
|
9882
|
+
out.push({ time: zt - offsetMs, label, major: true });
|
|
9883
|
+
}
|
|
9884
|
+
return out;
|
|
9885
|
+
}
|
|
9861
9886
|
|
|
9862
9887
|
// src/renderers/native/chrome/countdown.ts
|
|
9863
9888
|
function countdownText(barOpen, barMs, now2) {
|
|
@@ -17667,23 +17692,21 @@ function stackLayers(entries, candleZ) {
|
|
|
17667
17692
|
return { below, above };
|
|
17668
17693
|
}
|
|
17669
17694
|
|
|
17670
|
-
// src/renderers/native/chrome/
|
|
17671
|
-
var
|
|
17672
|
-
var
|
|
17695
|
+
// src/renderers/native/chrome/vela-logos.ts
|
|
17696
|
+
var VELA_MARK_SVG = '<svg viewBox="0 -142 161.66 148" aria-hidden="true"><g fill="currentColor"><path d="M0 -140L32.91 -140L77.52 -62.73L61.06 -34.24Z"/><path d="M161.66 -140L128.75 -140L84.14 -62.73L100.59 -34.24Z"/><path d="M80.83 -52.04L95.85 -26.02L80.83 0L65.81 -26.02Z"/></g></svg>';
|
|
17697
|
+
var VELA_LETTERS_SVG = '<svg viewBox="161.66 -142 310.57 148" aria-hidden="true"><g fill="currentColor"><path d="M226.3 1.17Q200.81 1.17 186.12 -12.99Q171.42 -27.15 171.42 -51.17Q171.42 -75.2 185.87 -89.6Q200.33 -104 224.25 -104Q247.4 -104 261.7 -90.58Q276.01 -77.15 276.3 -54.59Q276.3 -49.9 275.42 -45.02H200.81V-43.55Q201.2 -32.62 207.75 -26.42Q214.29 -20.21 225.03 -20.21Q233.72 -20.21 239.34 -23.93Q244.95 -27.64 246.81 -34.77H274.64Q272.1 -19.14 259.16 -8.98Q246.22 1.17 226.3 1.17ZM201.5 -63.38H247.88Q246.42 -72.75 240.27 -77.88Q234.12 -83.01 224.45 -83.01Q215.17 -83.01 208.92 -77.73Q202.67 -72.46 201.5 -63.38ZM287.54 0V-140.04H315.76V0ZM429.34 -23.83H432.56V0H418.11Q407.76 0 403.36 -4.44Q398.97 -8.89 399.16 -16.8Q387.83 1.17 365.57 1.17Q348.48 1.17 337.88 -6.74Q327.29 -14.65 327.29 -29Q327.29 -45.41 339.45 -54.3Q351.6 -63.18 374.55 -63.18H394.96V-68.16Q394.96 -75.2 390.08 -79.3Q385.2 -83.4 376.51 -83.4Q368.3 -83.4 363.03 -79.98Q357.76 -76.56 356.88 -70.8H329.73Q331.19 -85.84 344.08 -94.92Q356.97 -104 377.29 -104Q399.06 -104 410.88 -94.43Q422.7 -84.86 422.7 -66.6V-30.18Q422.7 -26.37 424.26 -25.1Q425.82 -23.83 429.34 -23.83ZM394.96 -42.38V-44.43H374.36Q365.47 -44.43 360.59 -40.92Q355.7 -37.4 355.7 -30.96Q355.7 -25.59 359.81 -22.41Q363.91 -19.24 370.94 -19.24Q381.97 -19.24 388.37 -25.54Q394.77 -31.84 394.96 -42.38Z"/><path fill-opacity="0.55" d="M437.44 -124.28H441.96V-113.41H445.34V-124.28H449.87V-127.4H437.44ZM451.43 -113.41H454.7V-123.29L458.97 -113.41H461.62L465.99 -123.29V-113.41H469.21V-127.4H464.53L460.42 -117.68L456.16 -127.4H451.43Z"/></g></svg>';
|
|
17673
17698
|
|
|
17674
17699
|
// src/renderers/native/chrome/AttributionMark.ts
|
|
17675
|
-
var ATTRIBUTION_URL = "https://
|
|
17700
|
+
var ATTRIBUTION_URL = "https://velacharts.dev/?utm_source=vela&utm_medium=attribution";
|
|
17676
17701
|
var STYLE_ID5 = "vela-attribution-styles";
|
|
17677
17702
|
var CSS = `
|
|
17678
17703
|
.vela-attribution {
|
|
17679
17704
|
text-decoration: none;
|
|
17680
17705
|
display: flex;
|
|
17681
17706
|
align-items: center;
|
|
17682
|
-
/*
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
reads wrong because the symbol's ink hangs low and the wordmark descends. */
|
|
17686
|
-
gap: 4px;
|
|
17707
|
+
/* No gutter: the V is the wordmark's first letter, and the letters' viewBox starts
|
|
17708
|
+
where the V's ends, so the kit's own letter spacing comes with them. */
|
|
17709
|
+
gap: 0;
|
|
17687
17710
|
}
|
|
17688
17711
|
.vela-attribution .vela-attr-symbol {
|
|
17689
17712
|
flex: none;
|
|
@@ -17691,7 +17714,7 @@ var CSS = `
|
|
|
17691
17714
|
line-height: 0;
|
|
17692
17715
|
}
|
|
17693
17716
|
.vela-attribution .vela-attr-symbol svg {
|
|
17694
|
-
height:
|
|
17717
|
+
height: 24px;
|
|
17695
17718
|
width: auto;
|
|
17696
17719
|
display: block;
|
|
17697
17720
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -17702,15 +17725,13 @@ var CSS = `
|
|
|
17702
17725
|
opacity: 0;
|
|
17703
17726
|
display: flex;
|
|
17704
17727
|
align-items: center;
|
|
17705
|
-
/*
|
|
17706
|
-
position: relative;
|
|
17707
|
-
top: 3px;
|
|
17728
|
+
/* Same height and baseline as the V (one viewBox height), so no vertical offset. */
|
|
17708
17729
|
transform: translateX(-8px);
|
|
17709
17730
|
transition: max-width 0.3s ease, opacity 0.25s ease, transform 0.3s ease;
|
|
17710
17731
|
flex: none;
|
|
17711
17732
|
}
|
|
17712
17733
|
.vela-attribution .vela-attr-wordmark svg {
|
|
17713
|
-
height:
|
|
17734
|
+
height: 24px;
|
|
17714
17735
|
width: auto;
|
|
17715
17736
|
display: block;
|
|
17716
17737
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -17725,14 +17746,11 @@ var CSS = `
|
|
|
17725
17746
|
(data-layout): the workspace's single grid-wide mark lives OUTSIDE any renderer
|
|
17726
17747
|
container, so only the shell attribute reaches it. */
|
|
17727
17748
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-symbol svg,
|
|
17728
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height:
|
|
17749
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height: 20px; }
|
|
17729
17750
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark,
|
|
17730
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark {
|
|
17731
|
-
top: 2px;
|
|
17732
|
-
transform: translateX(-6px);
|
|
17733
|
-
}
|
|
17751
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark { transform: translateX(-6px); }
|
|
17734
17752
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark svg,
|
|
17735
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height:
|
|
17753
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height: 20px; }
|
|
17736
17754
|
[data-vela-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark,
|
|
17737
17755
|
[data-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark { transform: translateX(0); }
|
|
17738
17756
|
`;
|
|
@@ -17789,10 +17807,10 @@ function createAttributionMark(doc, background) {
|
|
|
17789
17807
|
const symbol = doc.createElement("span");
|
|
17790
17808
|
symbol.className = "vela-attr-symbol";
|
|
17791
17809
|
symbol.setAttribute("aria-hidden", "true");
|
|
17792
|
-
symbol.innerHTML =
|
|
17810
|
+
symbol.innerHTML = VELA_MARK_SVG;
|
|
17793
17811
|
const wordmark = doc.createElement("span");
|
|
17794
17812
|
wordmark.className = "vela-attr-wordmark";
|
|
17795
|
-
wordmark.innerHTML =
|
|
17813
|
+
wordmark.innerHTML = VELA_LETTERS_SVG;
|
|
17796
17814
|
a.append(symbol, wordmark);
|
|
17797
17815
|
return a;
|
|
17798
17816
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore } from './chunk-
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, SecondClock, resolveTimezone, timezoneMenuRows, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, normalizeTimezone, isExchangeTimezone, TypedEventBus, timeframeToMs, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore } from './chunk-ATGTCWHJ.js';
|
|
2
2
|
import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, mobilePlacement, widgetAttachments, getDrawingType, inputDeltas } from './chunk-EZ5FWVLA.js';
|
|
3
|
-
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-
|
|
4
|
-
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-
|
|
3
|
+
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-LMBYEGUR.js';
|
|
4
|
+
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-NELQJCGK.js';
|
|
5
5
|
import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-BZQM2XO7.js';
|
|
6
6
|
import { baseOf } from './chunk-W4EJWLEO.js';
|
|
7
7
|
|
|
@@ -3652,7 +3652,12 @@ var TimeframeQuick = class {
|
|
|
3652
3652
|
content: (body) => body.append(this.input, this.hint),
|
|
3653
3653
|
onOpenChange: (open) => opts.onOpenChange?.(open)
|
|
3654
3654
|
});
|
|
3655
|
-
this.input.addEventListener("input", () =>
|
|
3655
|
+
this.input.addEventListener("input", () => {
|
|
3656
|
+
const { selectionStart, selectionEnd } = this.input;
|
|
3657
|
+
this.input.value = this.input.value.toUpperCase();
|
|
3658
|
+
this.input.setSelectionRange(selectionStart, selectionEnd);
|
|
3659
|
+
this.renderHint();
|
|
3660
|
+
});
|
|
3656
3661
|
this.input.addEventListener("keydown", (e) => {
|
|
3657
3662
|
if (e.key !== "Enter") return;
|
|
3658
3663
|
const parsed = parseTimeframe(this.input.value);
|
|
@@ -3664,7 +3669,7 @@ var TimeframeQuick = class {
|
|
|
3664
3669
|
}
|
|
3665
3670
|
open(seed = "") {
|
|
3666
3671
|
this.dialog.show();
|
|
3667
|
-
this.input.value = seed;
|
|
3672
|
+
this.input.value = seed.toUpperCase();
|
|
3668
3673
|
this.renderHint();
|
|
3669
3674
|
setTimeout(() => {
|
|
3670
3675
|
this.input.focus();
|
|
@@ -3682,7 +3687,7 @@ var TimeframeQuick = class {
|
|
|
3682
3687
|
this.open(text);
|
|
3683
3688
|
return;
|
|
3684
3689
|
}
|
|
3685
|
-
this.input.value += text;
|
|
3690
|
+
this.input.value += text.toUpperCase();
|
|
3686
3691
|
this.renderHint();
|
|
3687
3692
|
}
|
|
3688
3693
|
close() {
|
|
@@ -3695,7 +3700,7 @@ var TimeframeQuick = class {
|
|
|
3695
3700
|
const raw = this.input.value.trim();
|
|
3696
3701
|
const parsed = parseTimeframe(raw);
|
|
3697
3702
|
if (!raw) {
|
|
3698
|
-
this.hint.textContent = "e.g. 15,
|
|
3703
|
+
this.hint.textContent = "e.g. 15, 4H, D, 3M";
|
|
3699
3704
|
delete this.hint.dataset.invalid;
|
|
3700
3705
|
} else if (parsed.valid) {
|
|
3701
3706
|
this.hint.textContent = parsed.label ?? "";
|
|
@@ -3798,7 +3803,7 @@ var ShortcutsHelp = class {
|
|
|
3798
3803
|
addRow("Delete the drawing under the cursor", ["Middle-click"]);
|
|
3799
3804
|
const s = doc.createElement("div");
|
|
3800
3805
|
s.className = "vela-sh-static";
|
|
3801
|
-
s.textContent = "Typing a letter opens the symbol search; typing a digit opens the timeframe entry.";
|
|
3806
|
+
s.textContent = "Typing a letter or 0 opens the symbol search; typing a digit from 1 to 9 opens the timeframe entry.";
|
|
3802
3807
|
this.list.appendChild(s);
|
|
3803
3808
|
}
|
|
3804
3809
|
};
|
|
@@ -6424,7 +6429,7 @@ var ChartCell = class {
|
|
|
6424
6429
|
* then the manifest in the host's own order. */
|
|
6425
6430
|
libraryRows() {
|
|
6426
6431
|
return [
|
|
6427
|
-
...this.supportedNatives().map((n) => ({ name: n.title, category: "
|
|
6432
|
+
...this.supportedNatives().map((n) => ({ name: n.title, category: "Built-in", native: true, nativeType: n.type, beta: n.beta })),
|
|
6428
6433
|
...this.manifest.map((e) => ({ name: e.name, language: e.language, category: e.category }))
|
|
6429
6434
|
];
|
|
6430
6435
|
}
|
|
@@ -8676,11 +8681,11 @@ function resolveTyping(key, open) {
|
|
|
8676
8681
|
if (open.dialogs > 0) {
|
|
8677
8682
|
if (key.length !== 1) return null;
|
|
8678
8683
|
if (open.symbolSearch) return { target: "symbol", text: key.toUpperCase() };
|
|
8679
|
-
if (open.timeframeEntry) return { target: "timeframe", text: key };
|
|
8684
|
+
if (open.timeframeEntry) return { target: "timeframe", text: key.toUpperCase() };
|
|
8680
8685
|
return null;
|
|
8681
8686
|
}
|
|
8682
|
-
if (/^[a-zA-
|
|
8683
|
-
if (/^[
|
|
8687
|
+
if (/^[a-zA-Z0]$/.test(key)) return { target: "symbol", text: key.toUpperCase() };
|
|
8688
|
+
if (/^[1-9]$/.test(key)) return { target: "timeframe", text: key };
|
|
8684
8689
|
return null;
|
|
8685
8690
|
}
|
|
8686
8691
|
var VelaWorkspace = class {
|
|
@@ -10418,7 +10423,7 @@ var VelaWorkspace = class {
|
|
|
10418
10423
|
}
|
|
10419
10424
|
});
|
|
10420
10425
|
}
|
|
10421
|
-
/** Bare-typing router: letters → symbol search (seeded), digits → timeframe entry. */
|
|
10426
|
+
/** Bare-typing router: letters and `0` → symbol search (seeded), digits 1–9 → timeframe entry. */
|
|
10422
10427
|
routeTyping(ev) {
|
|
10423
10428
|
if (this.destroyed) return;
|
|
10424
10429
|
if (ev.ctrlKey || ev.metaKey || ev.altKey) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-
|
|
1
|
+
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-NELQJCGK.js';
|
|
2
2
|
import { injectStyles } from './chunk-BZQM2XO7.js';
|
|
3
3
|
import * as tooltip from '@zag-js/tooltip';
|
|
4
4
|
import * as dialog from '@zag-js/dialog';
|
|
@@ -2506,14 +2506,49 @@ function buildColorPicker(color, theme, onChange, options = {}) {
|
|
|
2506
2506
|
const knob = document.createElement("div");
|
|
2507
2507
|
knob.style.cssText = "position:absolute;top:50%;width:15px;height:15px;border-radius:50%;background:var(--vela-selected-bg);box-shadow:0 1px 3px rgba(0,0,0,0.55);transform:translate(-50%,-50%);pointer-events:none;";
|
|
2508
2508
|
track.appendChild(knob);
|
|
2509
|
-
const pctBox = document.createElement("
|
|
2510
|
-
pctBox.
|
|
2509
|
+
const pctBox = document.createElement("input");
|
|
2510
|
+
pctBox.type = "text";
|
|
2511
|
+
pctBox.inputMode = "numeric";
|
|
2512
|
+
pctBox.title = "Opacity (%)";
|
|
2513
|
+
pctBox.style.cssText = `width:46px;box-sizing:border-box;text-align:center;font:var(--vela-font-size-md) ${theme.fontFamily};color:var(--vela-fg);background:transparent;border:1px solid var(--vela-border);border-radius:5px;padding:3px 4px;outline:none;`;
|
|
2514
|
+
pctBox.addEventListener("focus", () => {
|
|
2515
|
+
pctBox.style.borderColor = "var(--vela-border-strong)";
|
|
2516
|
+
pctBox.select();
|
|
2517
|
+
});
|
|
2511
2518
|
opRow.append(track, pctBox);
|
|
2512
2519
|
const paintOpacity = () => {
|
|
2513
2520
|
track.style.background = `linear-gradient(to right, ${curHex}00, ${curHex}ff), ${CHECKER}`;
|
|
2514
2521
|
knob.style.left = `${curAlpha * 100}%`;
|
|
2515
|
-
pctBox.
|
|
2522
|
+
pctBox.value = `${Math.round(curAlpha * 100)}%`;
|
|
2523
|
+
};
|
|
2524
|
+
const commitTyped = () => {
|
|
2525
|
+
pctBox.style.borderColor = "var(--vela-border)";
|
|
2526
|
+
const n = parseFloat(pctBox.value.replace("%", ""));
|
|
2527
|
+
if (Number.isFinite(n)) {
|
|
2528
|
+
const next = Math.max(0, Math.min(100, n)) / 100;
|
|
2529
|
+
if (Math.round(next * 100) !== Math.round(curAlpha * 100)) {
|
|
2530
|
+
curAlpha = next;
|
|
2531
|
+
paintOpacity();
|
|
2532
|
+
emit();
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
paintOpacity();
|
|
2516
2537
|
};
|
|
2538
|
+
pctBox.addEventListener("change", commitTyped);
|
|
2539
|
+
pctBox.addEventListener("blur", () => {
|
|
2540
|
+
pctBox.style.borderColor = "var(--vela-border)";
|
|
2541
|
+
paintOpacity();
|
|
2542
|
+
});
|
|
2543
|
+
pctBox.addEventListener("keydown", (e) => {
|
|
2544
|
+
if (e.key === "Escape") return;
|
|
2545
|
+
e.stopPropagation();
|
|
2546
|
+
if (e.key === "Enter") {
|
|
2547
|
+
e.preventDefault();
|
|
2548
|
+
commitTyped();
|
|
2549
|
+
pctBox.blur();
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2517
2552
|
let dragging = false;
|
|
2518
2553
|
const onDrag = (clientX) => {
|
|
2519
2554
|
const r = track.getBoundingClientRect();
|