@pipsend/charts 2.3.10 → 2.3.12

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.
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @license
3
- * Pipsend Charts v2.3.10
3
+ * Pipsend Charts v2.3.12
4
4
  * Copyright (c) 2026 Pipsend
5
5
  * Licensed under MIT License
6
6
  * Built on TradingView Lightweight Charts™ (Apache 2.0)
@@ -19309,6 +19309,12 @@ function setVolumeProfileData(indicator, data) {
19309
19309
  }
19310
19310
 
19311
19311
  const CLICK_TOLERANCE_PX = 4;
19312
+ /**
19313
+ * A fingertip never holds still: every tap travels further than a pointer
19314
+ * does, and judging it by the mouse's few pixels turned each one into a tiny
19315
+ * drag, so the tap never arrived.
19316
+ */
19317
+ const TOUCH_CLICK_TOLERANCE_PX = 12;
19312
19318
  /**
19313
19319
  * Single input owner for every trading line on a chart.
19314
19320
  *
@@ -19327,6 +19333,8 @@ class TradingLineController {
19327
19333
  this._private__pointerId = null;
19328
19334
  this._private__pressOrigin = null;
19329
19335
  this._private__pressedLine = null;
19336
+ /** Whether the gesture in flight came from a finger rather than a mouse. */
19337
+ this._private__pressWasTouch = false;
19330
19338
  /** Distance from the pointer to the dragged line when the press landed. */
19331
19339
  this._private__grabOffset = 0;
19332
19340
  /** Latest pointer position in pane coordinates, or null when off the panes. */
@@ -19391,8 +19399,18 @@ class TradingLineController {
19391
19399
  this._private__applyCursor();
19392
19400
  }
19393
19401
  _private__onPointerDown(event) {
19394
- const line = this._private__hoveredId === null ? null : this._private__lines.get(this._private__hoveredId) ?? null;
19402
+ // Hover belongs to the mouse. Touch leaves whatever the last press marked
19403
+ // still marked, so trusting it here grabbed that line again wherever the
19404
+ // next tap landed: every press resolves itself instead.
19405
+ this._private__pressWasTouch = event.pointerType !== 'mouse';
19406
+ let line = this._private__pressWasTouch || this._private__hoveredId === null
19407
+ ? null
19408
+ : this._private__lines.get(this._private__hoveredId) ?? null;
19409
+ if (line === null) {
19410
+ line = this._private__resolveHitAt(event);
19411
+ }
19395
19412
  if (!line) {
19413
+ this._private__clearTouchHover();
19396
19414
  return;
19397
19415
  }
19398
19416
  this._private__pressOrigin = { _internal_x: event.clientX, _internal_y: event.clientY };
@@ -19431,14 +19449,16 @@ class TradingLineController {
19431
19449
  }
19432
19450
  _private__onPointerUp(event) {
19433
19451
  const dragged = this._private__dragging;
19452
+ const wasTouch = this._private__pressWasTouch;
19434
19453
  const pressed = this._private__pressedLine;
19435
19454
  const origin = this._private__pressOrigin;
19436
19455
  this._private__releasePointer();
19437
19456
  this._private__pressedLine = null;
19438
19457
  this._private__pressOrigin = null;
19458
+ const tolerance = wasTouch ? TOUCH_CLICK_TOLERANCE_PX : CLICK_TOLERANCE_PX;
19439
19459
  const moved = origin !== null &&
19440
- (Math.abs(event.clientX - origin._internal_x) > CLICK_TOLERANCE_PX ||
19441
- Math.abs(event.clientY - origin._internal_y) > CLICK_TOLERANCE_PX);
19460
+ (Math.abs(event.clientX - origin._internal_x) > tolerance ||
19461
+ Math.abs(event.clientY - origin._internal_y) > tolerance);
19442
19462
  if (dragged !== null) {
19443
19463
  this._private__dragging = null;
19444
19464
  this._private__grabOffset = 0;
@@ -19452,12 +19472,24 @@ class TradingLineController {
19452
19472
  dragged.click();
19453
19473
  }
19454
19474
  }
19475
+ this._private__clearTouchHover(wasTouch);
19455
19476
  this._private__applyCursor();
19456
19477
  return;
19457
19478
  }
19458
19479
  if (pressed !== null && !moved && pressed.isClickable()) {
19459
19480
  pressed.click();
19460
19481
  }
19482
+ this._private__clearTouchHover(wasTouch);
19483
+ }
19484
+ /** A finger leaves nothing hovered behind it, the way lifting a mouse does. */
19485
+ _private__clearTouchHover(wasTouch = this._private__pressWasTouch) {
19486
+ if (!wasTouch || this._private__hoveredId === null) {
19487
+ return;
19488
+ }
19489
+ const line = this._private__lines.get(this._private__hoveredId) ?? null;
19490
+ this._private__setHovered(null);
19491
+ this._private__setHoveredPart(line, null);
19492
+ this._private__applyCursor();
19461
19493
  }
19462
19494
  /**
19463
19495
  * Abort an in-flight gesture: the line goes back to where it was and no
@@ -19503,9 +19535,38 @@ class TradingLineController {
19503
19535
  return paneY === null ? null : line.priceAt(paneY - this._private__grabOffset);
19504
19536
  }
19505
19537
  /** The pointer's position inside the line's pane, in pane coordinates. */
19506
- _private__paneY(line, event) {
19538
+ /**
19539
+ * The hovered id comes from the crosshair, which touch never moves before it
19540
+ * presses, so the press resolves the target itself.
19541
+ */
19542
+ _private__resolveHitAt(event) {
19543
+ for (const line of this._private__lines.values()) {
19544
+ if (!line.hitTestAt) {
19545
+ continue;
19546
+ }
19547
+ const paneElement = this._private__paneElementOf(line);
19548
+ if (paneElement === null) {
19549
+ continue;
19550
+ }
19551
+ const rect = paneElement.getBoundingClientRect();
19552
+ // A fingertip is far coarser than a pointer, so its targets are widened.
19553
+ const slop = event.pointerType === 'mouse' ? 0 : 12 /* Constants.TouchSlopPx */;
19554
+ const hit = this._private__splitHit(line.hitTestAt(event.clientX - rect.left, event.clientY - rect.top, slop));
19555
+ if (hit === null) {
19556
+ continue;
19557
+ }
19558
+ this._private__setHovered(line.id());
19559
+ this._private__setHoveredPart(line, hit._internal_part);
19560
+ return line;
19561
+ }
19562
+ return null;
19563
+ }
19564
+ _private__paneElementOf(line) {
19507
19565
  const pane = this._private__chart.panes()[line.paneIndex()];
19508
- const paneElement = pane ? pane.getHTMLElement() : null;
19566
+ return pane ? pane.getHTMLElement() : null;
19567
+ }
19568
+ _private__paneY(line, event) {
19569
+ const paneElement = this._private__paneElementOf(line);
19509
19570
  if (paneElement) {
19510
19571
  return event.clientY - paneElement.getBoundingClientRect().top;
19511
19572
  }
@@ -19622,6 +19683,7 @@ let nextLineId = 0;
19622
19683
  * line. Hit testing comes from the engine — the line's id travels as the price
19623
19684
  * line's `externalId` — so the hit area matches what is drawn.
19624
19685
  */
19686
+ const HIT_TOLERANCE_PX$1 = 8;
19625
19687
  class DraggablePriceLine {
19626
19688
  constructor(chart, series, options) {
19627
19689
  this._private__priceLine = null;
@@ -19674,6 +19736,14 @@ class DraggablePriceLine {
19674
19736
  color: hovered ? this._private__options.hoverColor : this._private__originalColor,
19675
19737
  });
19676
19738
  }
19739
+ /**
19740
+ * The engine draws this one, so there is no pane view to ask: a press within
19741
+ * the line's own grab strip counts as a hit.
19742
+ */
19743
+ hitTestAt(x, y, slop = 0) {
19744
+ const coord = this._private__series.priceToCoordinate(this._private__options.price);
19745
+ return coord !== null && Math.abs(y - coord) <= HIT_TOLERANCE_PX$1 + slop ? this._private__id : null;
19746
+ }
19677
19747
  priceAt(paneY) {
19678
19748
  const price = this._private__series.coordinateToPrice(paneY);
19679
19749
  return price === null ? null : price;
@@ -20216,22 +20286,27 @@ class PositionLineRenderer {
20216
20286
  _internal_setData(data) {
20217
20287
  this._private__data = data;
20218
20288
  }
20219
- _internal_hitTest(x, y) {
20289
+ /**
20290
+ * `slop` widens every target by the same amount, for input coarser than a
20291
+ * mouse pointer.
20292
+ */
20293
+ _internal_hitTest(x, y, slop = 0) {
20220
20294
  // The close button sits on top of the label, which sits on top of the
20221
20295
  // line, so the narrowest target is tested first.
20222
20296
  for (const layout of this._private__layouts) {
20223
- if (layout._internal_closable && x >= layout._internal_closeLeft && x <= layout._internal_closeRight &&
20224
- Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20297
+ if (layout._internal_closable && x >= layout._internal_closeLeft - slop && x <= layout._internal_closeRight + slop &&
20298
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20225
20299
  return { _internal_level: layout._internal_level, _internal_part: 'close' };
20226
20300
  }
20227
20301
  }
20228
20302
  for (const layout of this._private__layouts) {
20229
- if (x >= layout._internal_pillLeft && x <= layout._internal_pillRight && Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20303
+ if (x >= layout._internal_pillLeft - slop && x <= layout._internal_pillRight + slop &&
20304
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20230
20305
  return { _internal_level: layout._internal_level, _internal_part: 'body' };
20231
20306
  }
20232
20307
  }
20233
20308
  for (const layout of this._private__layouts) {
20234
- if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */) {
20309
+ if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */ + slop) {
20235
20310
  return { _internal_level: layout._internal_level, _internal_part: 'line' };
20236
20311
  }
20237
20312
  }
@@ -20468,8 +20543,8 @@ class PositionLinePaneView {
20468
20543
  zOrder() {
20469
20544
  return 'top';
20470
20545
  }
20471
- _internal_hitTest(x, y) {
20472
- return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y);
20546
+ _internal_hitTest(x, y, slop = 0) {
20547
+ return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y, slop);
20473
20548
  }
20474
20549
  }
20475
20550
 
@@ -20620,6 +20695,13 @@ class PositionLine {
20620
20695
  * of jumping to sit under it — which matters most when the label has been
20621
20696
  * fanned away from its own line.
20622
20697
  */
20698
+ hitTestAt(x, y, slop = 0) {
20699
+ const hit = this._private__paneView._internal_hitTest(x, y, slop);
20700
+ if (hit === null) {
20701
+ return null;
20702
+ }
20703
+ return this._private__levelOptions(hit._internal_level) === null ? null : `${this._private__id}#${hit._internal_level}:${hit._internal_part}`;
20704
+ }
20623
20705
  dragAnchorY() {
20624
20706
  if (this._private__dragLevel === null) {
20625
20707
  return null;
@@ -29690,6 +29772,7 @@ class DrawingToolsManager {
29690
29772
  this._private__mouseMoveHandler = null;
29691
29773
  this._private__pointerDownHandler = null;
29692
29774
  this._private__pointerUpHandler = null;
29775
+ this._private__pointerMoveHandler = null;
29693
29776
  this._private__pointerCancelHandler = null;
29694
29777
  this._private__lostCaptureHandler = null;
29695
29778
  this._private__windowPointerUpHandler = null;
@@ -30264,10 +30347,12 @@ class DrawingToolsManager {
30264
30347
  if (chartElement) {
30265
30348
  this._private__pointerDownHandler = (event) => this._private__handlePointerDown(event);
30266
30349
  this._private__pointerUpHandler = (event) => this._private__handlePointerUp(event);
30350
+ this._private__pointerMoveHandler = (event) => this._private__handlePointerMove(event);
30267
30351
  this._private__pointerCancelHandler = (event) => this._private__handlePointerUp(event);
30268
30352
  this._private__lostCaptureHandler = (event) => this._private__handleLostPointerCapture(event);
30269
30353
  chartElement.addEventListener('pointerdown', this._private__pointerDownHandler);
30270
30354
  chartElement.addEventListener('pointerup', this._private__pointerUpHandler);
30355
+ chartElement.addEventListener('pointermove', this._private__pointerMoveHandler);
30271
30356
  chartElement.addEventListener('pointercancel', this._private__pointerCancelHandler);
30272
30357
  chartElement.addEventListener('lostpointercapture', this._private__lostCaptureHandler);
30273
30358
  }
@@ -30302,6 +30387,10 @@ class DrawingToolsManager {
30302
30387
  chartElement.removeEventListener('pointerup', this._private__pointerUpHandler);
30303
30388
  this._private__pointerUpHandler = null;
30304
30389
  }
30390
+ if (this._private__pointerMoveHandler) {
30391
+ chartElement.removeEventListener('pointermove', this._private__pointerMoveHandler);
30392
+ this._private__pointerMoveHandler = null;
30393
+ }
30305
30394
  if (this._private__pointerCancelHandler) {
30306
30395
  chartElement.removeEventListener('pointercancel', this._private__pointerCancelHandler);
30307
30396
  this._private__pointerCancelHandler = null;
@@ -30451,6 +30540,36 @@ class DrawingToolsManager {
30451
30540
  // mouse events, and those are what drive the crosshair the drag reads.
30452
30541
  this._private__disableChartInteractions();
30453
30542
  }
30543
+ /**
30544
+ * The drag reads the crosshair, which touch never moves: its move handler
30545
+ * only tries to pan, and the drag has just turned panning off. So touch is
30546
+ * driven straight from the pointer instead.
30547
+ */
30548
+ _private__handlePointerMove(event) {
30549
+ if (!this._private__isDragging || this._private__draggedToolId === null || event.pointerType === 'mouse') {
30550
+ return;
30551
+ }
30552
+ if (this._private__pointerId !== null && event.pointerId !== this._private__pointerId) {
30553
+ return;
30554
+ }
30555
+ const tool = this._private__tools.get(this._private__draggedToolId);
30556
+ if (!tool) {
30557
+ return;
30558
+ }
30559
+ const paneElement = this._private__paneElementOf(tool);
30560
+ if (paneElement === null) {
30561
+ return;
30562
+ }
30563
+ const rect = paneElement.getBoundingClientRect();
30564
+ const series = tool.series();
30565
+ const price = series.coordinateToPrice((event.clientY - rect.top));
30566
+ const time = timeFromCoordinate(this._private__chart, series, event.clientX - rect.left);
30567
+ if (price === null || time === null) {
30568
+ return;
30569
+ }
30570
+ tool.updateDrag(time, price);
30571
+ event.preventDefault();
30572
+ }
30454
30573
  _private__handlePointerUp(event) {
30455
30574
  if (!this._private__isDragging || this._private__draggedToolId === null) {
30456
30575
  return;
@@ -30624,7 +30743,7 @@ const customSeriesDefaultOptions = {
30624
30743
  * Returns the current version as a string. For example `'1.0.0'`.
30625
30744
  */
30626
30745
  function version() {
30627
- return "2.3.10";
30746
+ return "2.3.12";
30628
30747
  }
30629
30748
 
30630
30749
  export { areaSeries as AreaSeries, ArrowTool, barSeries as BarSeries, baselineSeries as BaselineSeries, BrushTool, candlestickSeries as CandlestickSeries, CircleTool, ColorType, CrossLineTool, CrosshairMode, DEFAULT_SESSIONS, DraggablePriceLine, DrawingToolsManager, EXTENDED_FIBONACCI_RATIOS, FibonacciCalculator, FibonacciExtensionTool, FibonacciFanTool, FibonacciTool, GanttTool, histogramSeries as HistogramSeries, HorizontalLineTool, InteractiveLineManager, LastPriceAnimationMode, lineSeries as LineSeries, LineStyle, LineType, MismatchDirection, ParallelChannelTool, PitchforkTool, PolygonTool, PositionCalculator, PositionLine, PositionMarkersManager, PositionTool, PriceLineSource, PriceScaleMode, RectangleTool, RulerCalculator, RulerTool, STANDARD_FIBONACCI_RATIOS, TextTool, TickMarkType, TrackingModeExitMode, TradingSessionsIndicator, TrendLineTool, VerticalLineTool, VolumeProfileIndicator, applyADX, applyATR, applyBollingerBands, applyCCI, applyDonchianChannels, applyEMA, applyHeikinAshi, applyIchimoku, applyKeltnerChannels, applyMACD, applyMFI, applyOBV, applyParabolicSAR, applyPivotPoints, applyRSI, applySMA, applyStochastic, applySuperTrend, applyVWAP, applyVolume, applyWMA, applyWilliamsR, calculateHeikinAshi, calculatePipConfig, coordinateFromTime, createArrowTool, createBrushTool, createChart, createChartEx, createCircleTool, createCrossLineTool, createFibonacciExtensionTool, createFibonacciFanTool, createFibonacciTool, createGanttTool, createHorizontalLineTool, createImageWatermark, createInteractiveLineManager, createOptionsChart, createParallelChannelTool, createPitchforkTool, createPolygonTool, createPositionLine, createPositionMarkers, createPositionTool, createRectangleTool, createRulerTool, createSeriesMarkers, createTextTool, createTextWatermark, createTradingLine, createTradingSessionsIndicator, createTrendLineTool, createUpDownMarkers, createVerticalLineTool, createVolumeProfileIndicator, createYieldCurveChart, customSeriesDefaultOptions, defaultHorzScaleBehavior, getPipConfig, hideSeriesPaint, isBusinessDay, isUTCTimestamp, setSeriesVolumes, setVolumeProfileData, timeFromCoordinate, version };