@luxalgo/vela 0.6.13 → 0.6.15
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 +28 -28
- package/README.md +1 -1
- package/dist/{DataProvider-DhzstpQb.d.ts → DataProvider-XLdJB86x.d.ts} +1 -1
- package/dist/{DataProvider-DlMtrwqM.d.cts → DataProvider-xH2VBcFT.d.cts} +1 -1
- package/dist/{chunk-F4M24ANM.js → chunk-32A7KHFM.js} +73 -3
- package/dist/{chunk-KG4YT3TI.js → chunk-6DPAYEGO.js} +8 -1
- package/dist/{chunk-G52XAKZY.js → chunk-7C7NWEXH.js} +345 -148
- package/dist/{chunk-JKGA36ZM.js → chunk-J5QIR2Z3.js} +165 -130
- package/dist/{chunk-MHY7MVXH.js → chunk-MWDNPGU3.js} +7 -1
- package/dist/{chunk-G77Y7LK2.js → chunk-MWS4CUJL.js} +2 -2
- package/dist/{contributions-37nni40G.d.ts → contributions-h5BzEiV2.d.ts} +13 -2
- package/dist/{contributions-lPojhTxI.d.cts → contributions-x7iamlnd.d.cts} +13 -2
- package/dist/index.cjs +176 -127
- package/dist/index.d.cts +20 -12
- package/dist/index.d.ts +20 -12
- package/dist/index.js +4 -4
- package/dist/{options-CYS5Wmlx.d.ts → options-bdSAtp7y.d.cts} +5 -0
- package/dist/{options-CYS5Wmlx.d.cts → options-bdSAtp7y.d.ts} +5 -0
- package/dist/{plugin-Cwikpz1m.d.cts → plugin-2sJcf5mk.d.cts} +11 -8
- package/dist/{plugin-DHyaoMjW.d.ts → plugin-BLaNPh55.d.ts} +11 -8
- package/dist/plugin.cjs +8 -0
- package/dist/plugin.d.cts +5 -5
- package/dist/plugin.d.ts +5 -5
- package/dist/plugin.js +2 -2
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/{side-panel-CT9ZwIGz.d.cts → side-panel-HF0IAzwf.d.cts} +17 -0
- package/dist/{side-panel-CT9ZwIGz.d.ts → side-panel-HF0IAzwf.d.ts} +17 -0
- package/dist/{statusline-model-D-q_OOx9.d.ts → statusline-model--tH0VWCy.d.cts} +6 -4
- package/dist/{statusline-model-CiJm-riV.d.cts → statusline-model-CLpaO3Dl.d.ts} +6 -4
- package/dist/ui.cjs +12 -0
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +176 -127
- package/dist/vela.global.min.js +52 -46
- package/dist/widget.cjs +587 -272
- package/dist/widget.d.cts +15 -11
- package/dist/widget.d.ts +15 -11
- package/dist/widget.js +7 -7
- package/dist/workspace.cjs +587 -272
- package/dist/workspace.d.cts +29 -10
- package/dist/workspace.d.ts +29 -10
- package/dist/workspace.js +6 -6
- package/package.json +1 -1
package/dist/ui.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { Drawer, KeymapManager, Tooltip, drawerController, tooltipController } from './chunk-
|
|
2
|
-
export { CALLOUT_CSS, CALLOUT_STYLE_ID, CalloutBubble, ColorField, Dialog, FIELD_GAP_PX, GlyphSelect, Menu, NumberInput, Popover, Select, Switch, TextArea, TextField, WIDTH_FIELD_OPTIONS, applyPlotOverlayTokens, applyThemeTokens, blendOver, buildColorPicker, buildFieldControl, buildPalette, calloutPanelRows, clampNumber, closeColorPopover, closeOpenPopovers, closeWidthPopover, closesPanel, colorField, colorPickerController, combineColor, decorateSelectScroll, dialogController, ensureUIHost, eventDismissedPopover, fieldGrid, fieldGridColumns, fieldRow, fieldSection, fieldSeparator, fillSelectList, glyphSelectController, hslHex, insetRect, intersectRects, isPopoverOpen, lineWidthGlyph, menuController, nextUid, normalizeProps, numberInputController, openPopoverTrigger, openSelectList, placePopover, popoverController, runMachine, selectController, snapToStep, splitColor, spreadProps, switchController, textAreaController, textFieldController, toggleSelectList, transparencyChecker, viewportRect, widthField, widthFieldOptions } from './chunk-
|
|
3
|
-
export { FIELD_FOCUS_CSS, FIELD_FOCUS_RING, iconEl, iconMarkup, injectStyles, overlayScrollbarCss, registerIcon, svg16, svg24, withAlpha } from './chunk-
|
|
1
|
+
export { Drawer, KeymapManager, Tooltip, drawerController, tooltipController } from './chunk-MWS4CUJL.js';
|
|
2
|
+
export { CALLOUT_CSS, CALLOUT_STYLE_ID, CalloutBubble, ColorField, Dialog, FIELD_GAP_PX, GlyphSelect, Menu, NumberInput, Popover, Select, Switch, TextArea, TextField, WIDTH_FIELD_OPTIONS, applyPlotOverlayTokens, applyThemeTokens, blendOver, buildColorPicker, buildFieldControl, buildPalette, calloutPanelRows, clampNumber, closeColorPopover, closeOpenPopovers, closeWidthPopover, closesPanel, colorField, colorPickerController, combineColor, decorateSelectScroll, dialogController, ensureUIHost, eventDismissedPopover, fieldGrid, fieldGridColumns, fieldRow, fieldSection, fieldSeparator, fillSelectList, glyphSelectController, hslHex, insetRect, intersectRects, isPopoverOpen, lineWidthGlyph, menuController, nextUid, normalizeProps, numberInputController, openPopoverTrigger, openSelectList, placePopover, popoverController, runMachine, selectController, snapToStep, splitColor, spreadProps, switchController, textAreaController, textFieldController, toggleSelectList, transparencyChecker, viewportRect, widthField, widthFieldOptions } from './chunk-MWDNPGU3.js';
|
|
3
|
+
export { FIELD_FOCUS_CSS, FIELD_FOCUS_RING, iconEl, iconMarkup, injectStyles, overlayScrollbarCss, registerIcon, svg16, svg24, withAlpha } from './chunk-6DPAYEGO.js';
|
package/dist/vela.global.js
CHANGED
|
@@ -276,6 +276,7 @@ var Vela = (function (exports) {
|
|
|
276
276
|
var CROSSHAIR = "#9aa0ad";
|
|
277
277
|
var SLATE_DEEP = "#1e293b";
|
|
278
278
|
var SLATE = "#475569";
|
|
279
|
+
var CHIP_PLATE = "#595959";
|
|
279
280
|
var TRADE_LONG = ACCENT;
|
|
280
281
|
var TRADE_SHORT = BEARISH;
|
|
281
282
|
var TRADE_EXIT = "#d500f9";
|
|
@@ -503,6 +504,10 @@ var Vela = (function (exports) {
|
|
|
503
504
|
"market-post",
|
|
504
505
|
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"/>')
|
|
505
506
|
);
|
|
507
|
+
registerIcon(
|
|
508
|
+
"market-extended",
|
|
509
|
+
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"/>')
|
|
510
|
+
);
|
|
506
511
|
registerIcon("market-closed", svg24('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>'));
|
|
507
512
|
registerIcon(
|
|
508
513
|
"market-holiday",
|
|
@@ -516,6 +521,8 @@ var Vela = (function (exports) {
|
|
|
516
521
|
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"/>'));
|
|
517
522
|
registerIcon("check", S('<path d="m2.8 8.4 3.4 3.4 7-7.6"/>'));
|
|
518
523
|
registerIcon("close", S('<path d="m3.8 3.8 8.4 8.4M12.2 3.8l-8.4 8.4"/>'));
|
|
524
|
+
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"/>'));
|
|
525
|
+
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"/>'));
|
|
519
526
|
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"/>'));
|
|
520
527
|
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"/>'));
|
|
521
528
|
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"/>'));
|
|
@@ -7578,6 +7585,7 @@ var Vela = (function (exports) {
|
|
|
7578
7585
|
var PREVIEW_BARS = 300;
|
|
7579
7586
|
var SINGLE_LOAD_BARS = 5e3;
|
|
7580
7587
|
var CHUNK_BARS = 1e4;
|
|
7588
|
+
var FIRST_PAINT_BARS = 20;
|
|
7581
7589
|
var GAP_FACTOR = 1.5;
|
|
7582
7590
|
var HEAL_COOLDOWN_MS = 5e3;
|
|
7583
7591
|
var EngineOrchestrator = class _EngineOrchestrator {
|
|
@@ -7853,6 +7861,7 @@ var Vela = (function (exports) {
|
|
|
7853
7861
|
let painted = false;
|
|
7854
7862
|
const paint = (bars, final) => {
|
|
7855
7863
|
if (this.generation !== gen || !final && bars.length === 0) return;
|
|
7864
|
+
if (!painted && !final && bars.length < Math.min(requested, FIRST_PAINT_BARS)) return;
|
|
7856
7865
|
this.setBarSeries(bars, painted ? { preserveView: true } : void 0);
|
|
7857
7866
|
if (!painted && bars.length > 0) {
|
|
7858
7867
|
painted = true;
|
|
@@ -9270,6 +9279,15 @@ var Vela = (function (exports) {
|
|
|
9270
9279
|
console.warn(`[vela] renderer "${this.renderer.name}" does not support screenshot().`);
|
|
9271
9280
|
return null;
|
|
9272
9281
|
}
|
|
9282
|
+
/**
|
|
9283
|
+
* Raster of the current chart onto a canvas (same pixels as {@link screenshot}),
|
|
9284
|
+
* or null if the renderer has no canvas export. Silent — a host compositing
|
|
9285
|
+
* several charts skips a renderer that cannot contribute.
|
|
9286
|
+
*/
|
|
9287
|
+
screenshotCanvas() {
|
|
9288
|
+
if (typeof this.renderer.screenshotCanvas === "function") return this.renderer.screenshotCanvas();
|
|
9289
|
+
return null;
|
|
9290
|
+
}
|
|
9273
9291
|
/**
|
|
9274
9292
|
* The active renderer's full cosmetic config as a serializable, versioned JSON
|
|
9275
9293
|
* document — persist it (templates, saved settings) and feed it back to
|
|
@@ -17139,6 +17157,12 @@ ${STATIC_DECLS}
|
|
|
17139
17157
|
.vela-ui *, .vela-ui-layer * { box-sizing: border-box; }
|
|
17140
17158
|
/* Text ENTRY is the one exception: selection is part of editing. */
|
|
17141
17159
|
.vela-ui :is(input, textarea), .vela-ui-layer :is(input, textarea) { user-select: text; -webkit-user-select: text; }
|
|
17160
|
+
/* iOS Safari zooms the page when a focused field is under 16px, and often
|
|
17161
|
+
keeps that zoom after the field blurs or a dialog closes. The shell's
|
|
17162
|
+
mobile size class is the honest gate \u2014 not a media query \u2014 so an embedded
|
|
17163
|
+
chart on a wide desktop still gets the rule when it is in the phone layout.
|
|
17164
|
+
Scoped to the kit root so a host page's own [data-layout] is never touched. */
|
|
17165
|
+
.vela-ui[data-layout='mobile'] :is(input, textarea, select) { font-size: 16px; }
|
|
17142
17166
|
.vela-icon { display: inline-flex; align-items: center; flex: none; }
|
|
17143
17167
|
.vela-icon svg { display: block; }
|
|
17144
17168
|
`;
|
|
@@ -22759,6 +22783,66 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22759
22783
|
center: (wickLeftDev + wickDev / 2) / dpr
|
|
22760
22784
|
};
|
|
22761
22785
|
}
|
|
22786
|
+
function aggregateCandleColumns(bars, i0, i1, xOf, yOf) {
|
|
22787
|
+
const out = [];
|
|
22788
|
+
let col = NaN;
|
|
22789
|
+
let intervals = [];
|
|
22790
|
+
const flush = () => {
|
|
22791
|
+
if (intervals.length === 0) return;
|
|
22792
|
+
const merged = [intervals[0]];
|
|
22793
|
+
for (let k = 1; k < intervals.length; k += 1) {
|
|
22794
|
+
const prev3 = merged[merged.length - 1];
|
|
22795
|
+
const next2 = intervals[k];
|
|
22796
|
+
if (Math.abs(yOf(prev3.hi) - yOf(next2.lo)) < 1) {
|
|
22797
|
+
prev3.hi = next2.hi;
|
|
22798
|
+
if (next2.headIdx < prev3.headIdx) {
|
|
22799
|
+
prev3.headIdx = next2.headIdx;
|
|
22800
|
+
prev3.headTime = next2.headTime;
|
|
22801
|
+
prev3.open = next2.open;
|
|
22802
|
+
}
|
|
22803
|
+
if (next2.lastIdx > prev3.lastIdx) {
|
|
22804
|
+
prev3.lastIdx = next2.lastIdx;
|
|
22805
|
+
prev3.close = next2.close;
|
|
22806
|
+
}
|
|
22807
|
+
} else {
|
|
22808
|
+
merged.push(next2);
|
|
22809
|
+
}
|
|
22810
|
+
}
|
|
22811
|
+
for (const iv of merged) out.push({ x: col, hi: iv.hi, lo: iv.lo, headTime: iv.headTime, open: iv.open, close: iv.close });
|
|
22812
|
+
intervals = [];
|
|
22813
|
+
};
|
|
22814
|
+
for (let i = i0; i <= i1; i += 1) {
|
|
22815
|
+
const b = bars[i];
|
|
22816
|
+
if (!b || b.high <= b.low) continue;
|
|
22817
|
+
const x = Math.round(xOf(i));
|
|
22818
|
+
if (x !== col) {
|
|
22819
|
+
flush();
|
|
22820
|
+
col = x;
|
|
22821
|
+
}
|
|
22822
|
+
let lo = b.low;
|
|
22823
|
+
let hi = b.high;
|
|
22824
|
+
let headIdx = i;
|
|
22825
|
+
let headTime = b.time;
|
|
22826
|
+
let open2 = b.open;
|
|
22827
|
+
for (let k = intervals.length - 1; k >= 0; k -= 1) {
|
|
22828
|
+
const iv = intervals[k];
|
|
22829
|
+
if (iv.lo > hi || iv.hi < lo) continue;
|
|
22830
|
+
if (iv.lo < lo) lo = iv.lo;
|
|
22831
|
+
if (iv.hi > hi) hi = iv.hi;
|
|
22832
|
+
if (iv.headIdx < headIdx) {
|
|
22833
|
+
headIdx = iv.headIdx;
|
|
22834
|
+
headTime = iv.headTime;
|
|
22835
|
+
open2 = iv.open;
|
|
22836
|
+
}
|
|
22837
|
+
intervals.splice(k, 1);
|
|
22838
|
+
}
|
|
22839
|
+
let insertAt = 0;
|
|
22840
|
+
while (insertAt < intervals.length && intervals[insertAt].lo < lo) insertAt += 1;
|
|
22841
|
+
intervals.splice(insertAt, 0, { lo, hi, headIdx, headTime, open: open2, lastIdx: i, close: b.close });
|
|
22842
|
+
}
|
|
22843
|
+
flush();
|
|
22844
|
+
return out;
|
|
22845
|
+
}
|
|
22762
22846
|
|
|
22763
22847
|
// src/renderers/native/core/chartConfig.ts
|
|
22764
22848
|
var CHART_CONFIG_VERSION = 1;
|
|
@@ -22769,6 +22853,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22769
22853
|
var BASELINE_LEVEL_DEFAULT = 50;
|
|
22770
22854
|
var PREMARKET_SHADE = withAlpha(WARNING, 0.08);
|
|
22771
22855
|
var POSTMARKET_SHADE = withAlpha(ACCENT, 0.08);
|
|
22856
|
+
var EXTENDED_SHADE = POSTMARKET_SHADE;
|
|
22772
22857
|
function defaultChartStyle() {
|
|
22773
22858
|
return {
|
|
22774
22859
|
chartTypes: {},
|
|
@@ -22777,7 +22862,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22777
22862
|
gridHorz: { visible: true, color: null },
|
|
22778
22863
|
borderColor: null,
|
|
22779
22864
|
separatorColor: null,
|
|
22780
|
-
crosshair: { color: CROSSHAIR, width: 1, style: "dashed", opacity: 0.4, labelBackground:
|
|
22865
|
+
crosshair: { color: CROSSHAIR, width: 1, style: "dashed", opacity: 0.4, labelBackground: CHIP_PLATE },
|
|
22781
22866
|
candle: {
|
|
22782
22867
|
bodyVisible: true,
|
|
22783
22868
|
borderVisible: false,
|
|
@@ -22800,7 +22885,7 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
22800
22885
|
width: 2,
|
|
22801
22886
|
baselineLevel: BASELINE_LEVEL_DEFAULT
|
|
22802
22887
|
},
|
|
22803
|
-
sessions: { premarketColor: PREMARKET_SHADE, postmarketColor: POSTMARKET_SHADE }
|
|
22888
|
+
sessions: { premarketColor: PREMARKET_SHADE, postmarketColor: POSTMARKET_SHADE, extendedColor: EXTENDED_SHADE }
|
|
22804
22889
|
};
|
|
22805
22890
|
}
|
|
22806
22891
|
var LINE_STYLES = ["solid", "dashed", "dotted"];
|
|
@@ -23029,7 +23114,8 @@ ${overlayScrollbarCss(".vela-dialog.vela-ind-dialog *", 9)}
|
|
|
23029
23114
|
},
|
|
23030
23115
|
sessions: {
|
|
23031
23116
|
premarketColor: isColor(sessions.premarketColor) ? sessions.premarketColor : base.sessions.premarketColor,
|
|
23032
|
-
postmarketColor: isColor(sessions.postmarketColor) ? sessions.postmarketColor : base.sessions.postmarketColor
|
|
23117
|
+
postmarketColor: isColor(sessions.postmarketColor) ? sessions.postmarketColor : base.sessions.postmarketColor,
|
|
23118
|
+
extendedColor: isColor(sessions.extendedColor) ? sessions.extendedColor : base.sessions.extendedColor
|
|
23033
23119
|
},
|
|
23034
23120
|
stacking: {
|
|
23035
23121
|
candles: isNum(stacking.candles) ? stacking.candles : base.stacking.candles,
|
|
@@ -24014,44 +24100,19 @@ void main() {
|
|
|
24014
24100
|
}
|
|
24015
24101
|
}
|
|
24016
24102
|
/**
|
|
24017
|
-
* Sub-pixel LOD (mirrors Canvas2dBackend.drawCandlesAggregated):
|
|
24018
|
-
*
|
|
24019
|
-
*
|
|
24103
|
+
* Sub-pixel LOD (mirrors Canvas2dBackend.drawCandlesAggregated): bars sharing a
|
|
24104
|
+
* rounded pixel column collapse into high-low sticks — one per contiguous
|
|
24105
|
+
* coverage run (see {@link aggregateCandleColumns}), so a price gap inside the
|
|
24106
|
+
* column stays a void. Draw cost stays bounded by screen width, not bar count;
|
|
24107
|
+
* stick color follows its own first-open→last-close.
|
|
24020
24108
|
*/
|
|
24021
24109
|
emitCandlesAggregated(b, bars, i0, i1, coords, pane, up, down, barColors) {
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24025
|
-
|
|
24026
|
-
|
|
24027
|
-
let headTime = 0;
|
|
24028
|
-
let active = false;
|
|
24029
|
-
const flush = () => {
|
|
24030
|
-
if (!active) return;
|
|
24031
|
-
const c = parseColor(barColors.get(headTime) ?? (closeV >= openV ? up : down));
|
|
24032
|
-
const hY = coords.priceToY(hi, pane.scale, pane.bounds);
|
|
24033
|
-
const lY = coords.priceToY(lo, pane.scale, pane.bounds);
|
|
24034
|
-
b.rect(px - 0.5, hY, 1, lY - hY, c);
|
|
24035
|
-
};
|
|
24036
|
-
for (let i = i0; i <= i1; i += 1) {
|
|
24037
|
-
const bar = bars[i];
|
|
24038
|
-
if (!bar || bar.high <= bar.low) continue;
|
|
24039
|
-
const x = Math.round(coords.logicalToX(i));
|
|
24040
|
-
if (!active || x !== px) {
|
|
24041
|
-
flush();
|
|
24042
|
-
px = x;
|
|
24043
|
-
lo = bar.low;
|
|
24044
|
-
hi = bar.high;
|
|
24045
|
-
openV = bar.open;
|
|
24046
|
-
headTime = bar.time;
|
|
24047
|
-
active = true;
|
|
24048
|
-
} else {
|
|
24049
|
-
if (bar.low < lo) lo = bar.low;
|
|
24050
|
-
if (bar.high > hi) hi = bar.high;
|
|
24051
|
-
}
|
|
24052
|
-
closeV = bar.close;
|
|
24110
|
+
const yOf = (price) => coords.priceToY(price, pane.scale, pane.bounds);
|
|
24111
|
+
for (const s of aggregateCandleColumns(bars, i0, i1, (i) => coords.logicalToX(i), yOf)) {
|
|
24112
|
+
const c = parseColor(barColors.get(s.headTime) ?? (s.close >= s.open ? up : down));
|
|
24113
|
+
const hY = yOf(s.hi);
|
|
24114
|
+
b.rect(s.x - 0.5, hY, 1, yOf(s.lo) - hY, c);
|
|
24053
24115
|
}
|
|
24054
|
-
flush();
|
|
24055
24116
|
}
|
|
24056
24117
|
emitSeries(b, spec, pane, coords, i0, i1, theme, off = 0) {
|
|
24057
24118
|
if (spec.kind === "candle" || spec.kind === "bar") {
|
|
@@ -25349,13 +25410,15 @@ void main() {
|
|
|
25349
25410
|
if (!this.orderedCache) this.orderedCache = [...this.panes.values()].sort((a, b) => a.order - b.order);
|
|
25350
25411
|
return this.orderedCache;
|
|
25351
25412
|
}
|
|
25352
|
-
/** The session zones resolved into colored bands (pre/post-market
|
|
25353
|
-
* config's session colors) — consumed by the same painting path as
|
|
25413
|
+
/** The session zones resolved into colored bands (pre/post-market or extended-hours
|
|
25414
|
+
* washes from the config's session colors) — consumed by the same painting path as
|
|
25415
|
+
* {@link highlights}. */
|
|
25354
25416
|
sessionHighlightBands() {
|
|
25355
25417
|
if (!this.sessionZones) return [];
|
|
25356
25418
|
const out = [];
|
|
25357
25419
|
for (const [from, to] of this.sessionZones.pre) out.push({ from, to, color: this.style.sessions.premarketColor });
|
|
25358
25420
|
for (const [from, to] of this.sessionZones.post) out.push({ from, to, color: this.style.sessions.postmarketColor });
|
|
25421
|
+
for (const [from, to] of this.sessionZones.extended) out.push({ from, to, color: this.style.sessions.extendedColor });
|
|
25359
25422
|
return out;
|
|
25360
25423
|
}
|
|
25361
25424
|
indicatorsForPane(paneId) {
|
|
@@ -25894,50 +25957,23 @@ void main() {
|
|
|
25894
25957
|
}
|
|
25895
25958
|
}
|
|
25896
25959
|
/**
|
|
25897
|
-
* Sub-pixel LOD:
|
|
25898
|
-
*
|
|
25899
|
-
*
|
|
25900
|
-
*
|
|
25960
|
+
* Sub-pixel LOD: bars sharing a rounded pixel column collapse into high-low
|
|
25961
|
+
* sticks (one per contiguous coverage run — see {@link aggregateCandleColumns}),
|
|
25962
|
+
* so draw cost is bounded by screen width (not bar count) when zoomed far out
|
|
25963
|
+
* and a price gap inside the column stays a void. Each stick's color follows
|
|
25964
|
+
* its first-open→last-close direction (a barcolor() on the head bar still wins).
|
|
25901
25965
|
*/
|
|
25902
25966
|
drawCandlesAggregated(ctx, bars, i0, i1, coords, pane, up, down, barColors) {
|
|
25903
|
-
|
|
25904
|
-
|
|
25905
|
-
|
|
25906
|
-
|
|
25907
|
-
|
|
25908
|
-
let headTime = 0;
|
|
25909
|
-
let active = false;
|
|
25910
|
-
const flush = () => {
|
|
25911
|
-
if (!active) return;
|
|
25912
|
-
const color = barColors.get(headTime) ?? (closeV >= openV ? up : down);
|
|
25913
|
-
const hY = coords.priceToY(hi, pane.scale, pane.bounds);
|
|
25914
|
-
const lY = coords.priceToY(lo, pane.scale, pane.bounds);
|
|
25915
|
-
ctx.strokeStyle = color;
|
|
25916
|
-
ctx.lineWidth = 1;
|
|
25967
|
+
const yOf = (price) => coords.priceToY(price, pane.scale, pane.bounds);
|
|
25968
|
+
ctx.lineWidth = 1;
|
|
25969
|
+
for (const s of aggregateCandleColumns(bars, i0, i1, (i) => coords.logicalToX(i), yOf)) {
|
|
25970
|
+
const x = s.x + 0.5;
|
|
25971
|
+
ctx.strokeStyle = barColors.get(s.headTime) ?? (s.close >= s.open ? up : down);
|
|
25917
25972
|
ctx.beginPath();
|
|
25918
|
-
ctx.moveTo(
|
|
25919
|
-
ctx.lineTo(
|
|
25973
|
+
ctx.moveTo(x, yOf(s.hi));
|
|
25974
|
+
ctx.lineTo(x, yOf(s.lo));
|
|
25920
25975
|
ctx.stroke();
|
|
25921
|
-
};
|
|
25922
|
-
for (let i = i0; i <= i1; i += 1) {
|
|
25923
|
-
const b = bars[i];
|
|
25924
|
-
if (!b || b.high <= b.low) continue;
|
|
25925
|
-
const x = Math.round(coords.logicalToX(i)) + 0.5;
|
|
25926
|
-
if (!active || x !== px) {
|
|
25927
|
-
flush();
|
|
25928
|
-
px = x;
|
|
25929
|
-
lo = b.low;
|
|
25930
|
-
hi = b.high;
|
|
25931
|
-
openV = b.open;
|
|
25932
|
-
headTime = b.time;
|
|
25933
|
-
active = true;
|
|
25934
|
-
} else {
|
|
25935
|
-
if (b.low < lo) lo = b.low;
|
|
25936
|
-
if (b.high > hi) hi = b.high;
|
|
25937
|
-
}
|
|
25938
|
-
closeV = b.close;
|
|
25939
25976
|
}
|
|
25940
|
-
flush();
|
|
25941
25977
|
}
|
|
25942
25978
|
drawSeries(ctx, spec, pane, coords, i0, i1, theme, off = 0) {
|
|
25943
25979
|
if (spec.kind === "candle" || spec.kind === "bar") {
|
|
@@ -26961,6 +26997,32 @@ void main() {
|
|
|
26961
26997
|
}
|
|
26962
26998
|
};
|
|
26963
26999
|
|
|
27000
|
+
// src/renderers/native/chrome/tz.ts
|
|
27001
|
+
function tzOffsetMs(ms, timeZone) {
|
|
27002
|
+
if (!timeZone || timeZone === "UTC") return 0;
|
|
27003
|
+
try {
|
|
27004
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
27005
|
+
timeZone,
|
|
27006
|
+
hourCycle: "h23",
|
|
27007
|
+
year: "numeric",
|
|
27008
|
+
month: "2-digit",
|
|
27009
|
+
day: "2-digit",
|
|
27010
|
+
hour: "2-digit",
|
|
27011
|
+
minute: "2-digit",
|
|
27012
|
+
second: "2-digit"
|
|
27013
|
+
});
|
|
27014
|
+
const parts3 = dtf.formatToParts(new Date(ms));
|
|
27015
|
+
const get = (t) => Number(parts3.find((p) => p.type === t)?.value);
|
|
27016
|
+
const asUTC = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
|
|
27017
|
+
return asUTC - ms;
|
|
27018
|
+
} catch {
|
|
27019
|
+
return 0;
|
|
27020
|
+
}
|
|
27021
|
+
}
|
|
27022
|
+
function zonedDate(ms, timeZone) {
|
|
27023
|
+
return new Date(ms + tzOffsetMs(ms, timeZone));
|
|
27024
|
+
}
|
|
27025
|
+
|
|
26964
27026
|
// src/renderers/native/chrome/ticks.ts
|
|
26965
27027
|
function priceTicks(min2, max2, target = 6) {
|
|
26966
27028
|
if (!(max2 > min2) || !Number.isFinite(min2) || !Number.isFinite(max2)) return [];
|
|
@@ -27108,7 +27170,14 @@ void main() {
|
|
|
27108
27170
|
YEAR
|
|
27109
27171
|
];
|
|
27110
27172
|
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
27173
|
+
var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
27111
27174
|
var pad2 = (n) => n < 10 ? `0${n}` : String(n);
|
|
27175
|
+
function formatTimeStamp(ms, timeZone, barIntervalMs) {
|
|
27176
|
+
const d = zonedDate(ms, timeZone);
|
|
27177
|
+
const date = `${WEEKDAYS[d.getUTCDay()]} ${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} '${pad2(d.getUTCFullYear() % 100)}`;
|
|
27178
|
+
if (barIntervalMs >= DAY) return date;
|
|
27179
|
+
return `${date} ${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}`;
|
|
27180
|
+
}
|
|
27112
27181
|
function pickStep(targetMs) {
|
|
27113
27182
|
for (const step of STEP_LADDER) if (step >= targetMs) return step;
|
|
27114
27183
|
return STEP_LADDER[STEP_LADDER.length - 1];
|
|
@@ -27150,32 +27219,6 @@ void main() {
|
|
|
27150
27219
|
return out;
|
|
27151
27220
|
}
|
|
27152
27221
|
|
|
27153
|
-
// src/renderers/native/chrome/tz.ts
|
|
27154
|
-
function tzOffsetMs(ms, timeZone) {
|
|
27155
|
-
if (!timeZone || timeZone === "UTC") return 0;
|
|
27156
|
-
try {
|
|
27157
|
-
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
27158
|
-
timeZone,
|
|
27159
|
-
hourCycle: "h23",
|
|
27160
|
-
year: "numeric",
|
|
27161
|
-
month: "2-digit",
|
|
27162
|
-
day: "2-digit",
|
|
27163
|
-
hour: "2-digit",
|
|
27164
|
-
minute: "2-digit",
|
|
27165
|
-
second: "2-digit"
|
|
27166
|
-
});
|
|
27167
|
-
const parts3 = dtf.formatToParts(new Date(ms));
|
|
27168
|
-
const get = (t) => Number(parts3.find((p) => p.type === t)?.value);
|
|
27169
|
-
const asUTC = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
|
|
27170
|
-
return asUTC - ms;
|
|
27171
|
-
} catch {
|
|
27172
|
-
return 0;
|
|
27173
|
-
}
|
|
27174
|
-
}
|
|
27175
|
-
function zonedDate(ms, timeZone) {
|
|
27176
|
-
return new Date(ms + tzOffsetMs(ms, timeZone));
|
|
27177
|
-
}
|
|
27178
|
-
|
|
27179
27222
|
// src/renderers/native/chrome/ChromeRenderer.ts
|
|
27180
27223
|
var ChromeRenderer = class {
|
|
27181
27224
|
constructor() {
|
|
@@ -27622,7 +27665,7 @@ void main() {
|
|
|
27622
27665
|
const price = coords.yToPrice(ch.y, pane.scale, pane.bounds);
|
|
27623
27666
|
this.chip(ctx, dataW + 1, ch.y, formatAxisValue(pane.scale, pane.bounds.height, price, percentScaleFor(scene, pane), scene.priceMintick, pane.axisFormat), chipBg, "left", false, theme.background);
|
|
27624
27667
|
}
|
|
27625
|
-
this.chip(ctx, x, dataH + 1,
|
|
27668
|
+
this.chip(ctx, x, dataH + 1, formatTimeStamp(coords.logicalToTime(logical), scene.timezone, coords.barInterval), chipBg, "center", true, theme.background);
|
|
27626
27669
|
}
|
|
27627
27670
|
destroy() {
|
|
27628
27671
|
this.canvas = null;
|
|
@@ -27670,7 +27713,7 @@ void main() {
|
|
|
27670
27713
|
this.chip(ctx, dataW + 1, ext.y, formatAxisValue(pane.scale, pane.bounds.height, ext.price, percentScaleFor(scene, pane), scene.priceMintick, pane.axisFormat), chipBg, "left", false, theme.background);
|
|
27671
27714
|
}
|
|
27672
27715
|
}
|
|
27673
|
-
this.chip(ctx, x, dataH + 1,
|
|
27716
|
+
this.chip(ctx, x, dataH + 1, formatTimeStamp(ext.time, scene.timezone, coords.barInterval), chipBg, "center", true, theme.background);
|
|
27674
27717
|
ctx.globalAlpha = 1;
|
|
27675
27718
|
}
|
|
27676
27719
|
/** A soft band + a brighter crisp center line over the hovered separator, so it reads as
|
|
@@ -27703,11 +27746,6 @@ void main() {
|
|
|
27703
27746
|
else if (style === "dotted") ctx.setLineDash([2, 3]);
|
|
27704
27747
|
else ctx.setLineDash([]);
|
|
27705
27748
|
}
|
|
27706
|
-
function formatStamp(ms, timeZone) {
|
|
27707
|
-
const d = zonedDate(ms, timeZone);
|
|
27708
|
-
const pad = (n) => n < 10 ? `0${n}` : String(n);
|
|
27709
|
-
return `${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`;
|
|
27710
|
-
}
|
|
27711
27749
|
|
|
27712
27750
|
// src/core/timezones.ts
|
|
27713
27751
|
var TIMEZONES = [
|
|
@@ -34196,6 +34234,9 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
34196
34234
|
const end = Math.min(right, x2);
|
|
34197
34235
|
return end > x ? { x, width: end - x } : null;
|
|
34198
34236
|
}
|
|
34237
|
+
function bandEdgeSlot(logical) {
|
|
34238
|
+
return Math.ceil(logical) - 0.5;
|
|
34239
|
+
}
|
|
34199
34240
|
var BackdropRenderer = class {
|
|
34200
34241
|
constructor() {
|
|
34201
34242
|
this.canvas = null;
|
|
@@ -34226,21 +34267,22 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
34226
34267
|
this.drawGrid(ctx, scene, coords, theme, coords.width, gridAlpha);
|
|
34227
34268
|
}
|
|
34228
34269
|
/** Renderer-owned session highlight bands: full-height (all panes), behind the grid.
|
|
34229
|
-
* Session-zone washes
|
|
34270
|
+
* Session-zone washes paint first (edges snapped to bar-slot boundaries so a band
|
|
34271
|
+
* never cuts a candle in two), host highlights on top (continuous time mapping —
|
|
34272
|
+
* hosts may paint sub-bar spans). */
|
|
34230
34273
|
drawHighlights(ctx, scene, coords) {
|
|
34231
34274
|
const sessions = scene.sessionHighlightBands();
|
|
34232
34275
|
if (sessions.length > 0) {
|
|
34233
34276
|
const left = Math.max(0, coords.logicalToX(-0.5));
|
|
34234
34277
|
const right = Math.min(coords.width, coords.logicalToX(coords.barCount - 0.5));
|
|
34235
|
-
this.drawHighlightSet(ctx, sessions, coords, left, right);
|
|
34278
|
+
this.drawHighlightSet(ctx, sessions, coords, left, right, true);
|
|
34236
34279
|
}
|
|
34237
|
-
this.drawHighlightSet(ctx, scene.highlights, coords, 0, coords.width);
|
|
34280
|
+
this.drawHighlightSet(ctx, scene.highlights, coords, 0, coords.width, false);
|
|
34238
34281
|
}
|
|
34239
|
-
drawHighlightSet(ctx, bands, coords, left, right) {
|
|
34282
|
+
drawHighlightSet(ctx, bands, coords, left, right, snapToSlots) {
|
|
34283
|
+
const edgeX = (ms) => snapToSlots ? coords.logicalToX(bandEdgeSlot(coords.timeToLogical(ms))) : coords.timeToX(ms);
|
|
34240
34284
|
for (const band of bands) {
|
|
34241
|
-
const
|
|
34242
|
-
const x2 = coords.timeToX(band.to);
|
|
34243
|
-
const rect = clipHighlightRect(x1, x2, left, right);
|
|
34285
|
+
const rect = clipHighlightRect(edgeX(band.from), edgeX(band.to), left, right);
|
|
34244
34286
|
if (!rect) continue;
|
|
34245
34287
|
ctx.fillStyle = band.color;
|
|
34246
34288
|
ctx.fillRect(rect.x, 0, rect.width, coords.height);
|
|
@@ -34499,6 +34541,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
34499
34541
|
});
|
|
34500
34542
|
el.style.color = attributionMarkColor(background);
|
|
34501
34543
|
el.innerHTML = html;
|
|
34544
|
+
el.dataset.velaScreenshot = "1";
|
|
34502
34545
|
return el;
|
|
34503
34546
|
}
|
|
34504
34547
|
function createAttributionMark(doc, background) {
|
|
@@ -34517,6 +34560,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
34517
34560
|
cursor: "pointer"
|
|
34518
34561
|
});
|
|
34519
34562
|
applyAttributionMarkTheme(a, background);
|
|
34563
|
+
a.dataset.velaScreenshot = "1";
|
|
34520
34564
|
const symbol = doc.createElement("span");
|
|
34521
34565
|
symbol.className = "vela-attr-symbol";
|
|
34522
34566
|
symbol.setAttribute("aria-hidden", "true");
|
|
@@ -35521,7 +35565,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35521
35565
|
};
|
|
35522
35566
|
})(),
|
|
35523
35567
|
series: { style: this.scene.priceStyle, baseline: this.scene.baselineValue, spacing: this.coords.spacingScale },
|
|
35524
|
-
sessions: { premarketColor: s.sessions.premarketColor, postmarketColor: s.sessions.postmarketColor }
|
|
35568
|
+
sessions: { premarketColor: s.sessions.premarketColor, postmarketColor: s.sessions.postmarketColor, extendedColor: s.sessions.extendedColor }
|
|
35525
35569
|
};
|
|
35526
35570
|
}
|
|
35527
35571
|
/**
|
|
@@ -35603,7 +35647,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35603
35647
|
width: next2.baseline.width,
|
|
35604
35648
|
baselineLevel: next2.baseline.baselineLevel
|
|
35605
35649
|
};
|
|
35606
|
-
s.sessions = { premarketColor: next2.sessions.premarketColor, postmarketColor: next2.sessions.postmarketColor };
|
|
35650
|
+
s.sessions = { premarketColor: next2.sessions.premarketColor, postmarketColor: next2.sessions.postmarketColor, extendedColor: next2.sessions.extendedColor };
|
|
35607
35651
|
this.setPriceStyle(next2.series.style);
|
|
35608
35652
|
this.scene.candleOverride = candleOverrideFor(this.scene.priceStyle, s.chartTypes);
|
|
35609
35653
|
this.scene.baselineValue = next2.series.baseline;
|
|
@@ -35825,9 +35869,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35825
35869
|
* opts in with a `data-vela-screenshot` attribute on the mount container's
|
|
35826
35870
|
* subtree (the widget marks its status line, and its symbol watermark with
|
|
35827
35871
|
* `"under"` — drawn beneath the canvases, where it sits on screen). Only the
|
|
35828
|
-
* crosshair (L2) is intentionally excluded.
|
|
35872
|
+
* crosshair (L2) is intentionally excluded. {@link screenshot} is this canvas
|
|
35873
|
+
* as a PNG data URL.
|
|
35829
35874
|
*/
|
|
35830
|
-
|
|
35875
|
+
screenshotCanvas() {
|
|
35831
35876
|
if (!this.dataCanvas) return null;
|
|
35832
35877
|
this.computeScales();
|
|
35833
35878
|
this.paintData();
|
|
@@ -35855,7 +35900,10 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
35855
35900
|
if (el.getAttribute("data-vela-screenshot") !== "under") rasterizeOverlay(ctx, el, frame);
|
|
35856
35901
|
}
|
|
35857
35902
|
}
|
|
35858
|
-
return out
|
|
35903
|
+
return out;
|
|
35904
|
+
}
|
|
35905
|
+
screenshot() {
|
|
35906
|
+
return this.screenshotCanvas()?.toDataURL("image/png") ?? null;
|
|
35859
35907
|
}
|
|
35860
35908
|
/**
|
|
35861
35909
|
* The candles-first-appear reveal — animates the **candles themselves** (no extra
|
|
@@ -37250,7 +37298,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
37250
37298
|
const pricePane = this.dataWindowPricePane();
|
|
37251
37299
|
const ohlc = this.dataWindowOHLC(bar, pricePane);
|
|
37252
37300
|
const parts3 = [];
|
|
37253
|
-
if (bar) parts3.push(
|
|
37301
|
+
if (bar) parts3.push(formatStamp(bar.time, this.scene.timezone));
|
|
37254
37302
|
if (ohlc) parts3.push(`Open ${ohlc.o}, High ${ohlc.h}, Low ${ohlc.l}, Close ${ohlc.c}`);
|
|
37255
37303
|
for (const group of this.dataWindowGroups(idx, pricePane)) {
|
|
37256
37304
|
for (const row of group.rows) parts3.push(`${row.label} ${row.value}`);
|
|
@@ -38137,7 +38185,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
38137
38185
|
time: `${p(d.getUTCHours())}:${p(d.getUTCMinutes())}`
|
|
38138
38186
|
};
|
|
38139
38187
|
}
|
|
38140
|
-
function
|
|
38188
|
+
function formatStamp(ms, timeZone) {
|
|
38141
38189
|
const { date, time } = formatStampParts(ms, timeZone);
|
|
38142
38190
|
return `${date} ${time}`;
|
|
38143
38191
|
}
|
|
@@ -38168,7 +38216,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
38168
38216
|
}
|
|
38169
38217
|
return out.sort((a, b) => a[0] - b[0]);
|
|
38170
38218
|
};
|
|
38171
|
-
return { pre: windows(v.pre), post: windows(v.post) };
|
|
38219
|
+
return { pre: windows(v.pre), post: windows(v.post), extended: windows(v.extended) };
|
|
38172
38220
|
}
|
|
38173
38221
|
function clamp012(v) {
|
|
38174
38222
|
return Math.max(0, Math.min(1, v));
|
|
@@ -40076,6 +40124,7 @@ ${overlayScrollbarCss(".vela-sd-pane")}
|
|
|
40076
40124
|
exports.BarStore = BarStore;
|
|
40077
40125
|
exports.BinanceProvider = BinanceProvider;
|
|
40078
40126
|
exports.CATEGORICAL = CATEGORICAL;
|
|
40127
|
+
exports.CHIP_PLATE = CHIP_PLATE;
|
|
40079
40128
|
exports.CROSSHAIR = CROSSHAIR;
|
|
40080
40129
|
exports.CachingDataFeed = CachingDataFeed;
|
|
40081
40130
|
exports.CoinbaseProvider = CoinbaseProvider;
|