@pipsend/charts 1.2.0 → 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.
- package/dist/pipsend-charts.development.mjs +128 -38
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +128 -38
- package/dist/pipsend-charts.standalone.development.mjs +128 -38
- package/dist/pipsend-charts.standalone.production.js +2 -2
- package/dist/pipsend-charts.standalone.production.mjs +2 -2
- package/dist/typings.d.ts +40 -4
- package/package.json +83 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v1.2.
|
|
3
|
+
* Pipsend Charts v1.2.1
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -17443,8 +17443,9 @@
|
|
|
17443
17443
|
indicator.setVolumeData(volumeMap);
|
|
17444
17444
|
}
|
|
17445
17445
|
|
|
17446
|
+
const CLICK_TOLERANCE_PX = 4;
|
|
17446
17447
|
/**
|
|
17447
|
-
* Draggable Price Line - Línea de precio que se puede arrastrar
|
|
17448
|
+
* Draggable Price Line - Línea de precio que se puede arrastrar y/o hacer click
|
|
17448
17449
|
*/
|
|
17449
17450
|
class DraggablePriceLine {
|
|
17450
17451
|
constructor(chart, series, options) {
|
|
@@ -17454,6 +17455,8 @@
|
|
|
17454
17455
|
this._private__unsubscribeHandlers = [];
|
|
17455
17456
|
this._private__isHovering = false;
|
|
17456
17457
|
this._private__originalColor = '';
|
|
17458
|
+
this._private__mouseDownPos = null;
|
|
17459
|
+
this._private__mouseDownOnLine = false;
|
|
17457
17460
|
this._private__chart = chart;
|
|
17458
17461
|
this._private__series = series;
|
|
17459
17462
|
this._private__options = {
|
|
@@ -17464,10 +17467,25 @@
|
|
|
17464
17467
|
...options,
|
|
17465
17468
|
};
|
|
17466
17469
|
this._private__createPriceLine();
|
|
17467
|
-
if (
|
|
17468
|
-
|
|
17470
|
+
// Set up handlers if line is interactive (draggable or clickable)
|
|
17471
|
+
if (this._private__options.draggable || this._private__options.onClick) {
|
|
17472
|
+
this._private__setupInteractionHandlers();
|
|
17469
17473
|
}
|
|
17470
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
|
+
}
|
|
17471
17489
|
_private__createPriceLine() {
|
|
17472
17490
|
this._private__originalColor = this._private__options.color;
|
|
17473
17491
|
this._private__priceLine = this._private__series.createPriceLine({
|
|
@@ -17476,29 +17494,36 @@
|
|
|
17476
17494
|
lineWidth: this._private__options.lineWidth,
|
|
17477
17495
|
lineStyle: this._private__options.lineStyle,
|
|
17478
17496
|
axisLabelVisible: this._private__options.axisLabelVisible,
|
|
17479
|
-
title: this.
|
|
17497
|
+
title: this._private__resolveTitle(),
|
|
17480
17498
|
});
|
|
17481
17499
|
}
|
|
17482
|
-
|
|
17500
|
+
_private__setupInteractionHandlers() {
|
|
17483
17501
|
const chartElement = this._private__chart.chartElement?.() || document.querySelector('.tv-lightweight-charts');
|
|
17484
17502
|
if (!chartElement)
|
|
17485
17503
|
return;
|
|
17486
17504
|
this._private__container = chartElement;
|
|
17487
17505
|
const handleMouseDown = (e) => {
|
|
17488
|
-
// Solo permitir
|
|
17506
|
+
// Solo permitir interacción desde el área del gráfico (no desde el price axis)
|
|
17489
17507
|
if (!this._private__isInChartArea(e)) {
|
|
17490
17508
|
return;
|
|
17491
17509
|
}
|
|
17492
17510
|
const price = this._private__getPriceFromY(e.clientY);
|
|
17493
|
-
if (this._private__isOnLine(e, price)) {
|
|
17511
|
+
if (!this._private__isOnLine(e, price)) {
|
|
17512
|
+
return;
|
|
17513
|
+
}
|
|
17514
|
+
// Track press for click vs drag detection
|
|
17515
|
+
this._private__mouseDownPos = { _internal_x: e.clientX, _internal_y: e.clientY };
|
|
17516
|
+
this._private__mouseDownOnLine = true;
|
|
17517
|
+
// Only start drag if line is draggable
|
|
17518
|
+
if (this._private__options.draggable) {
|
|
17494
17519
|
this._private__isDragging = true;
|
|
17495
17520
|
this._private__container.style.cursor = 'ns-resize';
|
|
17496
17521
|
if (this._private__options.onDragStart) {
|
|
17497
17522
|
this._private__options.onDragStart(this._private__options.price);
|
|
17498
17523
|
}
|
|
17499
|
-
e.preventDefault();
|
|
17500
|
-
e.stopPropagation();
|
|
17501
17524
|
}
|
|
17525
|
+
e.preventDefault();
|
|
17526
|
+
e.stopPropagation();
|
|
17502
17527
|
};
|
|
17503
17528
|
const handleMouseMove = (e) => {
|
|
17504
17529
|
if (this._private__isDragging) {
|
|
@@ -17510,32 +17535,65 @@
|
|
|
17510
17535
|
// Prevenir que el gráfico se mueva mientras arrastramos la línea
|
|
17511
17536
|
e.preventDefault();
|
|
17512
17537
|
e.stopPropagation();
|
|
17538
|
+
return;
|
|
17513
17539
|
}
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
|
|
17517
|
-
|
|
17518
|
-
|
|
17519
|
-
}
|
|
17520
|
-
const price = this._private__getPriceFromY(e.clientY);
|
|
17521
|
-
if (this._private__isOnLine(e, price)) {
|
|
17522
|
-
this._private__container.style.cursor = 'ns-resize';
|
|
17523
|
-
this._private__setHoverState(true);
|
|
17524
|
-
}
|
|
17525
|
-
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) {
|
|
17526
17545
|
this._private__container.style.cursor = 'default';
|
|
17527
17546
|
this._private__setHoverState(false);
|
|
17528
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);
|
|
17529
17560
|
}
|
|
17530
17561
|
};
|
|
17531
17562
|
const handleMouseUp = (e) => {
|
|
17532
|
-
|
|
17533
|
-
|
|
17563
|
+
const wasDragging = this._private__isDragging;
|
|
17564
|
+
const downOnLine = this._private__mouseDownOnLine;
|
|
17565
|
+
const downPos = this._private__mouseDownPos;
|
|
17566
|
+
// Reset state regardless of outcome
|
|
17567
|
+
this._private__isDragging = false;
|
|
17568
|
+
this._private__mouseDownOnLine = false;
|
|
17569
|
+
this._private__mouseDownPos = null;
|
|
17570
|
+
if (wasDragging) {
|
|
17571
|
+
// Drag-end path
|
|
17534
17572
|
this._private__container.style.cursor = 'default';
|
|
17535
17573
|
this._private__setHoverState(false);
|
|
17536
|
-
|
|
17574
|
+
const movedFromDown = downPos &&
|
|
17575
|
+
(Math.abs(e.clientX - downPos._internal_x) > CLICK_TOLERANCE_PX ||
|
|
17576
|
+
Math.abs(e.clientY - downPos._internal_y) > CLICK_TOLERANCE_PX);
|
|
17577
|
+
// If barely moved, treat as click instead of drag
|
|
17578
|
+
if (!movedFromDown && this._private__options.onClick) {
|
|
17579
|
+
this._private__options.onClick(this._private__options.price);
|
|
17580
|
+
}
|
|
17581
|
+
else if (this._private__options.onDragEnd) {
|
|
17537
17582
|
this._private__options.onDragEnd(this._private__options.price);
|
|
17538
17583
|
}
|
|
17584
|
+
return;
|
|
17585
|
+
}
|
|
17586
|
+
// Pure click path (non-draggable line or draggable that didn't start drag)
|
|
17587
|
+
if (downOnLine && downPos && this._private__options.onClick) {
|
|
17588
|
+
const moved = Math.abs(e.clientX - downPos._internal_x) > CLICK_TOLERANCE_PX ||
|
|
17589
|
+
Math.abs(e.clientY - downPos._internal_y) > CLICK_TOLERANCE_PX;
|
|
17590
|
+
if (!moved) {
|
|
17591
|
+
// Confirm release was still on the line area
|
|
17592
|
+
const price = this._private__getPriceFromY(e.clientY);
|
|
17593
|
+
if (this._private__isOnLine(e, price)) {
|
|
17594
|
+
this._private__options.onClick(this._private__options.price);
|
|
17595
|
+
}
|
|
17596
|
+
}
|
|
17539
17597
|
}
|
|
17540
17598
|
};
|
|
17541
17599
|
const handleMouseLeave = (e) => {
|
|
@@ -17546,9 +17604,12 @@
|
|
|
17546
17604
|
this._private__options.onDragEnd(this._private__options.price);
|
|
17547
17605
|
}
|
|
17548
17606
|
}
|
|
17549
|
-
else {
|
|
17607
|
+
else if (this._private__isHovering) {
|
|
17608
|
+
this._private__container.style.cursor = 'default';
|
|
17550
17609
|
this._private__setHoverState(false);
|
|
17551
17610
|
}
|
|
17611
|
+
this._private__mouseDownOnLine = false;
|
|
17612
|
+
this._private__mouseDownPos = null;
|
|
17552
17613
|
};
|
|
17553
17614
|
this._private__container.addEventListener('mousedown', handleMouseDown);
|
|
17554
17615
|
this._private__container.addEventListener('mousemove', handleMouseMove);
|
|
@@ -17642,11 +17703,16 @@
|
|
|
17642
17703
|
_private__updatePrice(newPrice) {
|
|
17643
17704
|
this._private__options.price = newPrice;
|
|
17644
17705
|
if (this._private__priceLine) {
|
|
17645
|
-
|
|
17706
|
+
// Re-resolve title so formatTitle reflects the new price.
|
|
17707
|
+
this._private__priceLine.applyOptions({
|
|
17708
|
+
price: newPrice,
|
|
17709
|
+
title: this._private__resolveTitle(),
|
|
17710
|
+
});
|
|
17646
17711
|
}
|
|
17647
17712
|
}
|
|
17648
17713
|
/**
|
|
17649
|
-
* 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`.
|
|
17650
17716
|
*/
|
|
17651
17717
|
applyOptions(options) {
|
|
17652
17718
|
this._private__options = { ...this._private__options, ...options };
|
|
@@ -17654,14 +17720,36 @@
|
|
|
17654
17720
|
if (options.color) {
|
|
17655
17721
|
this._private__originalColor = options.color;
|
|
17656
17722
|
}
|
|
17657
|
-
if (this._private__priceLine
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
|
|
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 });
|
|
17665
17753
|
}
|
|
17666
17754
|
}
|
|
17667
17755
|
/**
|
|
@@ -17671,7 +17759,7 @@
|
|
|
17671
17759
|
return this._private__options.price;
|
|
17672
17760
|
}
|
|
17673
17761
|
/**
|
|
17674
|
-
* Set price programmatically
|
|
17762
|
+
* Set price programmatically. Triggers formatTitle if configured.
|
|
17675
17763
|
*/
|
|
17676
17764
|
setPrice(price) {
|
|
17677
17765
|
this._private__updatePrice(price);
|
|
@@ -17793,6 +17881,8 @@
|
|
|
17793
17881
|
onDragStart: options.onDragStart,
|
|
17794
17882
|
onDragMove: options.onDragMove,
|
|
17795
17883
|
onDragEnd: options.onDragEnd,
|
|
17884
|
+
onClick: options.onClick,
|
|
17885
|
+
formatTitle: options.formatTitle,
|
|
17796
17886
|
};
|
|
17797
17887
|
return new DraggablePriceLine(chart, series, lineOptions);
|
|
17798
17888
|
}
|
|
@@ -24863,7 +24953,7 @@
|
|
|
24863
24953
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
24864
24954
|
*/
|
|
24865
24955
|
function version() {
|
|
24866
|
-
return "1.2.
|
|
24956
|
+
return "1.2.1";
|
|
24867
24957
|
}
|
|
24868
24958
|
|
|
24869
24959
|
var PipsendChartsModule = /*#__PURE__*/Object.freeze({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v1.2.
|
|
3
|
+
* Pipsend Charts v1.2.1
|
|
4
4
|
* Copyright (c) 2026 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -17440,8 +17440,9 @@ function setVolumeProfileData(indicator, data) {
|
|
|
17440
17440
|
indicator.setVolumeData(volumeMap);
|
|
17441
17441
|
}
|
|
17442
17442
|
|
|
17443
|
+
const CLICK_TOLERANCE_PX = 4;
|
|
17443
17444
|
/**
|
|
17444
|
-
* Draggable Price Line - Línea de precio que se puede arrastrar
|
|
17445
|
+
* Draggable Price Line - Línea de precio que se puede arrastrar y/o hacer click
|
|
17445
17446
|
*/
|
|
17446
17447
|
class DraggablePriceLine {
|
|
17447
17448
|
constructor(chart, series, options) {
|
|
@@ -17451,6 +17452,8 @@ class DraggablePriceLine {
|
|
|
17451
17452
|
this._private__unsubscribeHandlers = [];
|
|
17452
17453
|
this._private__isHovering = false;
|
|
17453
17454
|
this._private__originalColor = '';
|
|
17455
|
+
this._private__mouseDownPos = null;
|
|
17456
|
+
this._private__mouseDownOnLine = false;
|
|
17454
17457
|
this._private__chart = chart;
|
|
17455
17458
|
this._private__series = series;
|
|
17456
17459
|
this._private__options = {
|
|
@@ -17461,10 +17464,25 @@ class DraggablePriceLine {
|
|
|
17461
17464
|
...options,
|
|
17462
17465
|
};
|
|
17463
17466
|
this._private__createPriceLine();
|
|
17464
|
-
if (
|
|
17465
|
-
|
|
17467
|
+
// Set up handlers if line is interactive (draggable or clickable)
|
|
17468
|
+
if (this._private__options.draggable || this._private__options.onClick) {
|
|
17469
|
+
this._private__setupInteractionHandlers();
|
|
17466
17470
|
}
|
|
17467
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
|
+
}
|
|
17468
17486
|
_private__createPriceLine() {
|
|
17469
17487
|
this._private__originalColor = this._private__options.color;
|
|
17470
17488
|
this._private__priceLine = this._private__series.createPriceLine({
|
|
@@ -17473,29 +17491,36 @@ class DraggablePriceLine {
|
|
|
17473
17491
|
lineWidth: this._private__options.lineWidth,
|
|
17474
17492
|
lineStyle: this._private__options.lineStyle,
|
|
17475
17493
|
axisLabelVisible: this._private__options.axisLabelVisible,
|
|
17476
|
-
title: this.
|
|
17494
|
+
title: this._private__resolveTitle(),
|
|
17477
17495
|
});
|
|
17478
17496
|
}
|
|
17479
|
-
|
|
17497
|
+
_private__setupInteractionHandlers() {
|
|
17480
17498
|
const chartElement = this._private__chart.chartElement?.() || document.querySelector('.tv-lightweight-charts');
|
|
17481
17499
|
if (!chartElement)
|
|
17482
17500
|
return;
|
|
17483
17501
|
this._private__container = chartElement;
|
|
17484
17502
|
const handleMouseDown = (e) => {
|
|
17485
|
-
// Solo permitir
|
|
17503
|
+
// Solo permitir interacción desde el área del gráfico (no desde el price axis)
|
|
17486
17504
|
if (!this._private__isInChartArea(e)) {
|
|
17487
17505
|
return;
|
|
17488
17506
|
}
|
|
17489
17507
|
const price = this._private__getPriceFromY(e.clientY);
|
|
17490
|
-
if (this._private__isOnLine(e, price)) {
|
|
17508
|
+
if (!this._private__isOnLine(e, price)) {
|
|
17509
|
+
return;
|
|
17510
|
+
}
|
|
17511
|
+
// Track press for click vs drag detection
|
|
17512
|
+
this._private__mouseDownPos = { _internal_x: e.clientX, _internal_y: e.clientY };
|
|
17513
|
+
this._private__mouseDownOnLine = true;
|
|
17514
|
+
// Only start drag if line is draggable
|
|
17515
|
+
if (this._private__options.draggable) {
|
|
17491
17516
|
this._private__isDragging = true;
|
|
17492
17517
|
this._private__container.style.cursor = 'ns-resize';
|
|
17493
17518
|
if (this._private__options.onDragStart) {
|
|
17494
17519
|
this._private__options.onDragStart(this._private__options.price);
|
|
17495
17520
|
}
|
|
17496
|
-
e.preventDefault();
|
|
17497
|
-
e.stopPropagation();
|
|
17498
17521
|
}
|
|
17522
|
+
e.preventDefault();
|
|
17523
|
+
e.stopPropagation();
|
|
17499
17524
|
};
|
|
17500
17525
|
const handleMouseMove = (e) => {
|
|
17501
17526
|
if (this._private__isDragging) {
|
|
@@ -17507,32 +17532,65 @@ class DraggablePriceLine {
|
|
|
17507
17532
|
// Prevenir que el gráfico se mueva mientras arrastramos la línea
|
|
17508
17533
|
e.preventDefault();
|
|
17509
17534
|
e.stopPropagation();
|
|
17535
|
+
return;
|
|
17510
17536
|
}
|
|
17511
|
-
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
}
|
|
17517
|
-
const price = this._private__getPriceFromY(e.clientY);
|
|
17518
|
-
if (this._private__isOnLine(e, price)) {
|
|
17519
|
-
this._private__container.style.cursor = 'ns-resize';
|
|
17520
|
-
this._private__setHoverState(true);
|
|
17521
|
-
}
|
|
17522
|
-
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) {
|
|
17523
17542
|
this._private__container.style.cursor = 'default';
|
|
17524
17543
|
this._private__setHoverState(false);
|
|
17525
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);
|
|
17526
17557
|
}
|
|
17527
17558
|
};
|
|
17528
17559
|
const handleMouseUp = (e) => {
|
|
17529
|
-
|
|
17530
|
-
|
|
17560
|
+
const wasDragging = this._private__isDragging;
|
|
17561
|
+
const downOnLine = this._private__mouseDownOnLine;
|
|
17562
|
+
const downPos = this._private__mouseDownPos;
|
|
17563
|
+
// Reset state regardless of outcome
|
|
17564
|
+
this._private__isDragging = false;
|
|
17565
|
+
this._private__mouseDownOnLine = false;
|
|
17566
|
+
this._private__mouseDownPos = null;
|
|
17567
|
+
if (wasDragging) {
|
|
17568
|
+
// Drag-end path
|
|
17531
17569
|
this._private__container.style.cursor = 'default';
|
|
17532
17570
|
this._private__setHoverState(false);
|
|
17533
|
-
|
|
17571
|
+
const movedFromDown = downPos &&
|
|
17572
|
+
(Math.abs(e.clientX - downPos._internal_x) > CLICK_TOLERANCE_PX ||
|
|
17573
|
+
Math.abs(e.clientY - downPos._internal_y) > CLICK_TOLERANCE_PX);
|
|
17574
|
+
// If barely moved, treat as click instead of drag
|
|
17575
|
+
if (!movedFromDown && this._private__options.onClick) {
|
|
17576
|
+
this._private__options.onClick(this._private__options.price);
|
|
17577
|
+
}
|
|
17578
|
+
else if (this._private__options.onDragEnd) {
|
|
17534
17579
|
this._private__options.onDragEnd(this._private__options.price);
|
|
17535
17580
|
}
|
|
17581
|
+
return;
|
|
17582
|
+
}
|
|
17583
|
+
// Pure click path (non-draggable line or draggable that didn't start drag)
|
|
17584
|
+
if (downOnLine && downPos && this._private__options.onClick) {
|
|
17585
|
+
const moved = Math.abs(e.clientX - downPos._internal_x) > CLICK_TOLERANCE_PX ||
|
|
17586
|
+
Math.abs(e.clientY - downPos._internal_y) > CLICK_TOLERANCE_PX;
|
|
17587
|
+
if (!moved) {
|
|
17588
|
+
// Confirm release was still on the line area
|
|
17589
|
+
const price = this._private__getPriceFromY(e.clientY);
|
|
17590
|
+
if (this._private__isOnLine(e, price)) {
|
|
17591
|
+
this._private__options.onClick(this._private__options.price);
|
|
17592
|
+
}
|
|
17593
|
+
}
|
|
17536
17594
|
}
|
|
17537
17595
|
};
|
|
17538
17596
|
const handleMouseLeave = (e) => {
|
|
@@ -17543,9 +17601,12 @@ class DraggablePriceLine {
|
|
|
17543
17601
|
this._private__options.onDragEnd(this._private__options.price);
|
|
17544
17602
|
}
|
|
17545
17603
|
}
|
|
17546
|
-
else {
|
|
17604
|
+
else if (this._private__isHovering) {
|
|
17605
|
+
this._private__container.style.cursor = 'default';
|
|
17547
17606
|
this._private__setHoverState(false);
|
|
17548
17607
|
}
|
|
17608
|
+
this._private__mouseDownOnLine = false;
|
|
17609
|
+
this._private__mouseDownPos = null;
|
|
17549
17610
|
};
|
|
17550
17611
|
this._private__container.addEventListener('mousedown', handleMouseDown);
|
|
17551
17612
|
this._private__container.addEventListener('mousemove', handleMouseMove);
|
|
@@ -17639,11 +17700,16 @@ class DraggablePriceLine {
|
|
|
17639
17700
|
_private__updatePrice(newPrice) {
|
|
17640
17701
|
this._private__options.price = newPrice;
|
|
17641
17702
|
if (this._private__priceLine) {
|
|
17642
|
-
|
|
17703
|
+
// Re-resolve title so formatTitle reflects the new price.
|
|
17704
|
+
this._private__priceLine.applyOptions({
|
|
17705
|
+
price: newPrice,
|
|
17706
|
+
title: this._private__resolveTitle(),
|
|
17707
|
+
});
|
|
17643
17708
|
}
|
|
17644
17709
|
}
|
|
17645
17710
|
/**
|
|
17646
|
-
* 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`.
|
|
17647
17713
|
*/
|
|
17648
17714
|
applyOptions(options) {
|
|
17649
17715
|
this._private__options = { ...this._private__options, ...options };
|
|
@@ -17651,14 +17717,36 @@ class DraggablePriceLine {
|
|
|
17651
17717
|
if (options.color) {
|
|
17652
17718
|
this._private__originalColor = options.color;
|
|
17653
17719
|
}
|
|
17654
|
-
if (this._private__priceLine
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
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 });
|
|
17662
17750
|
}
|
|
17663
17751
|
}
|
|
17664
17752
|
/**
|
|
@@ -17668,7 +17756,7 @@ class DraggablePriceLine {
|
|
|
17668
17756
|
return this._private__options.price;
|
|
17669
17757
|
}
|
|
17670
17758
|
/**
|
|
17671
|
-
* Set price programmatically
|
|
17759
|
+
* Set price programmatically. Triggers formatTitle if configured.
|
|
17672
17760
|
*/
|
|
17673
17761
|
setPrice(price) {
|
|
17674
17762
|
this._private__updatePrice(price);
|
|
@@ -17790,6 +17878,8 @@ function createTradingLine(series, chart, options) {
|
|
|
17790
17878
|
onDragStart: options.onDragStart,
|
|
17791
17879
|
onDragMove: options.onDragMove,
|
|
17792
17880
|
onDragEnd: options.onDragEnd,
|
|
17881
|
+
onClick: options.onClick,
|
|
17882
|
+
formatTitle: options.formatTitle,
|
|
17793
17883
|
};
|
|
17794
17884
|
return new DraggablePriceLine(chart, series, lineOptions);
|
|
17795
17885
|
}
|
|
@@ -24860,7 +24950,7 @@ const customSeriesDefaultOptions = {
|
|
|
24860
24950
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
24861
24951
|
*/
|
|
24862
24952
|
function version() {
|
|
24863
|
-
return "1.2.
|
|
24953
|
+
return "1.2.1";
|
|
24864
24954
|
}
|
|
24865
24955
|
|
|
24866
24956
|
export { areaSeries as AreaSeries, ArrowTool, barSeries as BarSeries, baselineSeries as BaselineSeries, BrushTool, candlestickSeries as CandlestickSeries, CircleTool, ColorType, 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, PositionCalculator, PositionMarkersManager, PositionTool, PriceLineSource, PriceScaleMode, RectangleTool, RulerCalculator, RulerTool, STANDARD_FIBONACCI_RATIOS, TextTool, TickMarkType, TrackingModeExitMode, TradingSessionsIndicator, TrendLineTool, VerticalLineTool, VolumeProfileIndicator, applyATR, applyBollingerBands, applyEMA, applyMACD, applyOBV, applyRSI, applySMA, applyStochastic, applyVolume, applyWMA, calculatePipConfig, createArrowTool, createBrushTool, createChart, createChartEx, createCircleTool, createFibonacciExtensionTool, createFibonacciFanTool, createFibonacciTool, createGanttTool, createHorizontalLineTool, createImageWatermark, createInteractiveLineManager, createOptionsChart, createPositionMarkers, createPositionTool, createRectangleTool, createRulerTool, createSeriesMarkers, createTextTool, createTextWatermark, createTradingLine, createTradingSessionsIndicator, createTrendLineTool, createUpDownMarkers, createVerticalLineTool, createVolumeProfileIndicator, createYieldCurveChart, customSeriesDefaultOptions, defaultHorzScaleBehavior, getPipConfig, isBusinessDay, isUTCTimestamp, setOBVVolumeData, setVolumeData, setVolumeProfileData, version };
|