@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/plugin.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ACCENT, a as ACCENT_BRIGHT, B as BEARISH, b as BULLISH, c as BarTransform, d as BasePaintingModulation, C as CATEGORICAL, e as CROSSHAIR, f as ChartTypeDefinition, g as ChartTypeSettingsInstance, h as ChartTypeSettingsSection, i as ChartTypeSettingsSubsection, D as DrawingTypeMeta, H as HIGHLIGHT, I as INFO, j as INVALID, k as IdentifiableKind, M as MARKER, N as NEUTRAL, l as NormalizedSettingsRow, R as RendererLayerArgs, m as RendererLayerDefinition, n as RendererLayerInstance, S as SERIES_LINE, o as SESSION_OFF, p as SESSION_POST, q as SESSION_PRE, r as SLATE, s as SLATE_DEEP, t as SeriesDataEngine, u as SeriesDataEngineHost, v as SettingsInlineControl, w as SettingsRowCondition, x as SettingsRowDescriptor, y as SettingsRowInlineNumber, z as SettingsRowSwatch, E as SettingsRowValueKey, F as SettingsRowWhen, G as SettingsRowWidth, J as SettingsSelectOption, K as SettingsValueRow, T as TRADE_EXIT, L as TRADE_LONG, O as TRADE_SHORT, V as VALID, W as WARNING, P as categoricalColor, Q as chartType, U as chartTypes, Z as drawingTypes, _ as getDrawingType, $ as normalizeSettingsRow, a0 as registerChartType, a2 as registerRendererDefaults, a3 as registerRendererLayer, a4 as rendererDefaults, a5 as rendererLayers, a6 as settingsRowValueKeys, a7 as stableSeriesId, a8 as tickerModifierIds, a9 as unregisterChartType, aa as unregisterRendererDefaults, ab as unregisterRendererLayer } from './plugin-CnNd7cuF.js';
1
+ export { A as ACCENT, a as ACCENT_BRIGHT, B as BEARISH, b as BULLISH, c as BarTransform, d as BasePaintingModulation, C as CATEGORICAL, e as CROSSHAIR, f as ChartTypeDefinition, g as ChartTypeSettingsInstance, h as ChartTypeSettingsSection, i as ChartTypeSettingsSubsection, D as DrawingTypeMeta, H as HIGHLIGHT, I as INFO, j as INVALID, k as IdentifiableKind, M as MARKER, N as NEUTRAL, l as NormalizedSettingsRow, R as RendererLayerArgs, m as RendererLayerDefinition, n as RendererLayerInstance, S as SERIES_LINE, o as SESSION_OFF, p as SESSION_POST, q as SESSION_PRE, r as SLATE, s as SLATE_DEEP, t as SeriesDataEngine, u as SeriesDataEngineHost, v as SettingsInlineControl, w as SettingsRowCondition, x as SettingsRowDescriptor, y as SettingsRowInlineNumber, z as SettingsRowSwatch, E as SettingsRowValueKey, F as SettingsRowWhen, G as SettingsRowWidth, J as SettingsSelectOption, K as SettingsValueRow, T as TRADE_EXIT, L as TRADE_LONG, O as TRADE_SHORT, V as VALID, W as WARNING, P as categoricalColor, Q as chartType, U as chartTypes, Z as drawingTypes, _ as getDrawingType, $ as normalizeSettingsRow, a0 as registerChartType, a2 as registerRendererDefaults, a3 as registerRendererLayer, a4 as rendererDefaults, a5 as rendererLayers, a6 as settingsRowValueKeys, a7 as stableSeriesId, a8 as tickerModifierIds, a9 as unregisterChartType, aa as unregisterRendererDefaults, ab as unregisterRendererLayer } from './plugin-DP6A4t4o.js';
2
2
  export { B as BarsChangeReason, C as ContextSelect, E as EngineAlert, d as EngineCapabilities, e as EngineContextSnapshot, f as EngineFactory, g as EngineWarning, h as ExecutionHandlers, i as ExecutionMarket, j as ExecutionRequest, k as ExecutionSession, F as FetchSeries, L as LegendActionDescriptor, n as LegendIndicatorInfo, N as NativeIndicator, o as NativeIndicatorContext, p as NativeIndicatorDescriptor, q as NativeIndicatorInfo, r as NativeIndicatorOutput, s as PreparedScript, a as ScriptRun, w as ScriptRunCause, x as ScriptRunResult, S as ScriptingEngine, y as SidePanelButton, z as SidePanelDescriptor, A as SidePanelHandle, G as SidePanelHeader, H as StrategyFill, J as StrategyState, K as StrategyTrade, Q as VisibleBarRange, U as WidgetActionDescriptor, X as WidgetActionTarget, Y as WidgetAttachment, W as WidgetContext, Z as getNativeIndicator, _ as legendActions, a0 as nativeIndicatorTypes, a1 as registerDefaultEngine, a2 as registerLegendAction, a3 as registerNativeIndicator, a4 as registerSidePanel, a5 as registerWidgetAction, a6 as registerWidgetAttachment, a7 as resolveEngines, a8 as sidePanels, a9 as unregisterDefaultEngine, aa as unregisterLegendAction, ab as unregisterNativeIndicator, ac as unregisterSidePanel, ad as unregisterWidgetAction, ae as unregisterWidgetAttachment, af as widgetActions, ag as widgetAttachments } from './contributions-b6AVrqqG.js';
3
3
  export { D as DEFAULT_PANEL_MAX_WIDTH, a as DEFAULT_PANEL_MIN_WIDTH, b as DEFAULT_PANEL_WIDTH, S as SidePanelOptions, c as clampPanelWidth } from './side-panel-CT9ZwIGz.js';
4
4
  export { B as Background, x as BoxFontFamily, y as BoxHAlign, z as BoxTextSize, E as BoxVAlign, F as CandleBarColor, G as CandleSeries, H as CandleStyle, W as DirtyRange, X as DrawingBox, Y as DrawingExtend, _ as DrawingLabel, $ as DrawingLine, a0 as DrawingLinefill, a3 as DrawingPolyline, a5 as DrawingTable, u as DrawingTypeKey, a7 as DrawingXLoc, a9 as Fill, aa as FillGradientStop, ab as IndicatorMeta, j as IndicatorModel, ac as InputSchema, ad as InputType, l as InputValue, ae as LabelStyle, af as LabelYLoc, ag as LineLikeKind, ah as LineLikeSeries, ai as LineLikeStyle, L as LineStyle, aj as MarkerPoint, ak as MarkerSeries, s as Millis, O as OHLCV, g as Pane, an as PaneHint, ao as PaneKind, ap as PolylinePoint, aq as PriceLine, P as PriceStyle, au as Scene, k as ScenePatch, av as SchemaPatch, aw as SeriesKind, ax as SeriesPoint, ay as SeriesSpec, az as SeriesValueDelta, aC as TableCell, aD as TableMerge, aE as TablePosition, aG as TradeExecution, aH as ValuePatch } from './options-XTBpbx0s.js';
package/dist/plugin.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { stableSeriesId } from './chunk-Q3XQHLIH.js';
2
- export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, chartType, chartTypes, clampPanelWidth, drawingTypes, getDrawingType, getNativeIndicator, legendActions, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerLegendAction, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, settingsRowValueKeys, sidePanels, tickerModifierIds, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-B5TIKQJ5.js';
2
+ export { DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_WIDTH, chartType, chartTypes, clampPanelWidth, drawingTypes, getDrawingType, getNativeIndicator, legendActions, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerLegendAction, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resolveEngines, settingsRowValueKeys, sidePanels, tickerModifierIds, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments } from './chunk-WJKLBYRM.js';
3
3
  export { ACCENT, ACCENT_BRIGHT, BEARISH, BULLISH, CATEGORICAL, CROSSHAIR, HIGHLIGHT, INFO, INVALID, MARKER, NEUTRAL, SERIES_LINE, SESSION_OFF, SESSION_POST, SESSION_PRE, SLATE, SLATE_DEEP, TRADE_EXIT, TRADE_LONG, TRADE_SHORT, VALID, WARNING, categoricalColor, iconMarkup, registerIcon } from './chunk-LJLZR44Y.js';
@@ -14008,7 +14008,7 @@ void main() {
14008
14008
  var DOUBLE_TAP_MS = 350;
14009
14009
  var DOUBLE_TAP_SLOP = 30;
14010
14010
  var TIME_SCALE_K = 4e-3;
14011
- var WHEEL_ZOOM_K = 25e-4;
14011
+ var WHEEL_ZOOM_K = 4e-3;
14012
14012
  function wheelZoomAnchor(coords, cursorX, rightEdge) {
14013
14013
  if (rightEdge) return { logical: coords.rightEdgeLogical, x: coords.width };
14014
14014
  return { logical: coords.xToLogical(cursorX), x: cursorX };
@@ -14062,6 +14062,8 @@ void main() {
14062
14062
  // smoothed pointer velocity, px/ms
14063
14063
  this.middleDeleted = false;
14064
14064
  // the last middle press deleted a drawing (suppress autoscroll/paste)
14065
+ this.rightCancelled = false;
14066
+ // the last right press cancelled a placement (suppress the context menu)
14065
14067
  // Last cursor position over the element (NaN once it leaves) — lets a modifier
14066
14068
  // press/release re-shape the drawings preview with the pointer stationary.
14067
14069
  this.cursorX = NaN;
@@ -14086,6 +14088,14 @@ void main() {
14086
14088
  this.onMiddleGuard = (e) => {
14087
14089
  if (e.button === 1 && this.middleDeleted) e.preventDefault();
14088
14090
  };
14091
+ /** A right press that cancelled a placement must not ALSO open the host's chart
14092
+ * context menu — swallow its companion event before it bubbles to the host. */
14093
+ this.onContextGuard = (e) => {
14094
+ if (!this.rightCancelled) return;
14095
+ this.rightCancelled = false;
14096
+ e.preventDefault();
14097
+ e.stopPropagation();
14098
+ };
14089
14099
  /** A modifier press/release with the pointer stationary: re-issue the last cursor
14090
14100
  * position so the placing ghost / drag preview reflects the new state immediately
14091
14101
  * (Shift's 45° angle lock, Ctrl/Cmd's momentary strong magnet). */
@@ -14102,6 +14112,11 @@ void main() {
14102
14112
  if (this.middleDeleted) e.preventDefault();
14103
14113
  return;
14104
14114
  }
14115
+ if (e.button === 2) {
14116
+ this.rightCancelled = this.deps.drawingsCancelPlacement?.() ?? false;
14117
+ if (this.rightCancelled) e.preventDefault();
14118
+ return;
14119
+ }
14105
14120
  if (e.button !== 0) return;
14106
14121
  const { x, y } = this.local(e);
14107
14122
  if (e.pointerType === "touch") {
@@ -14306,6 +14321,7 @@ void main() {
14306
14321
  el.addEventListener("wheel", this.onWheel, { passive: false });
14307
14322
  el.addEventListener("mousedown", this.onMiddleGuard);
14308
14323
  el.addEventListener("auxclick", this.onMiddleGuard);
14324
+ el.addEventListener("contextmenu", this.onContextGuard);
14309
14325
  const win = el.ownerDocument?.defaultView;
14310
14326
  win?.addEventListener("keydown", this.onModifier);
14311
14327
  win?.addEventListener("keyup", this.onModifier);
@@ -14327,6 +14343,7 @@ void main() {
14327
14343
  el.removeEventListener("wheel", this.onWheel);
14328
14344
  el.removeEventListener("mousedown", this.onMiddleGuard);
14329
14345
  el.removeEventListener("auxclick", this.onMiddleGuard);
14346
+ el.removeEventListener("contextmenu", this.onContextGuard);
14330
14347
  this.cancelLongPress();
14331
14348
  this.touches.clear();
14332
14349
  this.el = null;
@@ -15999,8 +16016,11 @@ void main() {
15999
16016
  }
16000
16017
  ctx.font = `${scene.style.fontSize}px ${theme.fontFamily}`;
16001
16018
  ctx.textBaseline = "middle";
16002
- if (coords.barCount === 0) return;
16003
16019
  const panes = scene.orderedPanes();
16020
+ if (coords.barCount === 0) {
16021
+ this.drawPaneSeparators(ctx, scene, theme, fullW, panes);
16022
+ return;
16023
+ }
16004
16024
  const pricePane = panes.find((p) => p.kind === "price") ?? null;
16005
16025
  for (const pane of panes) {
16006
16026
  if (pane.collapsed) continue;
@@ -22158,6 +22178,16 @@ void main() {
22158
22178
  if (this.eraserMode) return "pointer";
22159
22179
  return this.interaction.cursorAt(x, y);
22160
22180
  }
22181
+ /** Right-click while placing: cancel the in-progress drawing and revert to the
22182
+ * pointer — the gesture is an explicit escape, so it disarms even in
22183
+ * stay-in-drawing-mode (where Escape would leave the tool armed). Returns whether
22184
+ * the press was consumed; false lets the host's context menu open normally. */
22185
+ cancelPlacement() {
22186
+ if (!this.interaction.isPlacing()) return false;
22187
+ this.interaction.cancel();
22188
+ if (this.activeTool != null) this.emit({ kind: "arm", type: null });
22189
+ return true;
22190
+ }
22161
22191
  /** Double-click over a drawing → suppress the chart's view reset (single-click already
22162
22192
  * opens settings). Returns true only when a drawing is under the cursor. */
22163
22193
  dblClick(x, y) {
@@ -22642,6 +22672,20 @@ void main() {
22642
22672
  };
22643
22673
 
22644
22674
  // src/renderers/native/layers.ts
22675
+ function foldBaseModulation(acc, next) {
22676
+ if (next == null) return acc;
22677
+ if (acc == null) return { ...next };
22678
+ return {
22679
+ candleBodyScale: minOpt(acc.candleBodyScale, next.candleBodyScale),
22680
+ candleBodyAlpha: minOpt(acc.candleBodyAlpha, next.candleBodyAlpha),
22681
+ gridAlpha: minOpt(acc.gridAlpha, next.gridAlpha)
22682
+ };
22683
+ }
22684
+ function minOpt(a, b) {
22685
+ if (a == null) return b;
22686
+ if (b == null) return a;
22687
+ return Math.min(a, b);
22688
+ }
22645
22689
  var registry3 = /* @__PURE__ */ new Map();
22646
22690
  function registerRendererLayer(def) {
22647
22691
  registry3.set(def.id, def);
@@ -23285,7 +23329,7 @@ void main() {
23285
23329
  this.scrollTargetRO = null;
23286
23330
  // eased rightOffset target while gliding back to the latest bars
23287
23331
  // Distance (px) from the plot's bottom edge to the button — tracks the bottom-most EXPANDED
23288
- // pane like the watermark: when the lower sub-panes collapse it rides up into the open pane.
23332
+ // pane: when the lower sub-panes collapse it rides up into the open pane.
23289
23333
  this.scrollBtnBottomPx = SCROLL_BTN_BOTTOM;
23290
23334
  // Distance (px) from the plot's right edge — clears the FULL scale gutter, which widens when a
23291
23335
  // pane carries merged (own-scale) columns; the constant only clears a single-column scale.
@@ -24252,6 +24296,7 @@ void main() {
24252
24296
  drawingsClaim: (x, y) => this.userDrawings?.claim(x, y) ?? false,
24253
24297
  drawingsMeasureStart: (x, y) => this.userDrawings?.beginMeasureAt(x, y) ?? false,
24254
24298
  drawingsDeleteAt: (x, y) => this.userDrawings?.deleteAt(x, y) ?? false,
24299
+ drawingsCancelPlacement: () => this.userDrawings?.cancelPlacement() ?? false,
24255
24300
  drawingsSnapMode: () => this.snapMode,
24256
24301
  drawingsPointerDown: (x, y, snap, shift) => this.userDrawings?.pointerDown(x, y, snap, shift),
24257
24302
  drawingsPointerMove: (x, y, snap, shift) => this.userDrawings?.pointerMove(x, y, snap, shift),
@@ -24503,6 +24548,8 @@ void main() {
24503
24548
  this.attributionEl = null;
24504
24549
  this.mountContainer?.style.removeProperty("--vela-toolbar-gutter");
24505
24550
  this.mountContainer?.style.removeProperty("--vela-scale-gutter");
24551
+ this.mountContainer?.style.removeProperty("--vela-price-pane-top");
24552
+ this.mountContainer?.style.removeProperty("--vela-price-pane-bottom");
24506
24553
  this.mountContainer = null;
24507
24554
  this.wrapper?.remove();
24508
24555
  }
@@ -25592,19 +25639,18 @@ void main() {
25592
25639
  theme: this.theme
25593
25640
  });
25594
25641
  const nowMs = typeof performance !== "undefined" ? performance.now() : Date.now();
25642
+ let folded = null;
25595
25643
  for (const l of this.extLayers) {
25596
25644
  const args = this.extLayerArgs(l.def.id, pane.scale, pane.bounds, nowMs);
25597
25645
  l.instance.render(args);
25598
- if (l.def.id === this.scene.priceStyle && l.instance.modulateBase) {
25599
- const mod = l.instance.modulateBase(args);
25600
- if (mod) {
25601
- if (mod.candleBodyScale != null) this.backend.candleBodyScale = clamp012(mod.candleBodyScale) || 0.01;
25602
- if (mod.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(mod.candleBodyAlpha) * this.candleBodyAlpha;
25603
- if (mod.gridAlpha != null) this.backend.gridAlpha = clamp012(mod.gridAlpha);
25604
- }
25605
- }
25646
+ folded = foldBaseModulation(folded, l.instance.modulateBase?.(args) ?? null);
25606
25647
  if (this.animZoom && l.instance.animating?.()) this.animator.start();
25607
25648
  }
25649
+ if (folded) {
25650
+ if (folded.candleBodyScale != null) this.backend.candleBodyScale = clamp012(folded.candleBodyScale) || 0.01;
25651
+ if (folded.candleBodyAlpha != null) this.backend.candleBodyAlpha = clamp012(folded.candleBodyAlpha) * this.candleBodyAlpha;
25652
+ if (folded.gridAlpha != null) this.backend.gridAlpha = clamp012(folded.gridAlpha);
25653
+ }
25608
25654
  }
25609
25655
  const li = this.bars.length - 1;
25610
25656
  const liveActual = li >= 0 ? this.bars[li] : void 0;
@@ -25996,6 +26042,7 @@ void main() {
25996
26042
  this.paneControls?.reposition();
25997
26043
  this.repositionScrollButton();
25998
26044
  this.positionAttribution();
26045
+ this.publishPricePaneBounds();
25999
26046
  return;
26000
26047
  }
26001
26048
  const collapsed = panes.filter((p) => p.collapsed);
@@ -26013,9 +26060,10 @@ void main() {
26013
26060
  this.paneControls?.reposition();
26014
26061
  this.repositionScrollButton();
26015
26062
  this.positionAttribution();
26063
+ this.publishPricePaneBounds();
26016
26064
  }
26017
- /** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area (like the
26018
- * watermark): with all lower sub-panes collapsed it settles into the lowest open pane. */
26065
+ /** Pin the scroll-to-realtime button above the bottom-most EXPANDED pane's data area:
26066
+ * with all lower sub-panes collapsed it settles into the lowest open pane. */
26019
26067
  repositionScrollButton() {
26020
26068
  const dataHeight = this.coords.height;
26021
26069
  if (dataHeight <= 0) return;
@@ -26059,6 +26107,21 @@ void main() {
26059
26107
  this.mountContainer?.style.setProperty("--vela-toolbar-gutter", `${this.toolbarGutter}px`);
26060
26108
  this.mountContainer?.style.setProperty("--vela-scale-gutter", `${this.rightAxisW}px`);
26061
26109
  }
26110
+ /** Publish the price pane's vertical insets as `--vela-price-pane-top` /
26111
+ * `--vela-price-pane-bottom` on the mount container, so the symbol watermark
26112
+ * (and any other host overlay) can clip to the price pane instead of spanning
26113
+ * study panes and the time axis. A maximized study pane collapses the box to
26114
+ * zero height — the mark does not appear on a study. */
26115
+ publishPricePaneBounds() {
26116
+ if (!this.mountContainer) return;
26117
+ const plotH = this.coords.height + TIME_AXIS_H;
26118
+ const price = this.scene.panes.get(PRICE_PANE_ID);
26119
+ const top = price ? price.bounds.top : 0;
26120
+ const height = price ? price.bounds.height : this.coords.height;
26121
+ const bottom = Math.max(0, plotH - (top + height));
26122
+ this.mountContainer.style.setProperty("--vela-price-pane-top", `${top}px`);
26123
+ this.mountContainer.style.setProperty("--vela-price-pane-bottom", `${bottom}px`);
26124
+ }
26062
26125
  /** The built-in mark, or the host's own when one is set. */
26063
26126
  buildAttributionEl() {
26064
26127
  return this.attributionHtml !== null ? createCustomMark(document, this.attributionHtml, this.theme.background) : createAttributionMark(document, this.theme.background);