@luxalgo/vela 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Y7TK4ZWK.js → chunk-EY63XBFZ.js} +9 -9
- package/dist/{chunk-RRFGWZNJ.js → chunk-L5NTMWPP.js} +63 -14
- package/dist/{chunk-B5TIKQJ5.js → chunk-WJKLBYRM.js} +15 -1
- package/dist/index.cjs +76 -13
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +2 -2
- package/dist/{plugin-CnNd7cuF.d.ts → plugin-DP6A4t4o.d.ts} +5 -4
- package/dist/{plugin-DfH4Y-Om.d.cts → plugin-DlidwMj6.d.cts} +5 -4
- package/dist/plugin.d.cts +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +1 -1
- package/dist/vela.global.js +76 -13
- package/dist/vela.global.min.js +27 -27
- package/dist/widget.cjs +83 -20
- package/dist/widget.d.cts +1 -1
- package/dist/widget.d.ts +1 -1
- package/dist/widget.js +6 -6
- package/dist/workspace.cjs +83 -20
- package/dist/workspace.js +4 -4
- package/package.json +1 -1
package/dist/widget.cjs
CHANGED
|
@@ -14014,7 +14014,7 @@ var TOUCH_TAP_SLOP = 14;
|
|
|
14014
14014
|
var DOUBLE_TAP_MS = 350;
|
|
14015
14015
|
var DOUBLE_TAP_SLOP = 30;
|
|
14016
14016
|
var TIME_SCALE_K = 4e-3;
|
|
14017
|
-
var WHEEL_ZOOM_K =
|
|
14017
|
+
var WHEEL_ZOOM_K = 4e-3;
|
|
14018
14018
|
function wheelZoomAnchor(coords, cursorX, rightEdge) {
|
|
14019
14019
|
if (rightEdge) return { logical: coords.rightEdgeLogical, x: coords.width };
|
|
14020
14020
|
return { logical: coords.xToLogical(cursorX), x: cursorX };
|
|
@@ -14068,6 +14068,8 @@ var InputController = class {
|
|
|
14068
14068
|
// smoothed pointer velocity, px/ms
|
|
14069
14069
|
this.middleDeleted = false;
|
|
14070
14070
|
// the last middle press deleted a drawing (suppress autoscroll/paste)
|
|
14071
|
+
this.rightCancelled = false;
|
|
14072
|
+
// the last right press cancelled a placement (suppress the context menu)
|
|
14071
14073
|
// Last cursor position over the element (NaN once it leaves) — lets a modifier
|
|
14072
14074
|
// press/release re-shape the drawings preview with the pointer stationary.
|
|
14073
14075
|
this.cursorX = NaN;
|
|
@@ -14092,6 +14094,14 @@ var InputController = class {
|
|
|
14092
14094
|
this.onMiddleGuard = (e) => {
|
|
14093
14095
|
if (e.button === 1 && this.middleDeleted) e.preventDefault();
|
|
14094
14096
|
};
|
|
14097
|
+
/** A right press that cancelled a placement must not ALSO open the host's chart
|
|
14098
|
+
* context menu — swallow its companion event before it bubbles to the host. */
|
|
14099
|
+
this.onContextGuard = (e) => {
|
|
14100
|
+
if (!this.rightCancelled) return;
|
|
14101
|
+
this.rightCancelled = false;
|
|
14102
|
+
e.preventDefault();
|
|
14103
|
+
e.stopPropagation();
|
|
14104
|
+
};
|
|
14095
14105
|
/** A modifier press/release with the pointer stationary: re-issue the last cursor
|
|
14096
14106
|
* position so the placing ghost / drag preview reflects the new state immediately
|
|
14097
14107
|
* (Shift's 45° angle lock, Ctrl/Cmd's momentary strong magnet). */
|
|
@@ -14108,6 +14118,11 @@ var InputController = class {
|
|
|
14108
14118
|
if (this.middleDeleted) e.preventDefault();
|
|
14109
14119
|
return;
|
|
14110
14120
|
}
|
|
14121
|
+
if (e.button === 2) {
|
|
14122
|
+
this.rightCancelled = this.deps.drawingsCancelPlacement?.() ?? false;
|
|
14123
|
+
if (this.rightCancelled) e.preventDefault();
|
|
14124
|
+
return;
|
|
14125
|
+
}
|
|
14111
14126
|
if (e.button !== 0) return;
|
|
14112
14127
|
const { x, y } = this.local(e);
|
|
14113
14128
|
if (e.pointerType === "touch") {
|
|
@@ -14312,6 +14327,7 @@ var InputController = class {
|
|
|
14312
14327
|
el.addEventListener("wheel", this.onWheel, { passive: false });
|
|
14313
14328
|
el.addEventListener("mousedown", this.onMiddleGuard);
|
|
14314
14329
|
el.addEventListener("auxclick", this.onMiddleGuard);
|
|
14330
|
+
el.addEventListener("contextmenu", this.onContextGuard);
|
|
14315
14331
|
const win = el.ownerDocument?.defaultView;
|
|
14316
14332
|
win?.addEventListener("keydown", this.onModifier);
|
|
14317
14333
|
win?.addEventListener("keyup", this.onModifier);
|
|
@@ -14333,6 +14349,7 @@ var InputController = class {
|
|
|
14333
14349
|
el.removeEventListener("wheel", this.onWheel);
|
|
14334
14350
|
el.removeEventListener("mousedown", this.onMiddleGuard);
|
|
14335
14351
|
el.removeEventListener("auxclick", this.onMiddleGuard);
|
|
14352
|
+
el.removeEventListener("contextmenu", this.onContextGuard);
|
|
14336
14353
|
this.cancelLongPress();
|
|
14337
14354
|
this.touches.clear();
|
|
14338
14355
|
this.el = null;
|
|
@@ -16005,8 +16022,11 @@ var ChromeRenderer = class {
|
|
|
16005
16022
|
}
|
|
16006
16023
|
ctx.font = `${scene.style.fontSize}px ${theme.fontFamily}`;
|
|
16007
16024
|
ctx.textBaseline = "middle";
|
|
16008
|
-
if (coords.barCount === 0) return;
|
|
16009
16025
|
const panes = scene.orderedPanes();
|
|
16026
|
+
if (coords.barCount === 0) {
|
|
16027
|
+
this.drawPaneSeparators(ctx, scene, theme, fullW, panes);
|
|
16028
|
+
return;
|
|
16029
|
+
}
|
|
16010
16030
|
const pricePane = panes.find((p) => p.kind === "price") ?? null;
|
|
16011
16031
|
for (const pane of panes) {
|
|
16012
16032
|
if (pane.collapsed) continue;
|
|
@@ -22168,6 +22188,16 @@ var UserDrawingController = class {
|
|
|
22168
22188
|
if (this.eraserMode) return "pointer";
|
|
22169
22189
|
return this.interaction.cursorAt(x, y);
|
|
22170
22190
|
}
|
|
22191
|
+
/** Right-click while placing: cancel the in-progress drawing and revert to the
|
|
22192
|
+
* pointer — the gesture is an explicit escape, so it disarms even in
|
|
22193
|
+
* stay-in-drawing-mode (where Escape would leave the tool armed). Returns whether
|
|
22194
|
+
* the press was consumed; false lets the host's context menu open normally. */
|
|
22195
|
+
cancelPlacement() {
|
|
22196
|
+
if (!this.interaction.isPlacing()) return false;
|
|
22197
|
+
this.interaction.cancel();
|
|
22198
|
+
if (this.activeTool != null) this.emit({ kind: "arm", type: null });
|
|
22199
|
+
return true;
|
|
22200
|
+
}
|
|
22171
22201
|
/** Double-click over a drawing → suppress the chart's view reset (single-click already
|
|
22172
22202
|
* opens settings). Returns true only when a drawing is under the cursor. */
|
|
22173
22203
|
dblClick(x, y) {
|
|
@@ -22652,6 +22682,20 @@ var VolumeRenderer = class {
|
|
|
22652
22682
|
};
|
|
22653
22683
|
|
|
22654
22684
|
// src/renderers/native/layers.ts
|
|
22685
|
+
function foldBaseModulation(acc, next) {
|
|
22686
|
+
if (next == null) return acc;
|
|
22687
|
+
if (acc == null) return { ...next };
|
|
22688
|
+
return {
|
|
22689
|
+
candleBodyScale: minOpt(acc.candleBodyScale, next.candleBodyScale),
|
|
22690
|
+
candleBodyAlpha: minOpt(acc.candleBodyAlpha, next.candleBodyAlpha),
|
|
22691
|
+
gridAlpha: minOpt(acc.gridAlpha, next.gridAlpha)
|
|
22692
|
+
};
|
|
22693
|
+
}
|
|
22694
|
+
function minOpt(a, b) {
|
|
22695
|
+
if (a == null) return b;
|
|
22696
|
+
if (b == null) return a;
|
|
22697
|
+
return Math.min(a, b);
|
|
22698
|
+
}
|
|
22655
22699
|
var registry3 = /* @__PURE__ */ new Map();
|
|
22656
22700
|
function rendererLayers() {
|
|
22657
22701
|
return [...registry3.values()];
|
|
@@ -23289,7 +23333,7 @@ var NativeRenderer = class {
|
|
|
23289
23333
|
this.scrollTargetRO = null;
|
|
23290
23334
|
// eased rightOffset target while gliding back to the latest bars
|
|
23291
23335
|
// Distance (px) from the plot's bottom edge to the button — tracks the bottom-most EXPANDED
|
|
23292
|
-
// pane
|
|
23336
|
+
// pane: when the lower sub-panes collapse it rides up into the open pane.
|
|
23293
23337
|
this.scrollBtnBottomPx = SCROLL_BTN_BOTTOM;
|
|
23294
23338
|
// Distance (px) from the plot's right edge — clears the FULL scale gutter, which widens when a
|
|
23295
23339
|
// pane carries merged (own-scale) columns; the constant only clears a single-column scale.
|
|
@@ -24256,6 +24300,7 @@ var NativeRenderer = class {
|
|
|
24256
24300
|
drawingsClaim: (x, y) => this.userDrawings?.claim(x, y) ?? false,
|
|
24257
24301
|
drawingsMeasureStart: (x, y) => this.userDrawings?.beginMeasureAt(x, y) ?? false,
|
|
24258
24302
|
drawingsDeleteAt: (x, y) => this.userDrawings?.deleteAt(x, y) ?? false,
|
|
24303
|
+
drawingsCancelPlacement: () => this.userDrawings?.cancelPlacement() ?? false,
|
|
24259
24304
|
drawingsSnapMode: () => this.snapMode,
|
|
24260
24305
|
drawingsPointerDown: (x, y, snap, shift) => this.userDrawings?.pointerDown(x, y, snap, shift),
|
|
24261
24306
|
drawingsPointerMove: (x, y, snap, shift) => this.userDrawings?.pointerMove(x, y, snap, shift),
|
|
@@ -24507,6 +24552,8 @@ var NativeRenderer = class {
|
|
|
24507
24552
|
this.attributionEl = null;
|
|
24508
24553
|
this.mountContainer?.style.removeProperty("--vela-toolbar-gutter");
|
|
24509
24554
|
this.mountContainer?.style.removeProperty("--vela-scale-gutter");
|
|
24555
|
+
this.mountContainer?.style.removeProperty("--vela-price-pane-top");
|
|
24556
|
+
this.mountContainer?.style.removeProperty("--vela-price-pane-bottom");
|
|
24510
24557
|
this.mountContainer = null;
|
|
24511
24558
|
this.wrapper?.remove();
|
|
24512
24559
|
}
|
|
@@ -25596,19 +25643,18 @@ var NativeRenderer = class {
|
|
|
25596
25643
|
theme: this.theme
|
|
25597
25644
|
});
|
|
25598
25645
|
const nowMs = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
25646
|
+
let folded = null;
|
|
25599
25647
|
for (const l of this.extLayers) {
|
|
25600
25648
|
const args = this.extLayerArgs(l.def.id, pane.scale, pane.bounds, nowMs);
|
|
25601
25649
|
l.instance.render(args);
|
|
25602
|
-
|
|
25603
|
-
const mod = l.instance.modulateBase(args);
|
|
25604
|
-
if (mod) {
|
|
25605
|
-
if (mod.candleBodyScale != null) this.backend.candleBodyScale = clamp012(mod.candleBodyScale) || 0.01;
|
|
25606
|
-
if (mod.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(mod.candleBodyAlpha) * this.candleBodyAlpha;
|
|
25607
|
-
if (mod.gridAlpha != null) this.backend.gridAlpha = clamp012(mod.gridAlpha);
|
|
25608
|
-
}
|
|
25609
|
-
}
|
|
25650
|
+
folded = foldBaseModulation(folded, l.instance.modulateBase?.(args) ?? null);
|
|
25610
25651
|
if (this.animZoom && l.instance.animating?.()) this.animator.start();
|
|
25611
25652
|
}
|
|
25653
|
+
if (folded) {
|
|
25654
|
+
if (folded.candleBodyScale != null) this.backend.candleBodyScale = clamp012(folded.candleBodyScale) || 0.01;
|
|
25655
|
+
if (folded.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(folded.candleBodyAlpha) * this.candleBodyAlpha;
|
|
25656
|
+
if (folded.gridAlpha != null) this.backend.gridAlpha = clamp012(folded.gridAlpha);
|
|
25657
|
+
}
|
|
25612
25658
|
}
|
|
25613
25659
|
const li = this.bars.length - 1;
|
|
25614
25660
|
const liveActual = li >= 0 ? this.bars[li] : void 0;
|
|
@@ -26000,6 +26046,7 @@ var NativeRenderer = class {
|
|
|
26000
26046
|
this.paneControls?.reposition();
|
|
26001
26047
|
this.repositionScrollButton();
|
|
26002
26048
|
this.positionAttribution();
|
|
26049
|
+
this.publishPricePaneBounds();
|
|
26003
26050
|
return;
|
|
26004
26051
|
}
|
|
26005
26052
|
const collapsed = panes.filter((p) => p.collapsed);
|
|
@@ -26017,9 +26064,10 @@ var NativeRenderer = class {
|
|
|
26017
26064
|
this.paneControls?.reposition();
|
|
26018
26065
|
this.repositionScrollButton();
|
|
26019
26066
|
this.positionAttribution();
|
|
26067
|
+
this.publishPricePaneBounds();
|
|
26020
26068
|
}
|
|
26021
|
-
/** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area
|
|
26022
|
-
*
|
|
26069
|
+
/** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area:
|
|
26070
|
+
* with all lower sub-panes collapsed it settles into the lowest open pane. */
|
|
26023
26071
|
repositionScrollButton() {
|
|
26024
26072
|
const dataHeight = this.coords.height;
|
|
26025
26073
|
if (dataHeight <= 0) return;
|
|
@@ -26063,6 +26111,21 @@ var NativeRenderer = class {
|
|
|
26063
26111
|
this.mountContainer?.style.setProperty("--vela-toolbar-gutter", `${this.toolbarGutter}px`);
|
|
26064
26112
|
this.mountContainer?.style.setProperty("--vela-scale-gutter", `${this.rightAxisW}px`);
|
|
26065
26113
|
}
|
|
26114
|
+
/** Publish the price pane's vertical insets as `--vela-price-pane-top` /
|
|
26115
|
+
* `--vela-price-pane-bottom` on the mount container, so the symbol watermark
|
|
26116
|
+
* (and any other host overlay) can clip to the price pane instead of spanning
|
|
26117
|
+
* study panes and the time axis. A maximized study pane collapses the box to
|
|
26118
|
+
* zero height — the mark does not appear on a study. */
|
|
26119
|
+
publishPricePaneBounds() {
|
|
26120
|
+
if (!this.mountContainer) return;
|
|
26121
|
+
const plotH = this.coords.height + TIME_AXIS_H;
|
|
26122
|
+
const price = this.scene.panes.get(PRICE_PANE_ID);
|
|
26123
|
+
const top = price ? price.bounds.top : 0;
|
|
26124
|
+
const height = price ? price.bounds.height : this.coords.height;
|
|
26125
|
+
const bottom = Math.max(0, plotH - (top + height));
|
|
26126
|
+
this.mountContainer.style.setProperty("--vela-price-pane-top", `${top}px`);
|
|
26127
|
+
this.mountContainer.style.setProperty("--vela-price-pane-bottom", `${bottom}px`);
|
|
26128
|
+
}
|
|
26066
26129
|
/** The built-in mark, or the host's own when one is set. */
|
|
26067
26130
|
buildAttributionEl() {
|
|
26068
26131
|
return this.attributionHtml !== null ? createCustomMark(document, this.attributionHtml, this.theme.background) : createAttributionMark(document, this.theme.background);
|
|
@@ -29038,17 +29101,17 @@ var STYLE_ID10 = "vela-widget-watermark";
|
|
|
29038
29101
|
var CSS6 = `
|
|
29039
29102
|
.vela-watermark {
|
|
29040
29103
|
position: absolute;
|
|
29041
|
-
/* Insets follow the renderer-published gutters
|
|
29042
|
-
*
|
|
29043
|
-
*
|
|
29044
|
-
|
|
29045
|
-
|
|
29046
|
-
bottom: 0;
|
|
29104
|
+
/* Insets follow the renderer-published gutters AND the price-pane vertical
|
|
29105
|
+
* bounds (mount container), so the mark centers on the PRICE PANE \u2014 never
|
|
29106
|
+
* the study panes below, the drawings toolbar, or the price scale. */
|
|
29107
|
+
top: var(--vela-price-pane-top, 0px);
|
|
29108
|
+
bottom: var(--vela-price-pane-bottom, 0px);
|
|
29047
29109
|
left: var(--vela-toolbar-gutter, 0px);
|
|
29048
29110
|
right: var(--vela-scale-gutter, 0px);
|
|
29049
29111
|
display: flex;
|
|
29050
29112
|
align-items: center;
|
|
29051
29113
|
justify-content: center;
|
|
29114
|
+
overflow: hidden;
|
|
29052
29115
|
pointer-events: none;
|
|
29053
29116
|
z-index: 1;
|
|
29054
29117
|
color: var(--vela-fg);
|
|
@@ -29103,7 +29166,7 @@ var Watermark = class {
|
|
|
29103
29166
|
this.text.textContent = symbol ? `${parseSymbol(symbol).ticker} \xB7 ${timeframeLabel(timeframe)}` : "";
|
|
29104
29167
|
this.fit();
|
|
29105
29168
|
}
|
|
29106
|
-
/** Measure the text at the cap and shrink it to the
|
|
29169
|
+
/** Measure the text at the cap and shrink it to the price pane's width. */
|
|
29107
29170
|
fit() {
|
|
29108
29171
|
if (this.el.clientWidth <= 0 || !this.text.textContent) return;
|
|
29109
29172
|
this.el.style.fontSize = `${MAX_FONT_PX}px`;
|
package/dist/widget.d.cts
CHANGED
|
@@ -442,7 +442,7 @@ declare class Watermark {
|
|
|
442
442
|
setLoading(loading: boolean): void;
|
|
443
443
|
private sync;
|
|
444
444
|
update(symbol: string, timeframe: string): void;
|
|
445
|
-
/** Measure the text at the cap and shrink it to the
|
|
445
|
+
/** Measure the text at the cap and shrink it to the price pane's width. */
|
|
446
446
|
private fit;
|
|
447
447
|
destroy(): void;
|
|
448
448
|
}
|
package/dist/widget.d.ts
CHANGED
|
@@ -442,7 +442,7 @@ declare class Watermark {
|
|
|
442
442
|
setLoading(loading: boolean): void;
|
|
443
443
|
private sync;
|
|
444
444
|
update(symbol: string, timeframe: string): void;
|
|
445
|
-
/** Measure the text at the cap and shrink it to the
|
|
445
|
+
/** Measure the text at the cap and shrink it to the price pane's width. */
|
|
446
446
|
private fit;
|
|
447
447
|
destroy(): void;
|
|
448
448
|
}
|
package/dist/widget.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Glider, WidgetHistory, localStorageAdapter, decodeState, prefixedSymbol, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, ChartContextMenu, Toast, Watermark, Statusline, Bottombar, MobileBar, DrawingPill, LayoutModeController, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, indicatorLedger, sanitizeState, legacyWidgetState, parsePersisted, statuslineInkOf, toolShortcutHints, resolveIndicators, encodeState } from './chunk-
|
|
2
|
-
export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, legacyWidgetState, loadPersisted, localStorageAdapter, parsePersisted, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, timeframeLabel, timeframeMs } from './chunk-
|
|
3
|
-
import { registerBuiltinChartTypes, resolveTheme, parseSymbol, buildToolbar, priceStyleIds, Vela, normalizeTimezone } from './chunk-
|
|
4
|
-
export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-
|
|
5
|
-
import { widgetActions, widgetAttachments, legendActionsProviderFor, resolveEngines } from './chunk-
|
|
6
|
-
export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, SidePanel, clampPanelWidth, registerSidePanel, registerWidgetAction, registerWidgetAttachment, sidePanels, unregisterSidePanel, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-
|
|
1
|
+
import { Glider, WidgetHistory, localStorageAdapter, decodeState, prefixedSymbol, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, ChartContextMenu, Toast, Watermark, Statusline, Bottombar, MobileBar, DrawingPill, LayoutModeController, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, indicatorLedger, sanitizeState, legacyWidgetState, parsePersisted, statuslineInkOf, toolShortcutHints, resolveIndicators, encodeState } from './chunk-EY63XBFZ.js';
|
|
2
|
+
export { Bottombar, ChartContextMenu, DataWindow, IndicatorPicker, ObjectTree, PanelDock, RANGE_PRESETS, ShortcutsHelp, Statusline, SymbolPicker, TimeframeQuick, Topbar, Watermark, dataWindowSections, decimalsFor, decodeState, encodeState, filterSymbols, fmtChange, fmtPrice, legacyWidgetState, loadPersisted, localStorageAdapter, parsePersisted, parseTimeframe, priceStyleLabel, resolveIndicators, sanitizeState, savePersisted, timeframeLabel, timeframeMs } from './chunk-EY63XBFZ.js';
|
|
3
|
+
import { registerBuiltinChartTypes, resolveTheme, parseSymbol, buildToolbar, priceStyleIds, Vela, normalizeTimezone } from './chunk-L5NTMWPP.js';
|
|
4
|
+
export { TIMEZONES, normalizeTimezone, tzButtonLabel, tzMenuLabel, tzOffset } from './chunk-L5NTMWPP.js';
|
|
5
|
+
import { widgetActions, widgetAttachments, legendActionsProviderFor, resolveEngines } from './chunk-WJKLBYRM.js';
|
|
6
|
+
export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, SidePanel, clampPanelWidth, registerSidePanel, registerWidgetAction, registerWidgetAttachment, sidePanels, unregisterSidePanel, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-WJKLBYRM.js';
|
|
7
7
|
import { ensureUIHost, KeymapManager, Menu, applyPlotOverlayTokens, isEditableTarget } from './chunk-P556H6EA.js';
|
|
8
8
|
import './chunk-ATPU5CI6.js';
|
|
9
9
|
import { injectStyles } from './chunk-LJLZR44Y.js';
|
package/dist/workspace.cjs
CHANGED
|
@@ -21060,7 +21060,7 @@ var TOUCH_TAP_SLOP = 14;
|
|
|
21060
21060
|
var DOUBLE_TAP_MS = 350;
|
|
21061
21061
|
var DOUBLE_TAP_SLOP = 30;
|
|
21062
21062
|
var TIME_SCALE_K = 4e-3;
|
|
21063
|
-
var WHEEL_ZOOM_K =
|
|
21063
|
+
var WHEEL_ZOOM_K = 4e-3;
|
|
21064
21064
|
function wheelZoomAnchor(coords, cursorX, rightEdge) {
|
|
21065
21065
|
if (rightEdge) return { logical: coords.rightEdgeLogical, x: coords.width };
|
|
21066
21066
|
return { logical: coords.xToLogical(cursorX), x: cursorX };
|
|
@@ -21114,6 +21114,8 @@ var InputController = class {
|
|
|
21114
21114
|
// smoothed pointer velocity, px/ms
|
|
21115
21115
|
this.middleDeleted = false;
|
|
21116
21116
|
// the last middle press deleted a drawing (suppress autoscroll/paste)
|
|
21117
|
+
this.rightCancelled = false;
|
|
21118
|
+
// the last right press cancelled a placement (suppress the context menu)
|
|
21117
21119
|
// Last cursor position over the element (NaN once it leaves) — lets a modifier
|
|
21118
21120
|
// press/release re-shape the drawings preview with the pointer stationary.
|
|
21119
21121
|
this.cursorX = NaN;
|
|
@@ -21138,6 +21140,14 @@ var InputController = class {
|
|
|
21138
21140
|
this.onMiddleGuard = (e) => {
|
|
21139
21141
|
if (e.button === 1 && this.middleDeleted) e.preventDefault();
|
|
21140
21142
|
};
|
|
21143
|
+
/** A right press that cancelled a placement must not ALSO open the host's chart
|
|
21144
|
+
* context menu — swallow its companion event before it bubbles to the host. */
|
|
21145
|
+
this.onContextGuard = (e) => {
|
|
21146
|
+
if (!this.rightCancelled) return;
|
|
21147
|
+
this.rightCancelled = false;
|
|
21148
|
+
e.preventDefault();
|
|
21149
|
+
e.stopPropagation();
|
|
21150
|
+
};
|
|
21141
21151
|
/** A modifier press/release with the pointer stationary: re-issue the last cursor
|
|
21142
21152
|
* position so the placing ghost / drag preview reflects the new state immediately
|
|
21143
21153
|
* (Shift's 45° angle lock, Ctrl/Cmd's momentary strong magnet). */
|
|
@@ -21154,6 +21164,11 @@ var InputController = class {
|
|
|
21154
21164
|
if (this.middleDeleted) e.preventDefault();
|
|
21155
21165
|
return;
|
|
21156
21166
|
}
|
|
21167
|
+
if (e.button === 2) {
|
|
21168
|
+
this.rightCancelled = this.deps.drawingsCancelPlacement?.() ?? false;
|
|
21169
|
+
if (this.rightCancelled) e.preventDefault();
|
|
21170
|
+
return;
|
|
21171
|
+
}
|
|
21157
21172
|
if (e.button !== 0) return;
|
|
21158
21173
|
const { x, y } = this.local(e);
|
|
21159
21174
|
if (e.pointerType === "touch") {
|
|
@@ -21358,6 +21373,7 @@ var InputController = class {
|
|
|
21358
21373
|
el.addEventListener("wheel", this.onWheel, { passive: false });
|
|
21359
21374
|
el.addEventListener("mousedown", this.onMiddleGuard);
|
|
21360
21375
|
el.addEventListener("auxclick", this.onMiddleGuard);
|
|
21376
|
+
el.addEventListener("contextmenu", this.onContextGuard);
|
|
21361
21377
|
const win = el.ownerDocument?.defaultView;
|
|
21362
21378
|
win?.addEventListener("keydown", this.onModifier);
|
|
21363
21379
|
win?.addEventListener("keyup", this.onModifier);
|
|
@@ -21379,6 +21395,7 @@ var InputController = class {
|
|
|
21379
21395
|
el.removeEventListener("wheel", this.onWheel);
|
|
21380
21396
|
el.removeEventListener("mousedown", this.onMiddleGuard);
|
|
21381
21397
|
el.removeEventListener("auxclick", this.onMiddleGuard);
|
|
21398
|
+
el.removeEventListener("contextmenu", this.onContextGuard);
|
|
21382
21399
|
this.cancelLongPress();
|
|
21383
21400
|
this.touches.clear();
|
|
21384
21401
|
this.el = null;
|
|
@@ -23051,8 +23068,11 @@ var ChromeRenderer = class {
|
|
|
23051
23068
|
}
|
|
23052
23069
|
ctx.font = `${scene.style.fontSize}px ${theme.fontFamily}`;
|
|
23053
23070
|
ctx.textBaseline = "middle";
|
|
23054
|
-
if (coords.barCount === 0) return;
|
|
23055
23071
|
const panes = scene.orderedPanes();
|
|
23072
|
+
if (coords.barCount === 0) {
|
|
23073
|
+
this.drawPaneSeparators(ctx, scene, theme, fullW, panes);
|
|
23074
|
+
return;
|
|
23075
|
+
}
|
|
23056
23076
|
const pricePane = panes.find((p) => p.kind === "price") ?? null;
|
|
23057
23077
|
for (const pane of panes) {
|
|
23058
23078
|
if (pane.collapsed) continue;
|
|
@@ -28496,6 +28516,16 @@ var UserDrawingController = class {
|
|
|
28496
28516
|
if (this.eraserMode) return "pointer";
|
|
28497
28517
|
return this.interaction.cursorAt(x, y);
|
|
28498
28518
|
}
|
|
28519
|
+
/** Right-click while placing: cancel the in-progress drawing and revert to the
|
|
28520
|
+
* pointer — the gesture is an explicit escape, so it disarms even in
|
|
28521
|
+
* stay-in-drawing-mode (where Escape would leave the tool armed). Returns whether
|
|
28522
|
+
* the press was consumed; false lets the host's context menu open normally. */
|
|
28523
|
+
cancelPlacement() {
|
|
28524
|
+
if (!this.interaction.isPlacing()) return false;
|
|
28525
|
+
this.interaction.cancel();
|
|
28526
|
+
if (this.activeTool != null) this.emit({ kind: "arm", type: null });
|
|
28527
|
+
return true;
|
|
28528
|
+
}
|
|
28499
28529
|
/** Double-click over a drawing → suppress the chart's view reset (single-click already
|
|
28500
28530
|
* opens settings). Returns true only when a drawing is under the cursor. */
|
|
28501
28531
|
dblClick(x, y) {
|
|
@@ -28980,6 +29010,20 @@ var VolumeRenderer = class {
|
|
|
28980
29010
|
};
|
|
28981
29011
|
|
|
28982
29012
|
// src/renderers/native/layers.ts
|
|
29013
|
+
function foldBaseModulation(acc, next) {
|
|
29014
|
+
if (next == null) return acc;
|
|
29015
|
+
if (acc == null) return { ...next };
|
|
29016
|
+
return {
|
|
29017
|
+
candleBodyScale: minOpt(acc.candleBodyScale, next.candleBodyScale),
|
|
29018
|
+
candleBodyAlpha: minOpt(acc.candleBodyAlpha, next.candleBodyAlpha),
|
|
29019
|
+
gridAlpha: minOpt(acc.gridAlpha, next.gridAlpha)
|
|
29020
|
+
};
|
|
29021
|
+
}
|
|
29022
|
+
function minOpt(a, b) {
|
|
29023
|
+
if (a == null) return b;
|
|
29024
|
+
if (b == null) return a;
|
|
29025
|
+
return Math.min(a, b);
|
|
29026
|
+
}
|
|
28983
29027
|
var registry4 = /* @__PURE__ */ new Map();
|
|
28984
29028
|
function rendererLayers() {
|
|
28985
29029
|
return [...registry4.values()];
|
|
@@ -29489,7 +29533,7 @@ var NativeRenderer = class {
|
|
|
29489
29533
|
this.scrollTargetRO = null;
|
|
29490
29534
|
// eased rightOffset target while gliding back to the latest bars
|
|
29491
29535
|
// Distance (px) from the plot's bottom edge to the button — tracks the bottom-most EXPANDED
|
|
29492
|
-
// pane
|
|
29536
|
+
// pane: when the lower sub-panes collapse it rides up into the open pane.
|
|
29493
29537
|
this.scrollBtnBottomPx = SCROLL_BTN_BOTTOM;
|
|
29494
29538
|
// Distance (px) from the plot's right edge — clears the FULL scale gutter, which widens when a
|
|
29495
29539
|
// pane carries merged (own-scale) columns; the constant only clears a single-column scale.
|
|
@@ -30456,6 +30500,7 @@ var NativeRenderer = class {
|
|
|
30456
30500
|
drawingsClaim: (x, y) => this.userDrawings?.claim(x, y) ?? false,
|
|
30457
30501
|
drawingsMeasureStart: (x, y) => this.userDrawings?.beginMeasureAt(x, y) ?? false,
|
|
30458
30502
|
drawingsDeleteAt: (x, y) => this.userDrawings?.deleteAt(x, y) ?? false,
|
|
30503
|
+
drawingsCancelPlacement: () => this.userDrawings?.cancelPlacement() ?? false,
|
|
30459
30504
|
drawingsSnapMode: () => this.snapMode,
|
|
30460
30505
|
drawingsPointerDown: (x, y, snap, shift) => this.userDrawings?.pointerDown(x, y, snap, shift),
|
|
30461
30506
|
drawingsPointerMove: (x, y, snap, shift) => this.userDrawings?.pointerMove(x, y, snap, shift),
|
|
@@ -30707,6 +30752,8 @@ var NativeRenderer = class {
|
|
|
30707
30752
|
this.attributionEl = null;
|
|
30708
30753
|
this.mountContainer?.style.removeProperty("--vela-toolbar-gutter");
|
|
30709
30754
|
this.mountContainer?.style.removeProperty("--vela-scale-gutter");
|
|
30755
|
+
this.mountContainer?.style.removeProperty("--vela-price-pane-top");
|
|
30756
|
+
this.mountContainer?.style.removeProperty("--vela-price-pane-bottom");
|
|
30710
30757
|
this.mountContainer = null;
|
|
30711
30758
|
this.wrapper?.remove();
|
|
30712
30759
|
}
|
|
@@ -31796,19 +31843,18 @@ var NativeRenderer = class {
|
|
|
31796
31843
|
theme: this.theme
|
|
31797
31844
|
});
|
|
31798
31845
|
const nowMs = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
31846
|
+
let folded = null;
|
|
31799
31847
|
for (const l of this.extLayers) {
|
|
31800
31848
|
const args = this.extLayerArgs(l.def.id, pane.scale, pane.bounds, nowMs);
|
|
31801
31849
|
l.instance.render(args);
|
|
31802
|
-
|
|
31803
|
-
const mod = l.instance.modulateBase(args);
|
|
31804
|
-
if (mod) {
|
|
31805
|
-
if (mod.candleBodyScale != null) this.backend.candleBodyScale = clamp012(mod.candleBodyScale) || 0.01;
|
|
31806
|
-
if (mod.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(mod.candleBodyAlpha) * this.candleBodyAlpha;
|
|
31807
|
-
if (mod.gridAlpha != null) this.backend.gridAlpha = clamp012(mod.gridAlpha);
|
|
31808
|
-
}
|
|
31809
|
-
}
|
|
31850
|
+
folded = foldBaseModulation(folded, l.instance.modulateBase?.(args) ?? null);
|
|
31810
31851
|
if (this.animZoom && l.instance.animating?.()) this.animator.start();
|
|
31811
31852
|
}
|
|
31853
|
+
if (folded) {
|
|
31854
|
+
if (folded.candleBodyScale != null) this.backend.candleBodyScale = clamp012(folded.candleBodyScale) || 0.01;
|
|
31855
|
+
if (folded.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(folded.candleBodyAlpha) * this.candleBodyAlpha;
|
|
31856
|
+
if (folded.gridAlpha != null) this.backend.gridAlpha = clamp012(folded.gridAlpha);
|
|
31857
|
+
}
|
|
31812
31858
|
}
|
|
31813
31859
|
const li = this.bars.length - 1;
|
|
31814
31860
|
const liveActual = li >= 0 ? this.bars[li] : void 0;
|
|
@@ -32200,6 +32246,7 @@ var NativeRenderer = class {
|
|
|
32200
32246
|
this.paneControls?.reposition();
|
|
32201
32247
|
this.repositionScrollButton();
|
|
32202
32248
|
this.positionAttribution();
|
|
32249
|
+
this.publishPricePaneBounds();
|
|
32203
32250
|
return;
|
|
32204
32251
|
}
|
|
32205
32252
|
const collapsed = panes.filter((p) => p.collapsed);
|
|
@@ -32217,9 +32264,10 @@ var NativeRenderer = class {
|
|
|
32217
32264
|
this.paneControls?.reposition();
|
|
32218
32265
|
this.repositionScrollButton();
|
|
32219
32266
|
this.positionAttribution();
|
|
32267
|
+
this.publishPricePaneBounds();
|
|
32220
32268
|
}
|
|
32221
|
-
/** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area
|
|
32222
|
-
*
|
|
32269
|
+
/** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area:
|
|
32270
|
+
* with all lower sub-panes collapsed it settles into the lowest open pane. */
|
|
32223
32271
|
repositionScrollButton() {
|
|
32224
32272
|
const dataHeight = this.coords.height;
|
|
32225
32273
|
if (dataHeight <= 0) return;
|
|
@@ -32263,6 +32311,21 @@ var NativeRenderer = class {
|
|
|
32263
32311
|
this.mountContainer?.style.setProperty("--vela-toolbar-gutter", `${this.toolbarGutter}px`);
|
|
32264
32312
|
this.mountContainer?.style.setProperty("--vela-scale-gutter", `${this.rightAxisW}px`);
|
|
32265
32313
|
}
|
|
32314
|
+
/** Publish the price pane's vertical insets as `--vela-price-pane-top` /
|
|
32315
|
+
* `--vela-price-pane-bottom` on the mount container, so the symbol watermark
|
|
32316
|
+
* (and any other host overlay) can clip to the price pane instead of spanning
|
|
32317
|
+
* study panes and the time axis. A maximized study pane collapses the box to
|
|
32318
|
+
* zero height — the mark does not appear on a study. */
|
|
32319
|
+
publishPricePaneBounds() {
|
|
32320
|
+
if (!this.mountContainer) return;
|
|
32321
|
+
const plotH = this.coords.height + TIME_AXIS_H;
|
|
32322
|
+
const price = this.scene.panes.get(PRICE_PANE_ID2);
|
|
32323
|
+
const top = price ? price.bounds.top : 0;
|
|
32324
|
+
const height = price ? price.bounds.height : this.coords.height;
|
|
32325
|
+
const bottom = Math.max(0, plotH - (top + height));
|
|
32326
|
+
this.mountContainer.style.setProperty("--vela-price-pane-top", `${top}px`);
|
|
32327
|
+
this.mountContainer.style.setProperty("--vela-price-pane-bottom", `${bottom}px`);
|
|
32328
|
+
}
|
|
32266
32329
|
/** The built-in mark, or the host's own when one is set. */
|
|
32267
32330
|
buildAttributionEl() {
|
|
32268
32331
|
return this.attributionHtml !== null ? createCustomMark(document, this.attributionHtml, this.theme.background) : createAttributionMark(document, this.theme.background);
|
|
@@ -33326,17 +33389,17 @@ var STYLE_ID26 = "vela-widget-watermark";
|
|
|
33326
33389
|
var CSS22 = `
|
|
33327
33390
|
.vela-watermark {
|
|
33328
33391
|
position: absolute;
|
|
33329
|
-
/* Insets follow the renderer-published gutters
|
|
33330
|
-
*
|
|
33331
|
-
*
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
bottom: 0;
|
|
33392
|
+
/* Insets follow the renderer-published gutters AND the price-pane vertical
|
|
33393
|
+
* bounds (mount container), so the mark centers on the PRICE PANE \u2014 never
|
|
33394
|
+
* the study panes below, the drawings toolbar, or the price scale. */
|
|
33395
|
+
top: var(--vela-price-pane-top, 0px);
|
|
33396
|
+
bottom: var(--vela-price-pane-bottom, 0px);
|
|
33335
33397
|
left: var(--vela-toolbar-gutter, 0px);
|
|
33336
33398
|
right: var(--vela-scale-gutter, 0px);
|
|
33337
33399
|
display: flex;
|
|
33338
33400
|
align-items: center;
|
|
33339
33401
|
justify-content: center;
|
|
33402
|
+
overflow: hidden;
|
|
33340
33403
|
pointer-events: none;
|
|
33341
33404
|
z-index: 1;
|
|
33342
33405
|
color: var(--vela-fg);
|
|
@@ -33391,7 +33454,7 @@ var Watermark = class {
|
|
|
33391
33454
|
this.text.textContent = symbol ? `${parseSymbol(symbol).ticker} \xB7 ${timeframeLabel(timeframe)}` : "";
|
|
33392
33455
|
this.fit();
|
|
33393
33456
|
}
|
|
33394
|
-
/** Measure the text at the cap and shrink it to the
|
|
33457
|
+
/** Measure the text at the cap and shrink it to the price pane's width. */
|
|
33395
33458
|
fit() {
|
|
33396
33459
|
if (this.el.clientWidth <= 0 || !this.text.textContent) return;
|
|
33397
33460
|
this.el.style.fontSize = `${MAX_FONT_PX}px`;
|
package/dist/workspace.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { WidgetHistory, prefixedSymbol, Watermark, Statusline, ChartContextMenu, statuslineInkOf, indicatorLedger, Glider, localStorageAdapter, decodeState, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, Toast, Bottombar, MobileBar, DrawingPill, LayoutModeController, toolShortcutHints, resolveIndicators, sanitizeState, encodeState, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp } from './chunk-
|
|
2
|
-
export { decodeState, encodeState, sanitizeState } from './chunk-
|
|
3
|
-
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs, priceStyleIds } from './chunk-
|
|
4
|
-
import { resolveEngines, legendActionsProviderFor, rendererDefaults, widgetActions, widgetAttachments } from './chunk-
|
|
1
|
+
import { WidgetHistory, prefixedSymbol, Watermark, Statusline, ChartContextMenu, statuslineInkOf, indicatorLedger, Glider, localStorageAdapter, decodeState, SymbolPicker, IndicatorPicker, TimeframeQuick, Topbar, PanelDock, ObjectTree, DataWindow, Toast, Bottombar, MobileBar, DrawingPill, LayoutModeController, toolShortcutHints, resolveIndicators, sanitizeState, encodeState, TimeframeDrawer, RANGE_PRESETS, DrawingsDrawer, MoreDrawer, priceStyleIcon, priceStyleLabel, TimezoneDrawer, PriceScaleDrawer, ZOOM_IN, ZOOM_OUT, PAN_FAST, ShortcutsHelp } from './chunk-EY63XBFZ.js';
|
|
2
|
+
export { decodeState, encodeState, sanitizeState } from './chunk-EY63XBFZ.js';
|
|
3
|
+
import { parseSymbol, Vela, normalizeTimezone, TypedEventBus, MultiProviderFeed, resolveTheme, createCustomMark, createAttributionMark, DrawingToolbar, defaultToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs, priceStyleIds } from './chunk-L5NTMWPP.js';
|
|
4
|
+
import { resolveEngines, legendActionsProviderFor, rendererDefaults, widgetActions, widgetAttachments } from './chunk-WJKLBYRM.js';
|
|
5
5
|
import { applyPlotOverlayTokens, ensureUIHost, KeymapManager, Menu, isEditableTarget } from './chunk-P556H6EA.js';
|
|
6
6
|
import './chunk-ATPU5CI6.js';
|
|
7
7
|
import { registerIcon, svg16, injectStyles } from './chunk-LJLZR44Y.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luxalgo/vela",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Open-source charting library with a native high-performance renderer, drawing tools, pluggable chart types and pluggable scripting engines.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://luxalgo.com/vela",
|