@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)
@@ -19705,6 +19705,12 @@
19705
19705
  }
19706
19706
 
19707
19707
  const CLICK_TOLERANCE_PX = 4;
19708
+ /**
19709
+ * A fingertip never holds still: every tap travels further than a pointer
19710
+ * does, and judging it by the mouse's few pixels turned each one into a tiny
19711
+ * drag, so the tap never arrived.
19712
+ */
19713
+ const TOUCH_CLICK_TOLERANCE_PX = 12;
19708
19714
  /**
19709
19715
  * Single input owner for every trading line on a chart.
19710
19716
  *
@@ -19723,6 +19729,8 @@
19723
19729
  this._private__pointerId = null;
19724
19730
  this._private__pressOrigin = null;
19725
19731
  this._private__pressedLine = null;
19732
+ /** Whether the gesture in flight came from a finger rather than a mouse. */
19733
+ this._private__pressWasTouch = false;
19726
19734
  /** Distance from the pointer to the dragged line when the press landed. */
19727
19735
  this._private__grabOffset = 0;
19728
19736
  /** Latest pointer position in pane coordinates, or null when off the panes. */
@@ -19787,8 +19795,18 @@
19787
19795
  this._private__applyCursor();
19788
19796
  }
19789
19797
  _private__onPointerDown(event) {
19790
- const line = this._private__hoveredId === null ? null : this._private__lines.get(this._private__hoveredId) ?? null;
19798
+ // Hover belongs to the mouse. Touch leaves whatever the last press marked
19799
+ // still marked, so trusting it here grabbed that line again wherever the
19800
+ // next tap landed: every press resolves itself instead.
19801
+ this._private__pressWasTouch = event.pointerType !== 'mouse';
19802
+ let line = this._private__pressWasTouch || this._private__hoveredId === null
19803
+ ? null
19804
+ : this._private__lines.get(this._private__hoveredId) ?? null;
19805
+ if (line === null) {
19806
+ line = this._private__resolveHitAt(event);
19807
+ }
19791
19808
  if (!line) {
19809
+ this._private__clearTouchHover();
19792
19810
  return;
19793
19811
  }
19794
19812
  this._private__pressOrigin = { _internal_x: event.clientX, _internal_y: event.clientY };
@@ -19827,14 +19845,16 @@
19827
19845
  }
19828
19846
  _private__onPointerUp(event) {
19829
19847
  const dragged = this._private__dragging;
19848
+ const wasTouch = this._private__pressWasTouch;
19830
19849
  const pressed = this._private__pressedLine;
19831
19850
  const origin = this._private__pressOrigin;
19832
19851
  this._private__releasePointer();
19833
19852
  this._private__pressedLine = null;
19834
19853
  this._private__pressOrigin = null;
19854
+ const tolerance = wasTouch ? TOUCH_CLICK_TOLERANCE_PX : CLICK_TOLERANCE_PX;
19835
19855
  const moved = origin !== null &&
19836
- (Math.abs(event.clientX - origin._internal_x) > CLICK_TOLERANCE_PX ||
19837
- Math.abs(event.clientY - origin._internal_y) > CLICK_TOLERANCE_PX);
19856
+ (Math.abs(event.clientX - origin._internal_x) > tolerance ||
19857
+ Math.abs(event.clientY - origin._internal_y) > tolerance);
19838
19858
  if (dragged !== null) {
19839
19859
  this._private__dragging = null;
19840
19860
  this._private__grabOffset = 0;
@@ -19848,12 +19868,24 @@
19848
19868
  dragged.click();
19849
19869
  }
19850
19870
  }
19871
+ this._private__clearTouchHover(wasTouch);
19851
19872
  this._private__applyCursor();
19852
19873
  return;
19853
19874
  }
19854
19875
  if (pressed !== null && !moved && pressed.isClickable()) {
19855
19876
  pressed.click();
19856
19877
  }
19878
+ this._private__clearTouchHover(wasTouch);
19879
+ }
19880
+ /** A finger leaves nothing hovered behind it, the way lifting a mouse does. */
19881
+ _private__clearTouchHover(wasTouch = this._private__pressWasTouch) {
19882
+ if (!wasTouch || this._private__hoveredId === null) {
19883
+ return;
19884
+ }
19885
+ const line = this._private__lines.get(this._private__hoveredId) ?? null;
19886
+ this._private__setHovered(null);
19887
+ this._private__setHoveredPart(line, null);
19888
+ this._private__applyCursor();
19857
19889
  }
19858
19890
  /**
19859
19891
  * Abort an in-flight gesture: the line goes back to where it was and no
@@ -19899,9 +19931,38 @@
19899
19931
  return paneY === null ? null : line.priceAt(paneY - this._private__grabOffset);
19900
19932
  }
19901
19933
  /** The pointer's position inside the line's pane, in pane coordinates. */
19902
- _private__paneY(line, event) {
19934
+ /**
19935
+ * The hovered id comes from the crosshair, which touch never moves before it
19936
+ * presses, so the press resolves the target itself.
19937
+ */
19938
+ _private__resolveHitAt(event) {
19939
+ for (const line of this._private__lines.values()) {
19940
+ if (!line.hitTestAt) {
19941
+ continue;
19942
+ }
19943
+ const paneElement = this._private__paneElementOf(line);
19944
+ if (paneElement === null) {
19945
+ continue;
19946
+ }
19947
+ const rect = paneElement.getBoundingClientRect();
19948
+ // A fingertip is far coarser than a pointer, so its targets are widened.
19949
+ const slop = event.pointerType === 'mouse' ? 0 : 12 /* Constants.TouchSlopPx */;
19950
+ const hit = this._private__splitHit(line.hitTestAt(event.clientX - rect.left, event.clientY - rect.top, slop));
19951
+ if (hit === null) {
19952
+ continue;
19953
+ }
19954
+ this._private__setHovered(line.id());
19955
+ this._private__setHoveredPart(line, hit._internal_part);
19956
+ return line;
19957
+ }
19958
+ return null;
19959
+ }
19960
+ _private__paneElementOf(line) {
19903
19961
  const pane = this._private__chart.panes()[line.paneIndex()];
19904
- const paneElement = pane ? pane.getHTMLElement() : null;
19962
+ return pane ? pane.getHTMLElement() : null;
19963
+ }
19964
+ _private__paneY(line, event) {
19965
+ const paneElement = this._private__paneElementOf(line);
19905
19966
  if (paneElement) {
19906
19967
  return event.clientY - paneElement.getBoundingClientRect().top;
19907
19968
  }
@@ -20018,6 +20079,7 @@
20018
20079
  * line. Hit testing comes from the engine — the line's id travels as the price
20019
20080
  * line's `externalId` — so the hit area matches what is drawn.
20020
20081
  */
20082
+ const HIT_TOLERANCE_PX$1 = 8;
20021
20083
  class DraggablePriceLine {
20022
20084
  constructor(chart, series, options) {
20023
20085
  this._private__priceLine = null;
@@ -20070,6 +20132,14 @@
20070
20132
  color: hovered ? this._private__options.hoverColor : this._private__originalColor,
20071
20133
  });
20072
20134
  }
20135
+ /**
20136
+ * The engine draws this one, so there is no pane view to ask: a press within
20137
+ * the line's own grab strip counts as a hit.
20138
+ */
20139
+ hitTestAt(x, y, slop = 0) {
20140
+ const coord = this._private__series.priceToCoordinate(this._private__options.price);
20141
+ return coord !== null && Math.abs(y - coord) <= HIT_TOLERANCE_PX$1 + slop ? this._private__id : null;
20142
+ }
20073
20143
  priceAt(paneY) {
20074
20144
  const price = this._private__series.coordinateToPrice(paneY);
20075
20145
  return price === null ? null : price;
@@ -20612,22 +20682,27 @@
20612
20682
  _internal_setData(data) {
20613
20683
  this._private__data = data;
20614
20684
  }
20615
- _internal_hitTest(x, y) {
20685
+ /**
20686
+ * `slop` widens every target by the same amount, for input coarser than a
20687
+ * mouse pointer.
20688
+ */
20689
+ _internal_hitTest(x, y, slop = 0) {
20616
20690
  // The close button sits on top of the label, which sits on top of the
20617
20691
  // line, so the narrowest target is tested first.
20618
20692
  for (const layout of this._private__layouts) {
20619
- if (layout._internal_closable && x >= layout._internal_closeLeft && x <= layout._internal_closeRight &&
20620
- Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20693
+ if (layout._internal_closable && x >= layout._internal_closeLeft - slop && x <= layout._internal_closeRight + slop &&
20694
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20621
20695
  return { _internal_level: layout._internal_level, _internal_part: 'close' };
20622
20696
  }
20623
20697
  }
20624
20698
  for (const layout of this._private__layouts) {
20625
- if (x >= layout._internal_pillLeft && x <= layout._internal_pillRight && Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20699
+ if (x >= layout._internal_pillLeft - slop && x <= layout._internal_pillRight + slop &&
20700
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20626
20701
  return { _internal_level: layout._internal_level, _internal_part: 'body' };
20627
20702
  }
20628
20703
  }
20629
20704
  for (const layout of this._private__layouts) {
20630
- if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */) {
20705
+ if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */ + slop) {
20631
20706
  return { _internal_level: layout._internal_level, _internal_part: 'line' };
20632
20707
  }
20633
20708
  }
@@ -20864,8 +20939,8 @@
20864
20939
  zOrder() {
20865
20940
  return 'top';
20866
20941
  }
20867
- _internal_hitTest(x, y) {
20868
- return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y);
20942
+ _internal_hitTest(x, y, slop = 0) {
20943
+ return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y, slop);
20869
20944
  }
20870
20945
  }
20871
20946
 
@@ -21016,6 +21091,13 @@
21016
21091
  * of jumping to sit under it — which matters most when the label has been
21017
21092
  * fanned away from its own line.
21018
21093
  */
21094
+ hitTestAt(x, y, slop = 0) {
21095
+ const hit = this._private__paneView._internal_hitTest(x, y, slop);
21096
+ if (hit === null) {
21097
+ return null;
21098
+ }
21099
+ return this._private__levelOptions(hit._internal_level) === null ? null : `${this._private__id}#${hit._internal_level}:${hit._internal_part}`;
21100
+ }
21019
21101
  dragAnchorY() {
21020
21102
  if (this._private__dragLevel === null) {
21021
21103
  return null;
@@ -30086,6 +30168,7 @@
30086
30168
  this._private__mouseMoveHandler = null;
30087
30169
  this._private__pointerDownHandler = null;
30088
30170
  this._private__pointerUpHandler = null;
30171
+ this._private__pointerMoveHandler = null;
30089
30172
  this._private__pointerCancelHandler = null;
30090
30173
  this._private__lostCaptureHandler = null;
30091
30174
  this._private__windowPointerUpHandler = null;
@@ -30660,10 +30743,12 @@
30660
30743
  if (chartElement) {
30661
30744
  this._private__pointerDownHandler = (event) => this._private__handlePointerDown(event);
30662
30745
  this._private__pointerUpHandler = (event) => this._private__handlePointerUp(event);
30746
+ this._private__pointerMoveHandler = (event) => this._private__handlePointerMove(event);
30663
30747
  this._private__pointerCancelHandler = (event) => this._private__handlePointerUp(event);
30664
30748
  this._private__lostCaptureHandler = (event) => this._private__handleLostPointerCapture(event);
30665
30749
  chartElement.addEventListener('pointerdown', this._private__pointerDownHandler);
30666
30750
  chartElement.addEventListener('pointerup', this._private__pointerUpHandler);
30751
+ chartElement.addEventListener('pointermove', this._private__pointerMoveHandler);
30667
30752
  chartElement.addEventListener('pointercancel', this._private__pointerCancelHandler);
30668
30753
  chartElement.addEventListener('lostpointercapture', this._private__lostCaptureHandler);
30669
30754
  }
@@ -30698,6 +30783,10 @@
30698
30783
  chartElement.removeEventListener('pointerup', this._private__pointerUpHandler);
30699
30784
  this._private__pointerUpHandler = null;
30700
30785
  }
30786
+ if (this._private__pointerMoveHandler) {
30787
+ chartElement.removeEventListener('pointermove', this._private__pointerMoveHandler);
30788
+ this._private__pointerMoveHandler = null;
30789
+ }
30701
30790
  if (this._private__pointerCancelHandler) {
30702
30791
  chartElement.removeEventListener('pointercancel', this._private__pointerCancelHandler);
30703
30792
  this._private__pointerCancelHandler = null;
@@ -30847,6 +30936,36 @@
30847
30936
  // mouse events, and those are what drive the crosshair the drag reads.
30848
30937
  this._private__disableChartInteractions();
30849
30938
  }
30939
+ /**
30940
+ * The drag reads the crosshair, which touch never moves: its move handler
30941
+ * only tries to pan, and the drag has just turned panning off. So touch is
30942
+ * driven straight from the pointer instead.
30943
+ */
30944
+ _private__handlePointerMove(event) {
30945
+ if (!this._private__isDragging || this._private__draggedToolId === null || event.pointerType === 'mouse') {
30946
+ return;
30947
+ }
30948
+ if (this._private__pointerId !== null && event.pointerId !== this._private__pointerId) {
30949
+ return;
30950
+ }
30951
+ const tool = this._private__tools.get(this._private__draggedToolId);
30952
+ if (!tool) {
30953
+ return;
30954
+ }
30955
+ const paneElement = this._private__paneElementOf(tool);
30956
+ if (paneElement === null) {
30957
+ return;
30958
+ }
30959
+ const rect = paneElement.getBoundingClientRect();
30960
+ const series = tool.series();
30961
+ const price = series.coordinateToPrice((event.clientY - rect.top));
30962
+ const time = timeFromCoordinate(this._private__chart, series, event.clientX - rect.left);
30963
+ if (price === null || time === null) {
30964
+ return;
30965
+ }
30966
+ tool.updateDrag(time, price);
30967
+ event.preventDefault();
30968
+ }
30850
30969
  _private__handlePointerUp(event) {
30851
30970
  if (!this._private__isDragging || this._private__draggedToolId === null) {
30852
30971
  return;
@@ -31020,7 +31139,7 @@
31020
31139
  * Returns the current version as a string. For example `'1.0.0'`.
31021
31140
  */
31022
31141
  function version() {
31023
- return "2.3.10";
31142
+ return "2.3.12";
31024
31143
  }
31025
31144
 
31026
31145
  var PipsendChartsModule = /*#__PURE__*/Object.freeze({
@@ -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)
@@ -19702,6 +19702,12 @@ function setVolumeProfileData(indicator, data) {
19702
19702
  }
19703
19703
 
19704
19704
  const CLICK_TOLERANCE_PX = 4;
19705
+ /**
19706
+ * A fingertip never holds still: every tap travels further than a pointer
19707
+ * does, and judging it by the mouse's few pixels turned each one into a tiny
19708
+ * drag, so the tap never arrived.
19709
+ */
19710
+ const TOUCH_CLICK_TOLERANCE_PX = 12;
19705
19711
  /**
19706
19712
  * Single input owner for every trading line on a chart.
19707
19713
  *
@@ -19720,6 +19726,8 @@ class TradingLineController {
19720
19726
  this._private__pointerId = null;
19721
19727
  this._private__pressOrigin = null;
19722
19728
  this._private__pressedLine = null;
19729
+ /** Whether the gesture in flight came from a finger rather than a mouse. */
19730
+ this._private__pressWasTouch = false;
19723
19731
  /** Distance from the pointer to the dragged line when the press landed. */
19724
19732
  this._private__grabOffset = 0;
19725
19733
  /** Latest pointer position in pane coordinates, or null when off the panes. */
@@ -19784,8 +19792,18 @@ class TradingLineController {
19784
19792
  this._private__applyCursor();
19785
19793
  }
19786
19794
  _private__onPointerDown(event) {
19787
- const line = this._private__hoveredId === null ? null : this._private__lines.get(this._private__hoveredId) ?? null;
19795
+ // Hover belongs to the mouse. Touch leaves whatever the last press marked
19796
+ // still marked, so trusting it here grabbed that line again wherever the
19797
+ // next tap landed: every press resolves itself instead.
19798
+ this._private__pressWasTouch = event.pointerType !== 'mouse';
19799
+ let line = this._private__pressWasTouch || this._private__hoveredId === null
19800
+ ? null
19801
+ : this._private__lines.get(this._private__hoveredId) ?? null;
19802
+ if (line === null) {
19803
+ line = this._private__resolveHitAt(event);
19804
+ }
19788
19805
  if (!line) {
19806
+ this._private__clearTouchHover();
19789
19807
  return;
19790
19808
  }
19791
19809
  this._private__pressOrigin = { _internal_x: event.clientX, _internal_y: event.clientY };
@@ -19824,14 +19842,16 @@ class TradingLineController {
19824
19842
  }
19825
19843
  _private__onPointerUp(event) {
19826
19844
  const dragged = this._private__dragging;
19845
+ const wasTouch = this._private__pressWasTouch;
19827
19846
  const pressed = this._private__pressedLine;
19828
19847
  const origin = this._private__pressOrigin;
19829
19848
  this._private__releasePointer();
19830
19849
  this._private__pressedLine = null;
19831
19850
  this._private__pressOrigin = null;
19851
+ const tolerance = wasTouch ? TOUCH_CLICK_TOLERANCE_PX : CLICK_TOLERANCE_PX;
19832
19852
  const moved = origin !== null &&
19833
- (Math.abs(event.clientX - origin._internal_x) > CLICK_TOLERANCE_PX ||
19834
- Math.abs(event.clientY - origin._internal_y) > CLICK_TOLERANCE_PX);
19853
+ (Math.abs(event.clientX - origin._internal_x) > tolerance ||
19854
+ Math.abs(event.clientY - origin._internal_y) > tolerance);
19835
19855
  if (dragged !== null) {
19836
19856
  this._private__dragging = null;
19837
19857
  this._private__grabOffset = 0;
@@ -19845,12 +19865,24 @@ class TradingLineController {
19845
19865
  dragged.click();
19846
19866
  }
19847
19867
  }
19868
+ this._private__clearTouchHover(wasTouch);
19848
19869
  this._private__applyCursor();
19849
19870
  return;
19850
19871
  }
19851
19872
  if (pressed !== null && !moved && pressed.isClickable()) {
19852
19873
  pressed.click();
19853
19874
  }
19875
+ this._private__clearTouchHover(wasTouch);
19876
+ }
19877
+ /** A finger leaves nothing hovered behind it, the way lifting a mouse does. */
19878
+ _private__clearTouchHover(wasTouch = this._private__pressWasTouch) {
19879
+ if (!wasTouch || this._private__hoveredId === null) {
19880
+ return;
19881
+ }
19882
+ const line = this._private__lines.get(this._private__hoveredId) ?? null;
19883
+ this._private__setHovered(null);
19884
+ this._private__setHoveredPart(line, null);
19885
+ this._private__applyCursor();
19854
19886
  }
19855
19887
  /**
19856
19888
  * Abort an in-flight gesture: the line goes back to where it was and no
@@ -19896,9 +19928,38 @@ class TradingLineController {
19896
19928
  return paneY === null ? null : line.priceAt(paneY - this._private__grabOffset);
19897
19929
  }
19898
19930
  /** The pointer's position inside the line's pane, in pane coordinates. */
19899
- _private__paneY(line, event) {
19931
+ /**
19932
+ * The hovered id comes from the crosshair, which touch never moves before it
19933
+ * presses, so the press resolves the target itself.
19934
+ */
19935
+ _private__resolveHitAt(event) {
19936
+ for (const line of this._private__lines.values()) {
19937
+ if (!line.hitTestAt) {
19938
+ continue;
19939
+ }
19940
+ const paneElement = this._private__paneElementOf(line);
19941
+ if (paneElement === null) {
19942
+ continue;
19943
+ }
19944
+ const rect = paneElement.getBoundingClientRect();
19945
+ // A fingertip is far coarser than a pointer, so its targets are widened.
19946
+ const slop = event.pointerType === 'mouse' ? 0 : 12 /* Constants.TouchSlopPx */;
19947
+ const hit = this._private__splitHit(line.hitTestAt(event.clientX - rect.left, event.clientY - rect.top, slop));
19948
+ if (hit === null) {
19949
+ continue;
19950
+ }
19951
+ this._private__setHovered(line.id());
19952
+ this._private__setHoveredPart(line, hit._internal_part);
19953
+ return line;
19954
+ }
19955
+ return null;
19956
+ }
19957
+ _private__paneElementOf(line) {
19900
19958
  const pane = this._private__chart.panes()[line.paneIndex()];
19901
- const paneElement = pane ? pane.getHTMLElement() : null;
19959
+ return pane ? pane.getHTMLElement() : null;
19960
+ }
19961
+ _private__paneY(line, event) {
19962
+ const paneElement = this._private__paneElementOf(line);
19902
19963
  if (paneElement) {
19903
19964
  return event.clientY - paneElement.getBoundingClientRect().top;
19904
19965
  }
@@ -20015,6 +20076,7 @@ let nextLineId = 0;
20015
20076
  * line. Hit testing comes from the engine — the line's id travels as the price
20016
20077
  * line's `externalId` — so the hit area matches what is drawn.
20017
20078
  */
20079
+ const HIT_TOLERANCE_PX$1 = 8;
20018
20080
  class DraggablePriceLine {
20019
20081
  constructor(chart, series, options) {
20020
20082
  this._private__priceLine = null;
@@ -20067,6 +20129,14 @@ class DraggablePriceLine {
20067
20129
  color: hovered ? this._private__options.hoverColor : this._private__originalColor,
20068
20130
  });
20069
20131
  }
20132
+ /**
20133
+ * The engine draws this one, so there is no pane view to ask: a press within
20134
+ * the line's own grab strip counts as a hit.
20135
+ */
20136
+ hitTestAt(x, y, slop = 0) {
20137
+ const coord = this._private__series.priceToCoordinate(this._private__options.price);
20138
+ return coord !== null && Math.abs(y - coord) <= HIT_TOLERANCE_PX$1 + slop ? this._private__id : null;
20139
+ }
20070
20140
  priceAt(paneY) {
20071
20141
  const price = this._private__series.coordinateToPrice(paneY);
20072
20142
  return price === null ? null : price;
@@ -20609,22 +20679,27 @@ class PositionLineRenderer {
20609
20679
  _internal_setData(data) {
20610
20680
  this._private__data = data;
20611
20681
  }
20612
- _internal_hitTest(x, y) {
20682
+ /**
20683
+ * `slop` widens every target by the same amount, for input coarser than a
20684
+ * mouse pointer.
20685
+ */
20686
+ _internal_hitTest(x, y, slop = 0) {
20613
20687
  // The close button sits on top of the label, which sits on top of the
20614
20688
  // line, so the narrowest target is tested first.
20615
20689
  for (const layout of this._private__layouts) {
20616
- if (layout._internal_closable && x >= layout._internal_closeLeft && x <= layout._internal_closeRight &&
20617
- Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20690
+ if (layout._internal_closable && x >= layout._internal_closeLeft - slop && x <= layout._internal_closeRight + slop &&
20691
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20618
20692
  return { _internal_level: layout._internal_level, _internal_part: 'close' };
20619
20693
  }
20620
20694
  }
20621
20695
  for (const layout of this._private__layouts) {
20622
- if (x >= layout._internal_pillLeft && x <= layout._internal_pillRight && Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2) {
20696
+ if (x >= layout._internal_pillLeft - slop && x <= layout._internal_pillRight + slop &&
20697
+ Math.abs(y - layout._internal_labelY) <= layout._internal_height / 2 + slop) {
20623
20698
  return { _internal_level: layout._internal_level, _internal_part: 'body' };
20624
20699
  }
20625
20700
  }
20626
20701
  for (const layout of this._private__layouts) {
20627
- if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */) {
20702
+ if (Math.abs(y - layout._internal_y) <= 8 /* Constants.LineHitTolerance */ + slop) {
20628
20703
  return { _internal_level: layout._internal_level, _internal_part: 'line' };
20629
20704
  }
20630
20705
  }
@@ -20861,8 +20936,8 @@ class PositionLinePaneView {
20861
20936
  zOrder() {
20862
20937
  return 'top';
20863
20938
  }
20864
- _internal_hitTest(x, y) {
20865
- return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y);
20939
+ _internal_hitTest(x, y, slop = 0) {
20940
+ return this._private__data === null ? null : this._private__renderer._internal_hitTest(x, y, slop);
20866
20941
  }
20867
20942
  }
20868
20943
 
@@ -21013,6 +21088,13 @@ class PositionLine {
21013
21088
  * of jumping to sit under it — which matters most when the label has been
21014
21089
  * fanned away from its own line.
21015
21090
  */
21091
+ hitTestAt(x, y, slop = 0) {
21092
+ const hit = this._private__paneView._internal_hitTest(x, y, slop);
21093
+ if (hit === null) {
21094
+ return null;
21095
+ }
21096
+ return this._private__levelOptions(hit._internal_level) === null ? null : `${this._private__id}#${hit._internal_level}:${hit._internal_part}`;
21097
+ }
21016
21098
  dragAnchorY() {
21017
21099
  if (this._private__dragLevel === null) {
21018
21100
  return null;
@@ -30083,6 +30165,7 @@ class DrawingToolsManager {
30083
30165
  this._private__mouseMoveHandler = null;
30084
30166
  this._private__pointerDownHandler = null;
30085
30167
  this._private__pointerUpHandler = null;
30168
+ this._private__pointerMoveHandler = null;
30086
30169
  this._private__pointerCancelHandler = null;
30087
30170
  this._private__lostCaptureHandler = null;
30088
30171
  this._private__windowPointerUpHandler = null;
@@ -30657,10 +30740,12 @@ class DrawingToolsManager {
30657
30740
  if (chartElement) {
30658
30741
  this._private__pointerDownHandler = (event) => this._private__handlePointerDown(event);
30659
30742
  this._private__pointerUpHandler = (event) => this._private__handlePointerUp(event);
30743
+ this._private__pointerMoveHandler = (event) => this._private__handlePointerMove(event);
30660
30744
  this._private__pointerCancelHandler = (event) => this._private__handlePointerUp(event);
30661
30745
  this._private__lostCaptureHandler = (event) => this._private__handleLostPointerCapture(event);
30662
30746
  chartElement.addEventListener('pointerdown', this._private__pointerDownHandler);
30663
30747
  chartElement.addEventListener('pointerup', this._private__pointerUpHandler);
30748
+ chartElement.addEventListener('pointermove', this._private__pointerMoveHandler);
30664
30749
  chartElement.addEventListener('pointercancel', this._private__pointerCancelHandler);
30665
30750
  chartElement.addEventListener('lostpointercapture', this._private__lostCaptureHandler);
30666
30751
  }
@@ -30695,6 +30780,10 @@ class DrawingToolsManager {
30695
30780
  chartElement.removeEventListener('pointerup', this._private__pointerUpHandler);
30696
30781
  this._private__pointerUpHandler = null;
30697
30782
  }
30783
+ if (this._private__pointerMoveHandler) {
30784
+ chartElement.removeEventListener('pointermove', this._private__pointerMoveHandler);
30785
+ this._private__pointerMoveHandler = null;
30786
+ }
30698
30787
  if (this._private__pointerCancelHandler) {
30699
30788
  chartElement.removeEventListener('pointercancel', this._private__pointerCancelHandler);
30700
30789
  this._private__pointerCancelHandler = null;
@@ -30844,6 +30933,36 @@ class DrawingToolsManager {
30844
30933
  // mouse events, and those are what drive the crosshair the drag reads.
30845
30934
  this._private__disableChartInteractions();
30846
30935
  }
30936
+ /**
30937
+ * The drag reads the crosshair, which touch never moves: its move handler
30938
+ * only tries to pan, and the drag has just turned panning off. So touch is
30939
+ * driven straight from the pointer instead.
30940
+ */
30941
+ _private__handlePointerMove(event) {
30942
+ if (!this._private__isDragging || this._private__draggedToolId === null || event.pointerType === 'mouse') {
30943
+ return;
30944
+ }
30945
+ if (this._private__pointerId !== null && event.pointerId !== this._private__pointerId) {
30946
+ return;
30947
+ }
30948
+ const tool = this._private__tools.get(this._private__draggedToolId);
30949
+ if (!tool) {
30950
+ return;
30951
+ }
30952
+ const paneElement = this._private__paneElementOf(tool);
30953
+ if (paneElement === null) {
30954
+ return;
30955
+ }
30956
+ const rect = paneElement.getBoundingClientRect();
30957
+ const series = tool.series();
30958
+ const price = series.coordinateToPrice((event.clientY - rect.top));
30959
+ const time = timeFromCoordinate(this._private__chart, series, event.clientX - rect.left);
30960
+ if (price === null || time === null) {
30961
+ return;
30962
+ }
30963
+ tool.updateDrag(time, price);
30964
+ event.preventDefault();
30965
+ }
30847
30966
  _private__handlePointerUp(event) {
30848
30967
  if (!this._private__isDragging || this._private__draggedToolId === null) {
30849
30968
  return;
@@ -31017,7 +31136,7 @@ const customSeriesDefaultOptions = {
31017
31136
  * Returns the current version as a string. For example `'1.0.0'`.
31018
31137
  */
31019
31138
  function version() {
31020
- return "2.3.10";
31139
+ return "2.3.12";
31021
31140
  }
31022
31141
 
31023
31142
  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 };