@pipsend/charts 1.2.1 → 1.2.2

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.
@@ -17472,6 +17472,20 @@
17472
17472
  this._private__setupInteractionHandlers();
17473
17473
  }
17474
17474
  }
17475
+ /**
17476
+ * Resolve the effective title: formatTitle(price) wins over the static title.
17477
+ */
17478
+ _private__resolveTitle() {
17479
+ if (this._private__options.formatTitle) {
17480
+ try {
17481
+ return this._private__options.formatTitle(this._private__options.price);
17482
+ }
17483
+ catch (error) {
17484
+ console.error('Error in formatTitle:', error);
17485
+ }
17486
+ }
17487
+ return this._private__options.title || '';
17488
+ }
17475
17489
  _private__createPriceLine() {
17476
17490
  this._private__originalColor = this._private__options.color;
17477
17491
  this._private__priceLine = this._private__series.createPriceLine({
@@ -17480,7 +17494,7 @@
17480
17494
  lineWidth: this._private__options.lineWidth,
17481
17495
  lineStyle: this._private__options.lineStyle,
17482
17496
  axisLabelVisible: this._private__options.axisLabelVisible,
17483
- title: this._private__options.title || '',
17497
+ title: this._private__resolveTitle(),
17484
17498
  });
17485
17499
  }
17486
17500
  _private__setupInteractionHandlers() {
@@ -17521,22 +17535,28 @@
17521
17535
  // Prevenir que el gráfico se mueva mientras arrastramos la línea
17522
17536
  e.preventDefault();
17523
17537
  e.stopPropagation();
17538
+ return;
17524
17539
  }
17525
- else {
17526
- // Solo mostrar hover si está en el área del gráfico
17527
- if (!this._private__isInChartArea(e)) {
17528
- this._private__setHoverState(false);
17529
- return;
17530
- }
17531
- const price = this._private__getPriceFromY(e.clientY);
17532
- if (this._private__isOnLine(e, price)) {
17533
- this._private__container.style.cursor = this._private__options.draggable ? 'ns-resize' : 'pointer';
17534
- this._private__setHoverState(true);
17535
- }
17536
- else {
17540
+ // Hover state — only mutate cursor for transitions involving THIS line.
17541
+ // Multiple lines can share the same chart element listener (one per line).
17542
+ // Blindly resetting the cursor here would clobber another line's drag/hover.
17543
+ if (!this._private__isInChartArea(e)) {
17544
+ if (this._private__isHovering) {
17537
17545
  this._private__container.style.cursor = 'default';
17538
17546
  this._private__setHoverState(false);
17539
17547
  }
17548
+ return;
17549
+ }
17550
+ const price = this._private__getPriceFromY(e.clientY);
17551
+ const onThisLine = this._private__isOnLine(e, price);
17552
+ if (onThisLine) {
17553
+ this._private__container.style.cursor = this._private__options.draggable ? 'ns-resize' : 'pointer';
17554
+ this._private__setHoverState(true);
17555
+ }
17556
+ else if (this._private__isHovering) {
17557
+ // Only revert when actually leaving — don't override another line's cursor.
17558
+ this._private__container.style.cursor = 'default';
17559
+ this._private__setHoverState(false);
17540
17560
  }
17541
17561
  };
17542
17562
  const handleMouseUp = (e) => {
@@ -17584,7 +17604,8 @@
17584
17604
  this._private__options.onDragEnd(this._private__options.price);
17585
17605
  }
17586
17606
  }
17587
- else {
17607
+ else if (this._private__isHovering) {
17608
+ this._private__container.style.cursor = 'default';
17588
17609
  this._private__setHoverState(false);
17589
17610
  }
17590
17611
  this._private__mouseDownOnLine = false;
@@ -17682,11 +17703,16 @@
17682
17703
  _private__updatePrice(newPrice) {
17683
17704
  this._private__options.price = newPrice;
17684
17705
  if (this._private__priceLine) {
17685
- this._private__priceLine.applyOptions({ price: newPrice });
17706
+ // Re-resolve title so formatTitle reflects the new price.
17707
+ this._private__priceLine.applyOptions({
17708
+ price: newPrice,
17709
+ title: this._private__resolveTitle(),
17710
+ });
17686
17711
  }
17687
17712
  }
17688
17713
  /**
17689
- * Update the price line options
17714
+ * Update the price line options. Any subset of options can be passed.
17715
+ * Title is recomputed from `formatTitle` if available, otherwise from `title`.
17690
17716
  */
17691
17717
  applyOptions(options) {
17692
17718
  this._private__options = { ...this._private__options, ...options };
@@ -17694,14 +17720,36 @@
17694
17720
  if (options.color) {
17695
17721
  this._private__originalColor = options.color;
17696
17722
  }
17697
- if (this._private__priceLine && options.price !== undefined) {
17698
- this._private__priceLine.applyOptions({
17699
- price: options.price,
17700
- color: options.color,
17701
- lineWidth: options.lineWidth,
17702
- lineStyle: options.lineStyle,
17703
- title: options.title,
17704
- });
17723
+ if (!this._private__priceLine)
17724
+ return;
17725
+ // Apply visual options. Any field not in `options` is left untouched on the
17726
+ // underlying price line, except `title` which we always re-resolve so that
17727
+ // formatTitle stays in sync with whatever changed.
17728
+ const patch = {
17729
+ title: this._private__resolveTitle(),
17730
+ };
17731
+ if (options.price !== undefined)
17732
+ patch.price = options.price;
17733
+ if (options.color !== undefined)
17734
+ patch.color = options.color;
17735
+ if (options.lineWidth !== undefined)
17736
+ patch.lineWidth = options.lineWidth;
17737
+ if (options.lineStyle !== undefined)
17738
+ patch.lineStyle = options.lineStyle;
17739
+ this._private__priceLine.applyOptions(patch);
17740
+ }
17741
+ /**
17742
+ * Set the title directly. Use this for updates that don't depend on the
17743
+ * line's price (e.g. live PnL on a fixed entry line). Bypasses formatTitle.
17744
+ */
17745
+ setTitle(text) {
17746
+ this._private__options.title = text;
17747
+ // If a formatter is set we still write the static title to options, but
17748
+ // the visual title comes from the formatter on the next price update.
17749
+ // To make this call effective immediately, we override the rendered title
17750
+ // here unconditionally.
17751
+ if (this._private__priceLine) {
17752
+ this._private__priceLine.applyOptions({ title: text });
17705
17753
  }
17706
17754
  }
17707
17755
  /**
@@ -17711,7 +17759,7 @@
17711
17759
  return this._private__options.price;
17712
17760
  }
17713
17761
  /**
17714
- * Set price programmatically
17762
+ * Set price programmatically. Triggers formatTitle if configured.
17715
17763
  */
17716
17764
  setPrice(price) {
17717
17765
  this._private__updatePrice(price);
@@ -17834,6 +17882,7 @@
17834
17882
  onDragMove: options.onDragMove,
17835
17883
  onDragEnd: options.onDragEnd,
17836
17884
  onClick: options.onClick,
17885
+ formatTitle: options.formatTitle,
17837
17886
  };
17838
17887
  return new DraggablePriceLine(chart, series, lineOptions);
17839
17888
  }
@@ -17469,6 +17469,20 @@ class DraggablePriceLine {
17469
17469
  this._private__setupInteractionHandlers();
17470
17470
  }
17471
17471
  }
17472
+ /**
17473
+ * Resolve the effective title: formatTitle(price) wins over the static title.
17474
+ */
17475
+ _private__resolveTitle() {
17476
+ if (this._private__options.formatTitle) {
17477
+ try {
17478
+ return this._private__options.formatTitle(this._private__options.price);
17479
+ }
17480
+ catch (error) {
17481
+ console.error('Error in formatTitle:', error);
17482
+ }
17483
+ }
17484
+ return this._private__options.title || '';
17485
+ }
17472
17486
  _private__createPriceLine() {
17473
17487
  this._private__originalColor = this._private__options.color;
17474
17488
  this._private__priceLine = this._private__series.createPriceLine({
@@ -17477,7 +17491,7 @@ class DraggablePriceLine {
17477
17491
  lineWidth: this._private__options.lineWidth,
17478
17492
  lineStyle: this._private__options.lineStyle,
17479
17493
  axisLabelVisible: this._private__options.axisLabelVisible,
17480
- title: this._private__options.title || '',
17494
+ title: this._private__resolveTitle(),
17481
17495
  });
17482
17496
  }
17483
17497
  _private__setupInteractionHandlers() {
@@ -17518,22 +17532,28 @@ class DraggablePriceLine {
17518
17532
  // Prevenir que el gráfico se mueva mientras arrastramos la línea
17519
17533
  e.preventDefault();
17520
17534
  e.stopPropagation();
17535
+ return;
17521
17536
  }
17522
- else {
17523
- // Solo mostrar hover si está en el área del gráfico
17524
- if (!this._private__isInChartArea(e)) {
17525
- this._private__setHoverState(false);
17526
- return;
17527
- }
17528
- const price = this._private__getPriceFromY(e.clientY);
17529
- if (this._private__isOnLine(e, price)) {
17530
- this._private__container.style.cursor = this._private__options.draggable ? 'ns-resize' : 'pointer';
17531
- this._private__setHoverState(true);
17532
- }
17533
- else {
17537
+ // Hover state — only mutate cursor for transitions involving THIS line.
17538
+ // Multiple lines can share the same chart element listener (one per line).
17539
+ // Blindly resetting the cursor here would clobber another line's drag/hover.
17540
+ if (!this._private__isInChartArea(e)) {
17541
+ if (this._private__isHovering) {
17534
17542
  this._private__container.style.cursor = 'default';
17535
17543
  this._private__setHoverState(false);
17536
17544
  }
17545
+ return;
17546
+ }
17547
+ const price = this._private__getPriceFromY(e.clientY);
17548
+ const onThisLine = this._private__isOnLine(e, price);
17549
+ if (onThisLine) {
17550
+ this._private__container.style.cursor = this._private__options.draggable ? 'ns-resize' : 'pointer';
17551
+ this._private__setHoverState(true);
17552
+ }
17553
+ else if (this._private__isHovering) {
17554
+ // Only revert when actually leaving — don't override another line's cursor.
17555
+ this._private__container.style.cursor = 'default';
17556
+ this._private__setHoverState(false);
17537
17557
  }
17538
17558
  };
17539
17559
  const handleMouseUp = (e) => {
@@ -17581,7 +17601,8 @@ class DraggablePriceLine {
17581
17601
  this._private__options.onDragEnd(this._private__options.price);
17582
17602
  }
17583
17603
  }
17584
- else {
17604
+ else if (this._private__isHovering) {
17605
+ this._private__container.style.cursor = 'default';
17585
17606
  this._private__setHoverState(false);
17586
17607
  }
17587
17608
  this._private__mouseDownOnLine = false;
@@ -17679,11 +17700,16 @@ class DraggablePriceLine {
17679
17700
  _private__updatePrice(newPrice) {
17680
17701
  this._private__options.price = newPrice;
17681
17702
  if (this._private__priceLine) {
17682
- this._private__priceLine.applyOptions({ price: newPrice });
17703
+ // Re-resolve title so formatTitle reflects the new price.
17704
+ this._private__priceLine.applyOptions({
17705
+ price: newPrice,
17706
+ title: this._private__resolveTitle(),
17707
+ });
17683
17708
  }
17684
17709
  }
17685
17710
  /**
17686
- * Update the price line options
17711
+ * Update the price line options. Any subset of options can be passed.
17712
+ * Title is recomputed from `formatTitle` if available, otherwise from `title`.
17687
17713
  */
17688
17714
  applyOptions(options) {
17689
17715
  this._private__options = { ...this._private__options, ...options };
@@ -17691,14 +17717,36 @@ class DraggablePriceLine {
17691
17717
  if (options.color) {
17692
17718
  this._private__originalColor = options.color;
17693
17719
  }
17694
- if (this._private__priceLine && options.price !== undefined) {
17695
- this._private__priceLine.applyOptions({
17696
- price: options.price,
17697
- color: options.color,
17698
- lineWidth: options.lineWidth,
17699
- lineStyle: options.lineStyle,
17700
- title: options.title,
17701
- });
17720
+ if (!this._private__priceLine)
17721
+ return;
17722
+ // Apply visual options. Any field not in `options` is left untouched on the
17723
+ // underlying price line, except `title` which we always re-resolve so that
17724
+ // formatTitle stays in sync with whatever changed.
17725
+ const patch = {
17726
+ title: this._private__resolveTitle(),
17727
+ };
17728
+ if (options.price !== undefined)
17729
+ patch.price = options.price;
17730
+ if (options.color !== undefined)
17731
+ patch.color = options.color;
17732
+ if (options.lineWidth !== undefined)
17733
+ patch.lineWidth = options.lineWidth;
17734
+ if (options.lineStyle !== undefined)
17735
+ patch.lineStyle = options.lineStyle;
17736
+ this._private__priceLine.applyOptions(patch);
17737
+ }
17738
+ /**
17739
+ * Set the title directly. Use this for updates that don't depend on the
17740
+ * line's price (e.g. live PnL on a fixed entry line). Bypasses formatTitle.
17741
+ */
17742
+ setTitle(text) {
17743
+ this._private__options.title = text;
17744
+ // If a formatter is set we still write the static title to options, but
17745
+ // the visual title comes from the formatter on the next price update.
17746
+ // To make this call effective immediately, we override the rendered title
17747
+ // here unconditionally.
17748
+ if (this._private__priceLine) {
17749
+ this._private__priceLine.applyOptions({ title: text });
17702
17750
  }
17703
17751
  }
17704
17752
  /**
@@ -17708,7 +17756,7 @@ class DraggablePriceLine {
17708
17756
  return this._private__options.price;
17709
17757
  }
17710
17758
  /**
17711
- * Set price programmatically
17759
+ * Set price programmatically. Triggers formatTitle if configured.
17712
17760
  */
17713
17761
  setPrice(price) {
17714
17762
  this._private__updatePrice(price);
@@ -17831,6 +17879,7 @@ function createTradingLine(series, chart, options) {
17831
17879
  onDragMove: options.onDragMove,
17832
17880
  onDragEnd: options.onDragEnd,
17833
17881
  onClick: options.onClick,
17882
+ formatTitle: options.formatTitle,
17834
17883
  };
17835
17884
  return new DraggablePriceLine(chart, series, lineOptions);
17836
17885
  }