@pipsend/charts 0.0.8 → 0.0.10
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 +3 -1
- package/dist/pipsend-charts.development.mjs +116 -110
- package/dist/pipsend-charts.production.mjs +2 -2
- package/dist/pipsend-charts.standalone.development.js +116 -110
- package/dist/pipsend-charts.standalone.development.mjs +116 -110
- package/dist/pipsend-charts.standalone.production.js +2 -2
- package/dist/pipsend-charts.standalone.production.mjs +2 -2
- package/dist/typings.d.ts +17 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @license
|
|
3
|
-
* Pipsend Charts v0.0.
|
|
3
|
+
* Pipsend Charts v0.0.10-dev+202510282321
|
|
4
4
|
* Copyright (c) 2025 Pipsend
|
|
5
5
|
* Licensed under MIT License
|
|
6
6
|
* Built on TradingView Lightweight Charts™ (Apache 2.0)
|
|
@@ -6418,7 +6418,12 @@
|
|
|
6418
6418
|
series._internal_destroy();
|
|
6419
6419
|
}
|
|
6420
6420
|
this._private__timeScale._internal_recalculateIndicesWithData();
|
|
6421
|
+
const paneCountBefore = this._private__panes.length;
|
|
6421
6422
|
this._private__cleanupIfPaneIsEmpty(paneImpl);
|
|
6423
|
+
// If a pane was removed, trigger full update to refresh the layout
|
|
6424
|
+
if (this._private__panes.length < paneCountBefore) {
|
|
6425
|
+
this._internal_fullUpdate();
|
|
6426
|
+
}
|
|
6422
6427
|
}
|
|
6423
6428
|
_internal_moveSeriesToScale(series, targetScaleId) {
|
|
6424
6429
|
const pane = ensureNotNull(this._internal_paneForSource(series));
|
|
@@ -16540,6 +16545,8 @@
|
|
|
16540
16545
|
this._private__isDragging = false;
|
|
16541
16546
|
this._private__container = null;
|
|
16542
16547
|
this._private__unsubscribeHandlers = [];
|
|
16548
|
+
this._private__isHovering = false;
|
|
16549
|
+
this._private__originalColor = '';
|
|
16543
16550
|
this._private__chart = chart;
|
|
16544
16551
|
this._private__series = series;
|
|
16545
16552
|
this._private__options = {
|
|
@@ -16555,6 +16562,7 @@
|
|
|
16555
16562
|
}
|
|
16556
16563
|
}
|
|
16557
16564
|
_private__createPriceLine() {
|
|
16565
|
+
this._private__originalColor = this._private__options.color;
|
|
16558
16566
|
this._private__priceLine = this._private__series.createPriceLine({
|
|
16559
16567
|
price: this._private__options.price,
|
|
16560
16568
|
color: this._private__options.color,
|
|
@@ -16570,8 +16578,12 @@
|
|
|
16570
16578
|
return;
|
|
16571
16579
|
this._private__container = chartElement;
|
|
16572
16580
|
const handleMouseDown = (e) => {
|
|
16581
|
+
// Solo permitir drag desde el área del gráfico (no desde el price axis)
|
|
16582
|
+
if (!this._private__isInChartArea(e)) {
|
|
16583
|
+
return;
|
|
16584
|
+
}
|
|
16573
16585
|
const price = this._private__getPriceFromY(e.clientY);
|
|
16574
|
-
if (this.
|
|
16586
|
+
if (this._private__isOnLine(e, price)) {
|
|
16575
16587
|
this._private__isDragging = true;
|
|
16576
16588
|
this._private__container.style.cursor = 'ns-resize';
|
|
16577
16589
|
if (this._private__options.onDragStart) {
|
|
@@ -16588,15 +16600,24 @@
|
|
|
16588
16600
|
if (this._private__options.onDragMove) {
|
|
16589
16601
|
this._private__options.onDragMove(newPrice);
|
|
16590
16602
|
}
|
|
16603
|
+
// Prevenir que el gráfico se mueva mientras arrastramos la línea
|
|
16604
|
+
e.preventDefault();
|
|
16605
|
+
e.stopPropagation();
|
|
16591
16606
|
}
|
|
16592
16607
|
else {
|
|
16593
|
-
//
|
|
16608
|
+
// Solo mostrar hover si está en el área del gráfico
|
|
16609
|
+
if (!this._private__isInChartArea(e)) {
|
|
16610
|
+
this._private__setHoverState(false);
|
|
16611
|
+
return;
|
|
16612
|
+
}
|
|
16594
16613
|
const price = this._private__getPriceFromY(e.clientY);
|
|
16595
|
-
if (this.
|
|
16614
|
+
if (this._private__isOnLine(e, price)) {
|
|
16596
16615
|
this._private__container.style.cursor = 'ns-resize';
|
|
16616
|
+
this._private__setHoverState(true);
|
|
16597
16617
|
}
|
|
16598
16618
|
else {
|
|
16599
16619
|
this._private__container.style.cursor = 'default';
|
|
16620
|
+
this._private__setHoverState(false);
|
|
16600
16621
|
}
|
|
16601
16622
|
}
|
|
16602
16623
|
};
|
|
@@ -16604,69 +16625,50 @@
|
|
|
16604
16625
|
if (this._private__isDragging) {
|
|
16605
16626
|
this._private__isDragging = false;
|
|
16606
16627
|
this._private__container.style.cursor = 'default';
|
|
16628
|
+
this._private__setHoverState(false);
|
|
16607
16629
|
if (this._private__options.onDragEnd) {
|
|
16608
16630
|
this._private__options.onDragEnd(this._private__options.price);
|
|
16609
16631
|
}
|
|
16610
16632
|
}
|
|
16611
16633
|
};
|
|
16634
|
+
const handleMouseLeave = (e) => {
|
|
16635
|
+
if (this._private__isDragging) {
|
|
16636
|
+
this._private__isDragging = false;
|
|
16637
|
+
this._private__setHoverState(false);
|
|
16638
|
+
if (this._private__options.onDragEnd) {
|
|
16639
|
+
this._private__options.onDragEnd(this._private__options.price);
|
|
16640
|
+
}
|
|
16641
|
+
}
|
|
16642
|
+
else {
|
|
16643
|
+
this._private__setHoverState(false);
|
|
16644
|
+
}
|
|
16645
|
+
};
|
|
16612
16646
|
this._private__container.addEventListener('mousedown', handleMouseDown);
|
|
16613
16647
|
this._private__container.addEventListener('mousemove', handleMouseMove);
|
|
16614
16648
|
this._private__container.addEventListener('mouseup', handleMouseUp);
|
|
16615
|
-
this._private__container.addEventListener('mouseleave',
|
|
16649
|
+
this._private__container.addEventListener('mouseleave', handleMouseLeave);
|
|
16616
16650
|
// Store unsubscribe handlers
|
|
16617
16651
|
this._private__unsubscribeHandlers.push(() => {
|
|
16618
16652
|
this._private__container?.removeEventListener('mousedown', handleMouseDown);
|
|
16619
16653
|
this._private__container?.removeEventListener('mousemove', handleMouseMove);
|
|
16620
16654
|
this._private__container?.removeEventListener('mouseup', handleMouseUp);
|
|
16621
|
-
this._private__container?.removeEventListener('mouseleave',
|
|
16655
|
+
this._private__container?.removeEventListener('mouseleave', handleMouseLeave);
|
|
16622
16656
|
});
|
|
16623
16657
|
}
|
|
16624
16658
|
_private__getPriceFromY(clientY) {
|
|
16625
16659
|
try {
|
|
16626
|
-
//
|
|
16660
|
+
// Usar la API del chart para convertir coordenada Y a precio
|
|
16661
|
+
// Esto garantiza que usamos exactamente la misma escala que el chart
|
|
16627
16662
|
const chartElement = this._private__chart.chartElement?.() || document.querySelector('.tv-lightweight-charts');
|
|
16628
16663
|
if (!chartElement)
|
|
16629
16664
|
return this._private__options.price;
|
|
16630
16665
|
const rect = chartElement.getBoundingClientRect();
|
|
16631
16666
|
const relativeY = clientY - rect.top;
|
|
16632
|
-
//
|
|
16633
|
-
const
|
|
16634
|
-
|
|
16635
|
-
if (!visibleRange)
|
|
16667
|
+
// Usar coordinateToPrice() - método oficial del chart
|
|
16668
|
+
const price = this._private__series.coordinateToPrice(relativeY);
|
|
16669
|
+
if (price === null) {
|
|
16636
16670
|
return this._private__options.price;
|
|
16637
|
-
// Get series data
|
|
16638
|
-
const seriesData = this._private__series.data();
|
|
16639
|
-
if (!seriesData || seriesData.length === 0)
|
|
16640
|
-
return this._private__options.price;
|
|
16641
|
-
// Calculate min/max price in visible range
|
|
16642
|
-
const startIndex = Math.max(0, Math.floor(visibleRange.from));
|
|
16643
|
-
const endIndex = Math.min(seriesData.length - 1, Math.ceil(visibleRange.to));
|
|
16644
|
-
let minPrice = Infinity;
|
|
16645
|
-
let maxPrice = -Infinity;
|
|
16646
|
-
for (let i = startIndex; i <= endIndex; i++) {
|
|
16647
|
-
const d = seriesData[i];
|
|
16648
|
-
if ('high' in d && 'low' in d) {
|
|
16649
|
-
minPrice = Math.min(minPrice, d.low);
|
|
16650
|
-
maxPrice = Math.max(maxPrice, d.high);
|
|
16651
|
-
}
|
|
16652
|
-
else if ('close' in d) {
|
|
16653
|
-
minPrice = Math.min(minPrice, d.close);
|
|
16654
|
-
maxPrice = Math.max(maxPrice, d.close);
|
|
16655
|
-
}
|
|
16656
|
-
else if ('value' in d) {
|
|
16657
|
-
minPrice = Math.min(minPrice, d.value);
|
|
16658
|
-
maxPrice = Math.max(maxPrice, d.value);
|
|
16659
|
-
}
|
|
16660
16671
|
}
|
|
16661
|
-
// Add 10% padding
|
|
16662
|
-
const padding = (maxPrice - minPrice) * 0.1;
|
|
16663
|
-
minPrice -= padding;
|
|
16664
|
-
maxPrice += padding;
|
|
16665
|
-
// Calculate price from Y position
|
|
16666
|
-
const priceRange = maxPrice - minPrice;
|
|
16667
|
-
const chartHeight = rect.height;
|
|
16668
|
-
const pricePerPixel = priceRange / chartHeight;
|
|
16669
|
-
const price = maxPrice - (relativeY * pricePerPixel);
|
|
16670
16672
|
return price;
|
|
16671
16673
|
}
|
|
16672
16674
|
catch (error) {
|
|
@@ -16674,37 +16676,61 @@
|
|
|
16674
16676
|
return this._private__options.price;
|
|
16675
16677
|
}
|
|
16676
16678
|
}
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
+
/**
|
|
16680
|
+
* Verifica si el mouse está EN la línea (no cerca, sino exactamente sobre ella)
|
|
16681
|
+
* Usa la API de coordenadas del chart para precisión consistente
|
|
16682
|
+
* @param e - Mouse event
|
|
16683
|
+
* @param price - Precio calculado desde la posición Y
|
|
16684
|
+
*/
|
|
16685
|
+
_private__isOnLine(e, price) {
|
|
16679
16686
|
const chartElement = this._private__chart.chartElement?.() || document.querySelector('.tv-lightweight-charts');
|
|
16680
16687
|
if (!chartElement)
|
|
16681
16688
|
return false;
|
|
16689
|
+
// Usar la API del chart para convertir precio a coordenada Y
|
|
16690
|
+
const lineCoordinate = this._private__series.priceToCoordinate(this._private__options.price);
|
|
16691
|
+
if (lineCoordinate === null)
|
|
16692
|
+
return false;
|
|
16693
|
+
// Obtener la coordenada Y del mouse relativa al chart
|
|
16682
16694
|
const rect = chartElement.getBoundingClientRect();
|
|
16683
|
-
const
|
|
16684
|
-
|
|
16695
|
+
const mouseY = e.clientY - rect.top;
|
|
16696
|
+
// Threshold FIJO en píxeles (muy preciso y consistente)
|
|
16697
|
+
const pixelThreshold = 5; // 5 píxeles - siempre igual sin importar el zoom
|
|
16698
|
+
// Comparar directamente en píxeles (más preciso)
|
|
16699
|
+
return Math.abs(mouseY - lineCoordinate) <= pixelThreshold;
|
|
16700
|
+
}
|
|
16701
|
+
/**
|
|
16702
|
+
* Verifica si el mouse está en el área del gráfico (no en el price axis)
|
|
16703
|
+
*/
|
|
16704
|
+
_private__isInChartArea(e) {
|
|
16705
|
+
if (!this._private__container)
|
|
16685
16706
|
return false;
|
|
16686
|
-
//
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16707
|
+
// Obtener el ancho del price axis (usualmente ~60-80px desde la derecha)
|
|
16708
|
+
const rect = this._private__container.getBoundingClientRect();
|
|
16709
|
+
const priceAxisWidth = 80; // Ancho aproximado del eje de precios
|
|
16710
|
+
// El mouse debe estar ANTES del price axis (área del gráfico)
|
|
16711
|
+
const mouseX = e.clientX - rect.left;
|
|
16712
|
+
const chartAreaWidth = rect.width - priceAxisWidth;
|
|
16713
|
+
return mouseX < chartAreaWidth;
|
|
16714
|
+
}
|
|
16715
|
+
/**
|
|
16716
|
+
* Activa/desactiva el estado de hover (línea negra)
|
|
16717
|
+
*/
|
|
16718
|
+
_private__setHoverState(isHovering) {
|
|
16719
|
+
if (this._private__isHovering === isHovering || !this._private__priceLine)
|
|
16720
|
+
return;
|
|
16721
|
+
this._private__isHovering = isHovering;
|
|
16722
|
+
if (isHovering) {
|
|
16723
|
+
// Cambiar a negro cuando está en hover
|
|
16724
|
+
this._private__priceLine.applyOptions({
|
|
16725
|
+
color: '#000000'
|
|
16726
|
+
});
|
|
16727
|
+
}
|
|
16728
|
+
else {
|
|
16729
|
+
// Restaurar color original
|
|
16730
|
+
this._private__priceLine.applyOptions({
|
|
16731
|
+
color: this._private__originalColor
|
|
16732
|
+
});
|
|
16703
16733
|
}
|
|
16704
|
-
const priceRange = maxPrice - minPrice;
|
|
16705
|
-
const pixelThreshold = 15; // 15 pixels
|
|
16706
|
-
const priceThreshold = (priceRange / rect.height) * pixelThreshold;
|
|
16707
|
-
return Math.abs(price - this._private__options.price) < priceThreshold;
|
|
16708
16734
|
}
|
|
16709
16735
|
_private__updatePrice(newPrice) {
|
|
16710
16736
|
this._private__options.price = newPrice;
|
|
@@ -16717,6 +16743,10 @@
|
|
|
16717
16743
|
*/
|
|
16718
16744
|
applyOptions(options) {
|
|
16719
16745
|
this._private__options = { ...this._private__options, ...options };
|
|
16746
|
+
// Actualizar color original si se proporciona
|
|
16747
|
+
if (options.color) {
|
|
16748
|
+
this._private__originalColor = options.color;
|
|
16749
|
+
}
|
|
16720
16750
|
if (this._private__priceLine && options.price !== undefined) {
|
|
16721
16751
|
this._private__priceLine.applyOptions({
|
|
16722
16752
|
price: options.price,
|
|
@@ -16746,6 +16776,8 @@
|
|
|
16746
16776
|
// Cleanup event listeners
|
|
16747
16777
|
this._private__unsubscribeHandlers.forEach(handler => handler());
|
|
16748
16778
|
this._private__unsubscribeHandlers = [];
|
|
16779
|
+
// Remove hover state
|
|
16780
|
+
this._private__setHoverState(false);
|
|
16749
16781
|
// Remove price line
|
|
16750
16782
|
if (this._private__priceLine) {
|
|
16751
16783
|
this._private__series.removePriceLine(this._private__priceLine);
|
|
@@ -16878,49 +16910,23 @@
|
|
|
16878
16910
|
}
|
|
16879
16911
|
}
|
|
16880
16912
|
_private__getPriceFromMouseEvent(e) {
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
const seriesData = this._private__series.data();
|
|
16892
|
-
if (!seriesData || seriesData.length === 0)
|
|
16893
|
-
return 0;
|
|
16894
|
-
// Calculate min/max price in visible range
|
|
16895
|
-
const startIndex = Math.max(0, Math.floor(visibleRange.from));
|
|
16896
|
-
const endIndex = Math.min(seriesData.length - 1, Math.ceil(visibleRange.to));
|
|
16897
|
-
let minPrice = Infinity;
|
|
16898
|
-
let maxPrice = -Infinity;
|
|
16899
|
-
for (let i = startIndex; i <= endIndex; i++) {
|
|
16900
|
-
const d = seriesData[i];
|
|
16901
|
-
if ('high' in d && 'low' in d) {
|
|
16902
|
-
minPrice = Math.min(minPrice, d.low);
|
|
16903
|
-
maxPrice = Math.max(maxPrice, d.high);
|
|
16904
|
-
}
|
|
16905
|
-
else if ('close' in d) {
|
|
16906
|
-
minPrice = Math.min(minPrice, d.close);
|
|
16907
|
-
maxPrice = Math.max(maxPrice, d.close);
|
|
16908
|
-
}
|
|
16909
|
-
else if ('value' in d) {
|
|
16910
|
-
minPrice = Math.min(minPrice, d.value);
|
|
16911
|
-
maxPrice = Math.max(maxPrice, d.value);
|
|
16913
|
+
try {
|
|
16914
|
+
if (!this._private__container)
|
|
16915
|
+
return 0;
|
|
16916
|
+
// Usar la misma API que usa el dragging para consistencia perfecta
|
|
16917
|
+
const rect = this._private__container.getBoundingClientRect();
|
|
16918
|
+
const relativeY = e.clientY - rect.top;
|
|
16919
|
+
// Usar coordinateToPrice() - método oficial del chart
|
|
16920
|
+
const price = this._private__series.coordinateToPrice(relativeY);
|
|
16921
|
+
if (price === null) {
|
|
16922
|
+
return 0;
|
|
16912
16923
|
}
|
|
16924
|
+
return price;
|
|
16925
|
+
}
|
|
16926
|
+
catch (error) {
|
|
16927
|
+
console.error('Error getting price from mouse event:', error);
|
|
16928
|
+
return 0;
|
|
16913
16929
|
}
|
|
16914
|
-
// Add 10% padding
|
|
16915
|
-
const padding = (maxPrice - minPrice) * 0.1;
|
|
16916
|
-
minPrice -= padding;
|
|
16917
|
-
maxPrice += padding;
|
|
16918
|
-
// Calculate price from Y position
|
|
16919
|
-
const priceRange = maxPrice - minPrice;
|
|
16920
|
-
const chartHeight = rect.height;
|
|
16921
|
-
const pricePerPixel = priceRange / chartHeight;
|
|
16922
|
-
const price = maxPrice - (relativeY * pricePerPixel);
|
|
16923
|
-
return price;
|
|
16924
16930
|
}
|
|
16925
16931
|
/**
|
|
16926
16932
|
* Activa el modo de creación de líneas por clic
|
|
@@ -17081,7 +17087,7 @@
|
|
|
17081
17087
|
* Returns the current version as a string. For example `'1.0.0'`.
|
|
17082
17088
|
*/
|
|
17083
17089
|
function version() {
|
|
17084
|
-
return "0.0.
|
|
17090
|
+
return "0.0.10-dev+202510282321";
|
|
17085
17091
|
}
|
|
17086
17092
|
|
|
17087
17093
|
var PipsendChartsModule = /*#__PURE__*/Object.freeze({
|