acttrader-charts 1.4.0-beta.5 → 1.4.0-beta.6

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/README.md CHANGED
@@ -2272,9 +2272,10 @@ Two details worth knowing:
2272
2272
  | --- | --- |
2273
2273
  | One-finger drag on the chart | Scrolls through time (with momentum) |
2274
2274
  | Pinch | Zooms the time axis |
2275
- | One-finger drag along the time (x) axis | Zooms the time axis: drag right to show more bars, left to show fewer |
2275
+ | One-finger drag along the time (x) axis | Zooms the time axis the way TradingView does: the right edge (normally the latest bar) stays put, drag right to zoom in and left to zoom out. Zooming out stops when the oldest bar reaches the left edge, so the candles always fill the full width. The mouse drag on the time axis behaves the same way |
2276
2276
  | One-finger drag on the price (y) axis | Zooms the price axis |
2277
- | One-finger **double tap** on the chart or price axis | Zooms the price axis in one step around the tapped price |
2277
+ | One-finger **double tap** on the chart | Zooms the price axis in one step around the tapped price |
2278
+ | One-finger **double tap** on the price (y) axis | Resets the view, the same as the Reset view button |
2278
2279
  | One-finger **double tap, then drag** up/down | Zooms the price axis continuously: up zooms in, down zooms out (the same direction as the price-axis drag) |
2279
2280
  | Long press | Shows the crosshair |
2280
2281
 
package/dist/index.cjs CHANGED
@@ -37085,6 +37085,9 @@ var DOUBLE_TAP_SLOP_PX = 30;
37085
37085
  var TAP_MAX_MS = 250;
37086
37086
  var TAP_MAX_MOVE_PX = 10;
37087
37087
  var DOUBLE_TAP_ZOOM_STEP = 0.7;
37088
+ var TIME_AXIS_DRAG_SPEED = 2.5;
37089
+ var MIN_VISIBLE_BARS_AXIS = 10;
37090
+ var MAX_VISIBLE_BARS_AXIS = 500;
37088
37091
  function lastIndexAtOrBefore(bars, time) {
37089
37092
  let lo = 0, hi = bars.length - 1, ans = -1;
37090
37093
  while (lo <= hi) {
@@ -37753,19 +37756,7 @@ var _ChartEngine = class _ChartEngine {
37753
37756
  );
37754
37757
  this.subPaneScaleFactors.set(this.axisDrag.instanceId, newFactor);
37755
37758
  } else {
37756
- const delta = x - this.axisDrag.startPos;
37757
- const newVisible = Math.max(
37758
- 10,
37759
- Math.min(500, Math.round(this.axisDrag.startSize + delta * 0.5))
37760
- );
37761
- const mid = (this.viewport.startIndex + this.viewport.endIndex) / 2;
37762
- const newStart = Math.max(0, mid - newVisible / 2);
37763
- this.viewport = {
37764
- ...this.viewport,
37765
- startIndex: newStart,
37766
- endIndex: newStart + newVisible
37767
- };
37768
- this._targetViewport = { ...this.viewport };
37759
+ this.applyTimeAxisDrag(x);
37769
37760
  }
37770
37761
  this.drawCanvas.style.cursor = this.axisDrag.axis === "time" ? "ew-resize" : "ns-resize";
37771
37762
  this.scheduleRender();
@@ -38021,7 +38012,13 @@ var _ChartEngine = class _ChartEngine {
38021
38012
  if (lastTap && now - lastTap.at < DOUBLE_TAP_MS && Math.hypot(x - lastTap.x, y - lastTap.y) < DOUBLE_TAP_SLOP_PX && y < priceH && !this._mobileCrosshairActive) {
38022
38013
  e.preventDefault();
38023
38014
  this.panHandler.cancel();
38024
- this.startTapZoom(y, priceH);
38015
+ this.axisDrag = null;
38016
+ if (x >= chartW) {
38017
+ this.resetView();
38018
+ this.scheduleViewportPersist();
38019
+ } else {
38020
+ this.startTapZoom(y, priceH);
38021
+ }
38025
38022
  return;
38026
38023
  }
38027
38024
  const axisTapHit = hitTestAxisTagCluster(x, y, this.axisTagClusterAreas);
@@ -38069,7 +38066,8 @@ var _ChartEngine = class _ChartEngine {
38069
38066
  this.axisDrag = {
38070
38067
  axis: "time",
38071
38068
  startPos: x,
38072
- startSize: this.viewport.endIndex - this.viewport.startIndex
38069
+ startSize: this.viewport.endIndex - this.viewport.startIndex,
38070
+ startEnd: this.viewport.endIndex
38073
38071
  };
38074
38072
  this.scheduleRender();
38075
38073
  return;
@@ -38286,19 +38284,7 @@ var _ChartEngine = class _ChartEngine {
38286
38284
  );
38287
38285
  this.subPaneScaleFactors.set(this.axisDrag.instanceId, newFactor);
38288
38286
  } else {
38289
- const delta = tx - this.axisDrag.startPos;
38290
- const newVisible = Math.max(
38291
- 10,
38292
- Math.min(500, Math.round(this.axisDrag.startSize + delta * 0.5))
38293
- );
38294
- const mid = (this.viewport.startIndex + this.viewport.endIndex) / 2;
38295
- const newStart = Math.max(0, mid - newVisible / 2);
38296
- this.viewport = {
38297
- ...this.viewport,
38298
- startIndex: newStart,
38299
- endIndex: newStart + newVisible
38300
- };
38301
- this._targetViewport = { ...this.viewport };
38287
+ this.applyTimeAxisDrag(tx);
38302
38288
  }
38303
38289
  this.scheduleRender();
38304
38290
  return;
@@ -38716,7 +38702,8 @@ var _ChartEngine = class _ChartEngine {
38716
38702
  this.axisDrag = {
38717
38703
  axis: "time",
38718
38704
  startPos: x,
38719
- startSize: this.viewport.endIndex - this.viewport.startIndex
38705
+ startSize: this.viewport.endIndex - this.viewport.startIndex,
38706
+ startEnd: this.viewport.endIndex
38720
38707
  };
38721
38708
  this.scheduleRender();
38722
38709
  return;
@@ -40306,6 +40293,7 @@ var _ChartEngine = class _ChartEngine {
40306
40293
  endIndex: this.viewport.endIndex + n
40307
40294
  };
40308
40295
  this._targetViewport = { ...this.viewport };
40296
+ if (this.axisDrag?.startEnd !== void 0) this.axisDrag.startEnd += n;
40309
40297
  this.drawingManager.shiftBarIndices(n);
40310
40298
  this.reanchorDrawingsByTimestamp();
40311
40299
  this.recomputeIndicators();
@@ -46938,6 +46926,30 @@ var _ChartEngine = class _ChartEngine {
46938
46926
  const all = this.dataStore.raw;
46939
46927
  return all[all.length - 1]?.close ?? 0;
46940
46928
  }
46929
+ /**
46930
+ * Time-axis drag (mouse or touch), the way TradingView does it: the right
46931
+ * edge — normally the latest bar — stays where it was, dragging right
46932
+ * spreads the bars (zoom in) and left packs more in (zoom out). The scale is
46933
+ * proportional to the drag, and zooming out stops once the oldest bar
46934
+ * reaches the left edge, so the candles always fill the full width.
46935
+ */
46936
+ applyTimeAxisDrag(x) {
46937
+ const drag = this.axisDrag;
46938
+ if (!drag || drag.axis !== "time") return;
46939
+ const { chartW } = this.getChartLayout();
46940
+ const end = drag.startEnd ?? this.viewport.endIndex;
46941
+ const delta = x - drag.startPos;
46942
+ const wanted = drag.startSize * Math.exp(-delta / Math.max(1, chartW) * TIME_AXIS_DRAG_SPEED);
46943
+ const maxVisible = Math.max(MIN_VISIBLE_BARS_AXIS, Math.min(MAX_VISIBLE_BARS_AXIS, end));
46944
+ const newVisible = Math.max(MIN_VISIBLE_BARS_AXIS, Math.min(maxVisible, wanted));
46945
+ this.viewport = {
46946
+ ...this.viewport,
46947
+ startIndex: end - newVisible,
46948
+ endIndex: end
46949
+ };
46950
+ this._targetViewport = { ...this.viewport };
46951
+ this.checkNeedMoreData();
46952
+ }
46941
46953
  /**
46942
46954
  * Arms a one-finger double-tap zoom at pane-local `y`. Locks the current
46943
46955
  * auto-fit range as the manual base so the zoom is relative to what is on