hyperprop-charting-library 0.1.38 → 0.1.40
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/hyperprop-charting-library.cjs +86 -52
- package/dist/hyperprop-charting-library.d.ts +1 -0
- package/dist/hyperprop-charting-library.js +86 -52
- package/dist/index.cjs +86 -52
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +86 -52
- package/package.json +2 -2
|
@@ -177,6 +177,47 @@ var DEFAULT_OPTIONS = {
|
|
|
177
177
|
dashPatterns: DEFAULT_DASH_PATTERNS,
|
|
178
178
|
indicators: []
|
|
179
179
|
};
|
|
180
|
+
var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
181
|
+
...baseOptions,
|
|
182
|
+
...options,
|
|
183
|
+
axis: {
|
|
184
|
+
...baseOptions.axis,
|
|
185
|
+
...options.axis ?? {},
|
|
186
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
187
|
+
},
|
|
188
|
+
xAxis: {
|
|
189
|
+
...baseOptions.xAxis,
|
|
190
|
+
...options.axis ?? {},
|
|
191
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
192
|
+
...options.xAxis ?? {}
|
|
193
|
+
},
|
|
194
|
+
yAxis: {
|
|
195
|
+
...baseOptions.yAxis,
|
|
196
|
+
...options.axis ?? {},
|
|
197
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
198
|
+
...options.yAxis ?? {}
|
|
199
|
+
},
|
|
200
|
+
crosshair: {
|
|
201
|
+
...baseOptions.crosshair,
|
|
202
|
+
...options.crosshair ?? {}
|
|
203
|
+
},
|
|
204
|
+
grid: {
|
|
205
|
+
...baseOptions.grid,
|
|
206
|
+
...options.grid ?? {}
|
|
207
|
+
},
|
|
208
|
+
watermark: {
|
|
209
|
+
...baseOptions.watermark,
|
|
210
|
+
...options.watermark ?? {}
|
|
211
|
+
},
|
|
212
|
+
tickerLine: {
|
|
213
|
+
...baseOptions.tickerLine,
|
|
214
|
+
...options.tickerLine ?? {}
|
|
215
|
+
},
|
|
216
|
+
dashPatterns: {
|
|
217
|
+
...baseOptions.dashPatterns,
|
|
218
|
+
...options.dashPatterns ?? {}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
180
221
|
var getIndicatorSourceValue = (point, source) => {
|
|
181
222
|
if (source === "open") return point.o;
|
|
182
223
|
if (source === "high") return point.h;
|
|
@@ -728,47 +769,7 @@ var BUILTIN_INDICATORS = [
|
|
|
728
769
|
BUILTIN_ATR_INDICATOR
|
|
729
770
|
];
|
|
730
771
|
function createChart(element, options = {}) {
|
|
731
|
-
|
|
732
|
-
...DEFAULT_OPTIONS,
|
|
733
|
-
...options,
|
|
734
|
-
axis: {
|
|
735
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
736
|
-
...options.axis ?? {},
|
|
737
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
738
|
-
},
|
|
739
|
-
xAxis: {
|
|
740
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
741
|
-
...options.axis ?? {},
|
|
742
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
743
|
-
...options.xAxis ?? {}
|
|
744
|
-
},
|
|
745
|
-
yAxis: {
|
|
746
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
747
|
-
...options.axis ?? {},
|
|
748
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
749
|
-
...options.yAxis ?? {}
|
|
750
|
-
},
|
|
751
|
-
crosshair: {
|
|
752
|
-
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
753
|
-
...options.crosshair ?? {}
|
|
754
|
-
},
|
|
755
|
-
grid: {
|
|
756
|
-
...DEFAULT_GRID_OPTIONS,
|
|
757
|
-
...options.grid
|
|
758
|
-
},
|
|
759
|
-
watermark: {
|
|
760
|
-
...DEFAULT_WATERMARK_OPTIONS,
|
|
761
|
-
...options.watermark
|
|
762
|
-
},
|
|
763
|
-
tickerLine: {
|
|
764
|
-
...DEFAULT_OPTIONS.tickerLine,
|
|
765
|
-
...options.tickerLine
|
|
766
|
-
},
|
|
767
|
-
dashPatterns: {
|
|
768
|
-
...DEFAULT_DASH_PATTERNS,
|
|
769
|
-
...options.dashPatterns ?? {}
|
|
770
|
-
}
|
|
771
|
-
};
|
|
772
|
+
let mergedOptions = mergeChartOptions(DEFAULT_OPTIONS, options);
|
|
772
773
|
let width = mergedOptions.width;
|
|
773
774
|
let height = mergedOptions.height;
|
|
774
775
|
let data = [];
|
|
@@ -859,7 +860,7 @@ function createChart(element, options = {}) {
|
|
|
859
860
|
const diff = tickerPriceTarget - smoothedTickerPrice;
|
|
860
861
|
if (Math.abs(diff) < 1e-9) {
|
|
861
862
|
smoothedTickerPrice = tickerPriceTarget;
|
|
862
|
-
draw();
|
|
863
|
+
draw({ updateAutoScale: false });
|
|
863
864
|
return;
|
|
864
865
|
}
|
|
865
866
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
@@ -867,7 +868,7 @@ function createChart(element, options = {}) {
|
|
|
867
868
|
const dt = 1 / 60;
|
|
868
869
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
869
870
|
smoothedTickerPrice += diff * lerp;
|
|
870
|
-
draw();
|
|
871
|
+
draw({ updateAutoScale: false });
|
|
871
872
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
872
873
|
};
|
|
873
874
|
const pushSmoothedPrice = (target) => {
|
|
@@ -1584,7 +1585,8 @@ function createChart(element, options = {}) {
|
|
|
1584
1585
|
crosshairPoint = point;
|
|
1585
1586
|
draw();
|
|
1586
1587
|
};
|
|
1587
|
-
const draw = () => {
|
|
1588
|
+
const draw = (options2 = {}) => {
|
|
1589
|
+
const shouldUpdateAutoScale = options2.updateAutoScale ?? true;
|
|
1588
1590
|
orderActionRegions = [];
|
|
1589
1591
|
orderDragRegions = [];
|
|
1590
1592
|
crosshairPriceActionRegion = null;
|
|
@@ -1690,6 +1692,9 @@ function createChart(element, options = {}) {
|
|
|
1690
1692
|
}
|
|
1691
1693
|
const visibleValues = [];
|
|
1692
1694
|
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1695
|
+
if (mergedOptions.autoScaleIgnoreLatestCandle && data.length > 1 && idx === data.length - 1) {
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1693
1698
|
const value = series[idx];
|
|
1694
1699
|
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1695
1700
|
visibleValues.push(value);
|
|
@@ -1712,7 +1717,7 @@ function createChart(element, options = {}) {
|
|
|
1712
1717
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1713
1718
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
1714
1719
|
const smoothing = clamp(mergedOptions.autoScaleSmoothing, 0, 1);
|
|
1715
|
-
if (yMinOverride === null || yMaxOverride === null) {
|
|
1720
|
+
if ((yMinOverride === null || yMaxOverride === null) && (shouldUpdateAutoScale || autoYMin === null || autoYMax === null)) {
|
|
1716
1721
|
if (autoYMin === null || autoYMax === null) {
|
|
1717
1722
|
autoYMin = autoMin;
|
|
1718
1723
|
autoYMax = autoMax;
|
|
@@ -1854,15 +1859,16 @@ function createChart(element, options = {}) {
|
|
|
1854
1859
|
continue;
|
|
1855
1860
|
}
|
|
1856
1861
|
const isLastCandle = useSmoothedCandle && index === lastDataIndex;
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
1859
|
-
const
|
|
1862
|
+
const actualDirection = point.c >= point.o ? "up" : "down";
|
|
1863
|
+
const displayClose = isLastCandle ? actualDirection === "up" ? Math.max(point.o, smoothedTickerPrice) : Math.min(point.o, smoothedTickerPrice) : point.c;
|
|
1864
|
+
const displayHigh = isLastCandle ? actualDirection === "up" ? Math.max(point.h, displayClose) : point.h : point.h;
|
|
1865
|
+
const displayLow = isLastCandle ? actualDirection === "up" ? point.l : Math.min(point.l, displayClose) : point.l;
|
|
1860
1866
|
const centerX = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1861
1867
|
const openY = yFromPrice(point.o);
|
|
1862
1868
|
const closeY = yFromPrice(displayClose);
|
|
1863
1869
|
const highY = yFromPrice(displayHigh);
|
|
1864
1870
|
const lowY = yFromPrice(displayLow);
|
|
1865
|
-
const direction = isLastCandle ?
|
|
1871
|
+
const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
|
|
1866
1872
|
const candleColor = direction === "up" ? mergedOptions.upColor : mergedOptions.downColor;
|
|
1867
1873
|
const roundedCenterX = Math.round(centerX);
|
|
1868
1874
|
ctx.strokeStyle = candleColor;
|
|
@@ -1872,10 +1878,13 @@ function createChart(element, options = {}) {
|
|
|
1872
1878
|
ctx.lineTo(roundedCenterX + 0.5, crisp(lowY));
|
|
1873
1879
|
ctx.stroke();
|
|
1874
1880
|
const bodyLeft = roundedCenterX - Math.floor(bodyWidth / 2);
|
|
1875
|
-
const
|
|
1876
|
-
const
|
|
1881
|
+
const openYPx = Math.round(openY);
|
|
1882
|
+
const closeYPx = Math.round(closeY);
|
|
1883
|
+
const bodyIsUp = displayClose >= point.o;
|
|
1884
|
+
const bodyTop = bodyIsUp ? Math.min(closeYPx, openYPx - 1) : openYPx;
|
|
1885
|
+
const bodyBottom = bodyIsUp ? openYPx : Math.max(closeYPx, openYPx + 1);
|
|
1877
1886
|
ctx.fillStyle = candleColor;
|
|
1878
|
-
ctx.fillRect(bodyLeft,
|
|
1887
|
+
ctx.fillRect(bodyLeft, bodyTop, bodyWidth, bodyBottom - bodyTop);
|
|
1879
1888
|
}
|
|
1880
1889
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1881
1890
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
@@ -2803,6 +2812,29 @@ function createChart(element, options = {}) {
|
|
|
2803
2812
|
canvas.addEventListener("pointerleave", endPointerDrag);
|
|
2804
2813
|
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2805
2814
|
canvas.addEventListener("dblclick", onDoubleClick);
|
|
2815
|
+
const updateOptions = (nextOptions) => {
|
|
2816
|
+
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2817
|
+
const previousWidth = width;
|
|
2818
|
+
const previousHeight = height;
|
|
2819
|
+
mergedOptions = mergeChartOptions(mergedOptions, nextOptions);
|
|
2820
|
+
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
2821
|
+
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
2822
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2823
|
+
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
2824
|
+
doubleClickAction = mergedOptions.doubleClickAction;
|
|
2825
|
+
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2826
|
+
if (!isTickerSmoothingEnabled) {
|
|
2827
|
+
smoothedTickerPrice = null;
|
|
2828
|
+
tickerPriceTarget = null;
|
|
2829
|
+
if (smoothingRafId !== null) {
|
|
2830
|
+
cancelAnimationFrame(smoothingRafId);
|
|
2831
|
+
smoothingRafId = null;
|
|
2832
|
+
}
|
|
2833
|
+
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2834
|
+
pushSmoothedPrice(data[data.length - 1].c);
|
|
2835
|
+
}
|
|
2836
|
+
draw();
|
|
2837
|
+
};
|
|
2806
2838
|
const resize = (nextWidth, nextHeight) => {
|
|
2807
2839
|
if (nextWidth && nextWidth > 0) {
|
|
2808
2840
|
width = nextWidth;
|
|
@@ -2810,6 +2842,7 @@ function createChart(element, options = {}) {
|
|
|
2810
2842
|
if (nextHeight && nextHeight > 0) {
|
|
2811
2843
|
height = nextHeight;
|
|
2812
2844
|
}
|
|
2845
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2813
2846
|
draw();
|
|
2814
2847
|
};
|
|
2815
2848
|
const setData = (nextData) => {
|
|
@@ -3013,6 +3046,7 @@ function createChart(element, options = {}) {
|
|
|
3013
3046
|
};
|
|
3014
3047
|
draw();
|
|
3015
3048
|
return {
|
|
3049
|
+
updateOptions,
|
|
3016
3050
|
setData,
|
|
3017
3051
|
setPriceLines,
|
|
3018
3052
|
addPriceLine,
|
|
@@ -263,6 +263,7 @@ interface TickerLineOptions {
|
|
|
263
263
|
smoothingSpeed?: number;
|
|
264
264
|
}
|
|
265
265
|
interface ChartInstance {
|
|
266
|
+
updateOptions: (options: ChartOptions) => void;
|
|
266
267
|
setData: (data: OhlcDataPoint[]) => void;
|
|
267
268
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
268
269
|
addPriceLine: (line: PriceLineOptions) => string;
|
|
@@ -153,6 +153,47 @@ var DEFAULT_OPTIONS = {
|
|
|
153
153
|
dashPatterns: DEFAULT_DASH_PATTERNS,
|
|
154
154
|
indicators: []
|
|
155
155
|
};
|
|
156
|
+
var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
157
|
+
...baseOptions,
|
|
158
|
+
...options,
|
|
159
|
+
axis: {
|
|
160
|
+
...baseOptions.axis,
|
|
161
|
+
...options.axis ?? {},
|
|
162
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
163
|
+
},
|
|
164
|
+
xAxis: {
|
|
165
|
+
...baseOptions.xAxis,
|
|
166
|
+
...options.axis ?? {},
|
|
167
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
168
|
+
...options.xAxis ?? {}
|
|
169
|
+
},
|
|
170
|
+
yAxis: {
|
|
171
|
+
...baseOptions.yAxis,
|
|
172
|
+
...options.axis ?? {},
|
|
173
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
174
|
+
...options.yAxis ?? {}
|
|
175
|
+
},
|
|
176
|
+
crosshair: {
|
|
177
|
+
...baseOptions.crosshair,
|
|
178
|
+
...options.crosshair ?? {}
|
|
179
|
+
},
|
|
180
|
+
grid: {
|
|
181
|
+
...baseOptions.grid,
|
|
182
|
+
...options.grid ?? {}
|
|
183
|
+
},
|
|
184
|
+
watermark: {
|
|
185
|
+
...baseOptions.watermark,
|
|
186
|
+
...options.watermark ?? {}
|
|
187
|
+
},
|
|
188
|
+
tickerLine: {
|
|
189
|
+
...baseOptions.tickerLine,
|
|
190
|
+
...options.tickerLine ?? {}
|
|
191
|
+
},
|
|
192
|
+
dashPatterns: {
|
|
193
|
+
...baseOptions.dashPatterns,
|
|
194
|
+
...options.dashPatterns ?? {}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
156
197
|
var getIndicatorSourceValue = (point, source) => {
|
|
157
198
|
if (source === "open") return point.o;
|
|
158
199
|
if (source === "high") return point.h;
|
|
@@ -704,47 +745,7 @@ var BUILTIN_INDICATORS = [
|
|
|
704
745
|
BUILTIN_ATR_INDICATOR
|
|
705
746
|
];
|
|
706
747
|
function createChart(element, options = {}) {
|
|
707
|
-
|
|
708
|
-
...DEFAULT_OPTIONS,
|
|
709
|
-
...options,
|
|
710
|
-
axis: {
|
|
711
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
712
|
-
...options.axis ?? {},
|
|
713
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
714
|
-
},
|
|
715
|
-
xAxis: {
|
|
716
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
717
|
-
...options.axis ?? {},
|
|
718
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
719
|
-
...options.xAxis ?? {}
|
|
720
|
-
},
|
|
721
|
-
yAxis: {
|
|
722
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
723
|
-
...options.axis ?? {},
|
|
724
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
725
|
-
...options.yAxis ?? {}
|
|
726
|
-
},
|
|
727
|
-
crosshair: {
|
|
728
|
-
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
729
|
-
...options.crosshair ?? {}
|
|
730
|
-
},
|
|
731
|
-
grid: {
|
|
732
|
-
...DEFAULT_GRID_OPTIONS,
|
|
733
|
-
...options.grid
|
|
734
|
-
},
|
|
735
|
-
watermark: {
|
|
736
|
-
...DEFAULT_WATERMARK_OPTIONS,
|
|
737
|
-
...options.watermark
|
|
738
|
-
},
|
|
739
|
-
tickerLine: {
|
|
740
|
-
...DEFAULT_OPTIONS.tickerLine,
|
|
741
|
-
...options.tickerLine
|
|
742
|
-
},
|
|
743
|
-
dashPatterns: {
|
|
744
|
-
...DEFAULT_DASH_PATTERNS,
|
|
745
|
-
...options.dashPatterns ?? {}
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
+
let mergedOptions = mergeChartOptions(DEFAULT_OPTIONS, options);
|
|
748
749
|
let width = mergedOptions.width;
|
|
749
750
|
let height = mergedOptions.height;
|
|
750
751
|
let data = [];
|
|
@@ -835,7 +836,7 @@ function createChart(element, options = {}) {
|
|
|
835
836
|
const diff = tickerPriceTarget - smoothedTickerPrice;
|
|
836
837
|
if (Math.abs(diff) < 1e-9) {
|
|
837
838
|
smoothedTickerPrice = tickerPriceTarget;
|
|
838
|
-
draw();
|
|
839
|
+
draw({ updateAutoScale: false });
|
|
839
840
|
return;
|
|
840
841
|
}
|
|
841
842
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
@@ -843,7 +844,7 @@ function createChart(element, options = {}) {
|
|
|
843
844
|
const dt = 1 / 60;
|
|
844
845
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
845
846
|
smoothedTickerPrice += diff * lerp;
|
|
846
|
-
draw();
|
|
847
|
+
draw({ updateAutoScale: false });
|
|
847
848
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
848
849
|
};
|
|
849
850
|
const pushSmoothedPrice = (target) => {
|
|
@@ -1560,7 +1561,8 @@ function createChart(element, options = {}) {
|
|
|
1560
1561
|
crosshairPoint = point;
|
|
1561
1562
|
draw();
|
|
1562
1563
|
};
|
|
1563
|
-
const draw = () => {
|
|
1564
|
+
const draw = (options2 = {}) => {
|
|
1565
|
+
const shouldUpdateAutoScale = options2.updateAutoScale ?? true;
|
|
1564
1566
|
orderActionRegions = [];
|
|
1565
1567
|
orderDragRegions = [];
|
|
1566
1568
|
crosshairPriceActionRegion = null;
|
|
@@ -1666,6 +1668,9 @@ function createChart(element, options = {}) {
|
|
|
1666
1668
|
}
|
|
1667
1669
|
const visibleValues = [];
|
|
1668
1670
|
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1671
|
+
if (mergedOptions.autoScaleIgnoreLatestCandle && data.length > 1 && idx === data.length - 1) {
|
|
1672
|
+
continue;
|
|
1673
|
+
}
|
|
1669
1674
|
const value = series[idx];
|
|
1670
1675
|
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1671
1676
|
visibleValues.push(value);
|
|
@@ -1688,7 +1693,7 @@ function createChart(element, options = {}) {
|
|
|
1688
1693
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1689
1694
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
1690
1695
|
const smoothing = clamp(mergedOptions.autoScaleSmoothing, 0, 1);
|
|
1691
|
-
if (yMinOverride === null || yMaxOverride === null) {
|
|
1696
|
+
if ((yMinOverride === null || yMaxOverride === null) && (shouldUpdateAutoScale || autoYMin === null || autoYMax === null)) {
|
|
1692
1697
|
if (autoYMin === null || autoYMax === null) {
|
|
1693
1698
|
autoYMin = autoMin;
|
|
1694
1699
|
autoYMax = autoMax;
|
|
@@ -1830,15 +1835,16 @@ function createChart(element, options = {}) {
|
|
|
1830
1835
|
continue;
|
|
1831
1836
|
}
|
|
1832
1837
|
const isLastCandle = useSmoothedCandle && index === lastDataIndex;
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
1835
|
-
const
|
|
1838
|
+
const actualDirection = point.c >= point.o ? "up" : "down";
|
|
1839
|
+
const displayClose = isLastCandle ? actualDirection === "up" ? Math.max(point.o, smoothedTickerPrice) : Math.min(point.o, smoothedTickerPrice) : point.c;
|
|
1840
|
+
const displayHigh = isLastCandle ? actualDirection === "up" ? Math.max(point.h, displayClose) : point.h : point.h;
|
|
1841
|
+
const displayLow = isLastCandle ? actualDirection === "up" ? point.l : Math.min(point.l, displayClose) : point.l;
|
|
1836
1842
|
const centerX = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1837
1843
|
const openY = yFromPrice(point.o);
|
|
1838
1844
|
const closeY = yFromPrice(displayClose);
|
|
1839
1845
|
const highY = yFromPrice(displayHigh);
|
|
1840
1846
|
const lowY = yFromPrice(displayLow);
|
|
1841
|
-
const direction = isLastCandle ?
|
|
1847
|
+
const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
|
|
1842
1848
|
const candleColor = direction === "up" ? mergedOptions.upColor : mergedOptions.downColor;
|
|
1843
1849
|
const roundedCenterX = Math.round(centerX);
|
|
1844
1850
|
ctx.strokeStyle = candleColor;
|
|
@@ -1848,10 +1854,13 @@ function createChart(element, options = {}) {
|
|
|
1848
1854
|
ctx.lineTo(roundedCenterX + 0.5, crisp(lowY));
|
|
1849
1855
|
ctx.stroke();
|
|
1850
1856
|
const bodyLeft = roundedCenterX - Math.floor(bodyWidth / 2);
|
|
1851
|
-
const
|
|
1852
|
-
const
|
|
1857
|
+
const openYPx = Math.round(openY);
|
|
1858
|
+
const closeYPx = Math.round(closeY);
|
|
1859
|
+
const bodyIsUp = displayClose >= point.o;
|
|
1860
|
+
const bodyTop = bodyIsUp ? Math.min(closeYPx, openYPx - 1) : openYPx;
|
|
1861
|
+
const bodyBottom = bodyIsUp ? openYPx : Math.max(closeYPx, openYPx + 1);
|
|
1853
1862
|
ctx.fillStyle = candleColor;
|
|
1854
|
-
ctx.fillRect(bodyLeft,
|
|
1863
|
+
ctx.fillRect(bodyLeft, bodyTop, bodyWidth, bodyBottom - bodyTop);
|
|
1855
1864
|
}
|
|
1856
1865
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1857
1866
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
@@ -2779,6 +2788,29 @@ function createChart(element, options = {}) {
|
|
|
2779
2788
|
canvas.addEventListener("pointerleave", endPointerDrag);
|
|
2780
2789
|
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2781
2790
|
canvas.addEventListener("dblclick", onDoubleClick);
|
|
2791
|
+
const updateOptions = (nextOptions) => {
|
|
2792
|
+
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2793
|
+
const previousWidth = width;
|
|
2794
|
+
const previousHeight = height;
|
|
2795
|
+
mergedOptions = mergeChartOptions(mergedOptions, nextOptions);
|
|
2796
|
+
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
2797
|
+
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
2798
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2799
|
+
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
2800
|
+
doubleClickAction = mergedOptions.doubleClickAction;
|
|
2801
|
+
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2802
|
+
if (!isTickerSmoothingEnabled) {
|
|
2803
|
+
smoothedTickerPrice = null;
|
|
2804
|
+
tickerPriceTarget = null;
|
|
2805
|
+
if (smoothingRafId !== null) {
|
|
2806
|
+
cancelAnimationFrame(smoothingRafId);
|
|
2807
|
+
smoothingRafId = null;
|
|
2808
|
+
}
|
|
2809
|
+
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2810
|
+
pushSmoothedPrice(data[data.length - 1].c);
|
|
2811
|
+
}
|
|
2812
|
+
draw();
|
|
2813
|
+
};
|
|
2782
2814
|
const resize = (nextWidth, nextHeight) => {
|
|
2783
2815
|
if (nextWidth && nextWidth > 0) {
|
|
2784
2816
|
width = nextWidth;
|
|
@@ -2786,6 +2818,7 @@ function createChart(element, options = {}) {
|
|
|
2786
2818
|
if (nextHeight && nextHeight > 0) {
|
|
2787
2819
|
height = nextHeight;
|
|
2788
2820
|
}
|
|
2821
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2789
2822
|
draw();
|
|
2790
2823
|
};
|
|
2791
2824
|
const setData = (nextData) => {
|
|
@@ -2989,6 +3022,7 @@ function createChart(element, options = {}) {
|
|
|
2989
3022
|
};
|
|
2990
3023
|
draw();
|
|
2991
3024
|
return {
|
|
3025
|
+
updateOptions,
|
|
2992
3026
|
setData,
|
|
2993
3027
|
setPriceLines,
|
|
2994
3028
|
addPriceLine,
|
package/dist/index.cjs
CHANGED
|
@@ -177,6 +177,47 @@ var DEFAULT_OPTIONS = {
|
|
|
177
177
|
dashPatterns: DEFAULT_DASH_PATTERNS,
|
|
178
178
|
indicators: []
|
|
179
179
|
};
|
|
180
|
+
var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
181
|
+
...baseOptions,
|
|
182
|
+
...options,
|
|
183
|
+
axis: {
|
|
184
|
+
...baseOptions.axis,
|
|
185
|
+
...options.axis ?? {},
|
|
186
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
187
|
+
},
|
|
188
|
+
xAxis: {
|
|
189
|
+
...baseOptions.xAxis,
|
|
190
|
+
...options.axis ?? {},
|
|
191
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
192
|
+
...options.xAxis ?? {}
|
|
193
|
+
},
|
|
194
|
+
yAxis: {
|
|
195
|
+
...baseOptions.yAxis,
|
|
196
|
+
...options.axis ?? {},
|
|
197
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
198
|
+
...options.yAxis ?? {}
|
|
199
|
+
},
|
|
200
|
+
crosshair: {
|
|
201
|
+
...baseOptions.crosshair,
|
|
202
|
+
...options.crosshair ?? {}
|
|
203
|
+
},
|
|
204
|
+
grid: {
|
|
205
|
+
...baseOptions.grid,
|
|
206
|
+
...options.grid ?? {}
|
|
207
|
+
},
|
|
208
|
+
watermark: {
|
|
209
|
+
...baseOptions.watermark,
|
|
210
|
+
...options.watermark ?? {}
|
|
211
|
+
},
|
|
212
|
+
tickerLine: {
|
|
213
|
+
...baseOptions.tickerLine,
|
|
214
|
+
...options.tickerLine ?? {}
|
|
215
|
+
},
|
|
216
|
+
dashPatterns: {
|
|
217
|
+
...baseOptions.dashPatterns,
|
|
218
|
+
...options.dashPatterns ?? {}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
180
221
|
var getIndicatorSourceValue = (point, source) => {
|
|
181
222
|
if (source === "open") return point.o;
|
|
182
223
|
if (source === "high") return point.h;
|
|
@@ -728,47 +769,7 @@ var BUILTIN_INDICATORS = [
|
|
|
728
769
|
BUILTIN_ATR_INDICATOR
|
|
729
770
|
];
|
|
730
771
|
function createChart(element, options = {}) {
|
|
731
|
-
|
|
732
|
-
...DEFAULT_OPTIONS,
|
|
733
|
-
...options,
|
|
734
|
-
axis: {
|
|
735
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
736
|
-
...options.axis ?? {},
|
|
737
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
738
|
-
},
|
|
739
|
-
xAxis: {
|
|
740
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
741
|
-
...options.axis ?? {},
|
|
742
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
743
|
-
...options.xAxis ?? {}
|
|
744
|
-
},
|
|
745
|
-
yAxis: {
|
|
746
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
747
|
-
...options.axis ?? {},
|
|
748
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
749
|
-
...options.yAxis ?? {}
|
|
750
|
-
},
|
|
751
|
-
crosshair: {
|
|
752
|
-
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
753
|
-
...options.crosshair ?? {}
|
|
754
|
-
},
|
|
755
|
-
grid: {
|
|
756
|
-
...DEFAULT_GRID_OPTIONS,
|
|
757
|
-
...options.grid
|
|
758
|
-
},
|
|
759
|
-
watermark: {
|
|
760
|
-
...DEFAULT_WATERMARK_OPTIONS,
|
|
761
|
-
...options.watermark
|
|
762
|
-
},
|
|
763
|
-
tickerLine: {
|
|
764
|
-
...DEFAULT_OPTIONS.tickerLine,
|
|
765
|
-
...options.tickerLine
|
|
766
|
-
},
|
|
767
|
-
dashPatterns: {
|
|
768
|
-
...DEFAULT_DASH_PATTERNS,
|
|
769
|
-
...options.dashPatterns ?? {}
|
|
770
|
-
}
|
|
771
|
-
};
|
|
772
|
+
let mergedOptions = mergeChartOptions(DEFAULT_OPTIONS, options);
|
|
772
773
|
let width = mergedOptions.width;
|
|
773
774
|
let height = mergedOptions.height;
|
|
774
775
|
let data = [];
|
|
@@ -859,7 +860,7 @@ function createChart(element, options = {}) {
|
|
|
859
860
|
const diff = tickerPriceTarget - smoothedTickerPrice;
|
|
860
861
|
if (Math.abs(diff) < 1e-9) {
|
|
861
862
|
smoothedTickerPrice = tickerPriceTarget;
|
|
862
|
-
draw();
|
|
863
|
+
draw({ updateAutoScale: false });
|
|
863
864
|
return;
|
|
864
865
|
}
|
|
865
866
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
@@ -867,7 +868,7 @@ function createChart(element, options = {}) {
|
|
|
867
868
|
const dt = 1 / 60;
|
|
868
869
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
869
870
|
smoothedTickerPrice += diff * lerp;
|
|
870
|
-
draw();
|
|
871
|
+
draw({ updateAutoScale: false });
|
|
871
872
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
872
873
|
};
|
|
873
874
|
const pushSmoothedPrice = (target) => {
|
|
@@ -1584,7 +1585,8 @@ function createChart(element, options = {}) {
|
|
|
1584
1585
|
crosshairPoint = point;
|
|
1585
1586
|
draw();
|
|
1586
1587
|
};
|
|
1587
|
-
const draw = () => {
|
|
1588
|
+
const draw = (options2 = {}) => {
|
|
1589
|
+
const shouldUpdateAutoScale = options2.updateAutoScale ?? true;
|
|
1588
1590
|
orderActionRegions = [];
|
|
1589
1591
|
orderDragRegions = [];
|
|
1590
1592
|
crosshairPriceActionRegion = null;
|
|
@@ -1690,6 +1692,9 @@ function createChart(element, options = {}) {
|
|
|
1690
1692
|
}
|
|
1691
1693
|
const visibleValues = [];
|
|
1692
1694
|
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1695
|
+
if (mergedOptions.autoScaleIgnoreLatestCandle && data.length > 1 && idx === data.length - 1) {
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1693
1698
|
const value = series[idx];
|
|
1694
1699
|
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1695
1700
|
visibleValues.push(value);
|
|
@@ -1712,7 +1717,7 @@ function createChart(element, options = {}) {
|
|
|
1712
1717
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1713
1718
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
1714
1719
|
const smoothing = clamp(mergedOptions.autoScaleSmoothing, 0, 1);
|
|
1715
|
-
if (yMinOverride === null || yMaxOverride === null) {
|
|
1720
|
+
if ((yMinOverride === null || yMaxOverride === null) && (shouldUpdateAutoScale || autoYMin === null || autoYMax === null)) {
|
|
1716
1721
|
if (autoYMin === null || autoYMax === null) {
|
|
1717
1722
|
autoYMin = autoMin;
|
|
1718
1723
|
autoYMax = autoMax;
|
|
@@ -1854,15 +1859,16 @@ function createChart(element, options = {}) {
|
|
|
1854
1859
|
continue;
|
|
1855
1860
|
}
|
|
1856
1861
|
const isLastCandle = useSmoothedCandle && index === lastDataIndex;
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
1859
|
-
const
|
|
1862
|
+
const actualDirection = point.c >= point.o ? "up" : "down";
|
|
1863
|
+
const displayClose = isLastCandle ? actualDirection === "up" ? Math.max(point.o, smoothedTickerPrice) : Math.min(point.o, smoothedTickerPrice) : point.c;
|
|
1864
|
+
const displayHigh = isLastCandle ? actualDirection === "up" ? Math.max(point.h, displayClose) : point.h : point.h;
|
|
1865
|
+
const displayLow = isLastCandle ? actualDirection === "up" ? point.l : Math.min(point.l, displayClose) : point.l;
|
|
1860
1866
|
const centerX = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1861
1867
|
const openY = yFromPrice(point.o);
|
|
1862
1868
|
const closeY = yFromPrice(displayClose);
|
|
1863
1869
|
const highY = yFromPrice(displayHigh);
|
|
1864
1870
|
const lowY = yFromPrice(displayLow);
|
|
1865
|
-
const direction = isLastCandle ?
|
|
1871
|
+
const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
|
|
1866
1872
|
const candleColor = direction === "up" ? mergedOptions.upColor : mergedOptions.downColor;
|
|
1867
1873
|
const roundedCenterX = Math.round(centerX);
|
|
1868
1874
|
ctx.strokeStyle = candleColor;
|
|
@@ -1872,10 +1878,13 @@ function createChart(element, options = {}) {
|
|
|
1872
1878
|
ctx.lineTo(roundedCenterX + 0.5, crisp(lowY));
|
|
1873
1879
|
ctx.stroke();
|
|
1874
1880
|
const bodyLeft = roundedCenterX - Math.floor(bodyWidth / 2);
|
|
1875
|
-
const
|
|
1876
|
-
const
|
|
1881
|
+
const openYPx = Math.round(openY);
|
|
1882
|
+
const closeYPx = Math.round(closeY);
|
|
1883
|
+
const bodyIsUp = displayClose >= point.o;
|
|
1884
|
+
const bodyTop = bodyIsUp ? Math.min(closeYPx, openYPx - 1) : openYPx;
|
|
1885
|
+
const bodyBottom = bodyIsUp ? openYPx : Math.max(closeYPx, openYPx + 1);
|
|
1877
1886
|
ctx.fillStyle = candleColor;
|
|
1878
|
-
ctx.fillRect(bodyLeft,
|
|
1887
|
+
ctx.fillRect(bodyLeft, bodyTop, bodyWidth, bodyBottom - bodyTop);
|
|
1879
1888
|
}
|
|
1880
1889
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1881
1890
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
@@ -2803,6 +2812,29 @@ function createChart(element, options = {}) {
|
|
|
2803
2812
|
canvas.addEventListener("pointerleave", endPointerDrag);
|
|
2804
2813
|
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2805
2814
|
canvas.addEventListener("dblclick", onDoubleClick);
|
|
2815
|
+
const updateOptions = (nextOptions) => {
|
|
2816
|
+
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2817
|
+
const previousWidth = width;
|
|
2818
|
+
const previousHeight = height;
|
|
2819
|
+
mergedOptions = mergeChartOptions(mergedOptions, nextOptions);
|
|
2820
|
+
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
2821
|
+
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
2822
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2823
|
+
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
2824
|
+
doubleClickAction = mergedOptions.doubleClickAction;
|
|
2825
|
+
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2826
|
+
if (!isTickerSmoothingEnabled) {
|
|
2827
|
+
smoothedTickerPrice = null;
|
|
2828
|
+
tickerPriceTarget = null;
|
|
2829
|
+
if (smoothingRafId !== null) {
|
|
2830
|
+
cancelAnimationFrame(smoothingRafId);
|
|
2831
|
+
smoothingRafId = null;
|
|
2832
|
+
}
|
|
2833
|
+
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2834
|
+
pushSmoothedPrice(data[data.length - 1].c);
|
|
2835
|
+
}
|
|
2836
|
+
draw();
|
|
2837
|
+
};
|
|
2806
2838
|
const resize = (nextWidth, nextHeight) => {
|
|
2807
2839
|
if (nextWidth && nextWidth > 0) {
|
|
2808
2840
|
width = nextWidth;
|
|
@@ -2810,6 +2842,7 @@ function createChart(element, options = {}) {
|
|
|
2810
2842
|
if (nextHeight && nextHeight > 0) {
|
|
2811
2843
|
height = nextHeight;
|
|
2812
2844
|
}
|
|
2845
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2813
2846
|
draw();
|
|
2814
2847
|
};
|
|
2815
2848
|
const setData = (nextData) => {
|
|
@@ -3013,6 +3046,7 @@ function createChart(element, options = {}) {
|
|
|
3013
3046
|
};
|
|
3014
3047
|
draw();
|
|
3015
3048
|
return {
|
|
3049
|
+
updateOptions,
|
|
3016
3050
|
setData,
|
|
3017
3051
|
setPriceLines,
|
|
3018
3052
|
addPriceLine,
|
package/dist/index.d.cts
CHANGED
|
@@ -263,6 +263,7 @@ interface TickerLineOptions {
|
|
|
263
263
|
smoothingSpeed?: number;
|
|
264
264
|
}
|
|
265
265
|
interface ChartInstance {
|
|
266
|
+
updateOptions: (options: ChartOptions) => void;
|
|
266
267
|
setData: (data: OhlcDataPoint[]) => void;
|
|
267
268
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
268
269
|
addPriceLine: (line: PriceLineOptions) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -263,6 +263,7 @@ interface TickerLineOptions {
|
|
|
263
263
|
smoothingSpeed?: number;
|
|
264
264
|
}
|
|
265
265
|
interface ChartInstance {
|
|
266
|
+
updateOptions: (options: ChartOptions) => void;
|
|
266
267
|
setData: (data: OhlcDataPoint[]) => void;
|
|
267
268
|
setPriceLines: (lines: PriceLineOptions[]) => void;
|
|
268
269
|
addPriceLine: (line: PriceLineOptions) => string;
|
package/dist/index.js
CHANGED
|
@@ -153,6 +153,47 @@ var DEFAULT_OPTIONS = {
|
|
|
153
153
|
dashPatterns: DEFAULT_DASH_PATTERNS,
|
|
154
154
|
indicators: []
|
|
155
155
|
};
|
|
156
|
+
var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
157
|
+
...baseOptions,
|
|
158
|
+
...options,
|
|
159
|
+
axis: {
|
|
160
|
+
...baseOptions.axis,
|
|
161
|
+
...options.axis ?? {},
|
|
162
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
163
|
+
},
|
|
164
|
+
xAxis: {
|
|
165
|
+
...baseOptions.xAxis,
|
|
166
|
+
...options.axis ?? {},
|
|
167
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
168
|
+
...options.xAxis ?? {}
|
|
169
|
+
},
|
|
170
|
+
yAxis: {
|
|
171
|
+
...baseOptions.yAxis,
|
|
172
|
+
...options.axis ?? {},
|
|
173
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
174
|
+
...options.yAxis ?? {}
|
|
175
|
+
},
|
|
176
|
+
crosshair: {
|
|
177
|
+
...baseOptions.crosshair,
|
|
178
|
+
...options.crosshair ?? {}
|
|
179
|
+
},
|
|
180
|
+
grid: {
|
|
181
|
+
...baseOptions.grid,
|
|
182
|
+
...options.grid ?? {}
|
|
183
|
+
},
|
|
184
|
+
watermark: {
|
|
185
|
+
...baseOptions.watermark,
|
|
186
|
+
...options.watermark ?? {}
|
|
187
|
+
},
|
|
188
|
+
tickerLine: {
|
|
189
|
+
...baseOptions.tickerLine,
|
|
190
|
+
...options.tickerLine ?? {}
|
|
191
|
+
},
|
|
192
|
+
dashPatterns: {
|
|
193
|
+
...baseOptions.dashPatterns,
|
|
194
|
+
...options.dashPatterns ?? {}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
156
197
|
var getIndicatorSourceValue = (point, source) => {
|
|
157
198
|
if (source === "open") return point.o;
|
|
158
199
|
if (source === "high") return point.h;
|
|
@@ -704,47 +745,7 @@ var BUILTIN_INDICATORS = [
|
|
|
704
745
|
BUILTIN_ATR_INDICATOR
|
|
705
746
|
];
|
|
706
747
|
function createChart(element, options = {}) {
|
|
707
|
-
|
|
708
|
-
...DEFAULT_OPTIONS,
|
|
709
|
-
...options,
|
|
710
|
-
axis: {
|
|
711
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
712
|
-
...options.axis ?? {},
|
|
713
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
714
|
-
},
|
|
715
|
-
xAxis: {
|
|
716
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
717
|
-
...options.axis ?? {},
|
|
718
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
719
|
-
...options.xAxis ?? {}
|
|
720
|
-
},
|
|
721
|
-
yAxis: {
|
|
722
|
-
...DEFAULT_AXIS_OPTIONS,
|
|
723
|
-
...options.axis ?? {},
|
|
724
|
-
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
725
|
-
...options.yAxis ?? {}
|
|
726
|
-
},
|
|
727
|
-
crosshair: {
|
|
728
|
-
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
729
|
-
...options.crosshair ?? {}
|
|
730
|
-
},
|
|
731
|
-
grid: {
|
|
732
|
-
...DEFAULT_GRID_OPTIONS,
|
|
733
|
-
...options.grid
|
|
734
|
-
},
|
|
735
|
-
watermark: {
|
|
736
|
-
...DEFAULT_WATERMARK_OPTIONS,
|
|
737
|
-
...options.watermark
|
|
738
|
-
},
|
|
739
|
-
tickerLine: {
|
|
740
|
-
...DEFAULT_OPTIONS.tickerLine,
|
|
741
|
-
...options.tickerLine
|
|
742
|
-
},
|
|
743
|
-
dashPatterns: {
|
|
744
|
-
...DEFAULT_DASH_PATTERNS,
|
|
745
|
-
...options.dashPatterns ?? {}
|
|
746
|
-
}
|
|
747
|
-
};
|
|
748
|
+
let mergedOptions = mergeChartOptions(DEFAULT_OPTIONS, options);
|
|
748
749
|
let width = mergedOptions.width;
|
|
749
750
|
let height = mergedOptions.height;
|
|
750
751
|
let data = [];
|
|
@@ -835,7 +836,7 @@ function createChart(element, options = {}) {
|
|
|
835
836
|
const diff = tickerPriceTarget - smoothedTickerPrice;
|
|
836
837
|
if (Math.abs(diff) < 1e-9) {
|
|
837
838
|
smoothedTickerPrice = tickerPriceTarget;
|
|
838
|
-
draw();
|
|
839
|
+
draw({ updateAutoScale: false });
|
|
839
840
|
return;
|
|
840
841
|
}
|
|
841
842
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
@@ -843,7 +844,7 @@ function createChart(element, options = {}) {
|
|
|
843
844
|
const dt = 1 / 60;
|
|
844
845
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
845
846
|
smoothedTickerPrice += diff * lerp;
|
|
846
|
-
draw();
|
|
847
|
+
draw({ updateAutoScale: false });
|
|
847
848
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
848
849
|
};
|
|
849
850
|
const pushSmoothedPrice = (target) => {
|
|
@@ -1560,7 +1561,8 @@ function createChart(element, options = {}) {
|
|
|
1560
1561
|
crosshairPoint = point;
|
|
1561
1562
|
draw();
|
|
1562
1563
|
};
|
|
1563
|
-
const draw = () => {
|
|
1564
|
+
const draw = (options2 = {}) => {
|
|
1565
|
+
const shouldUpdateAutoScale = options2.updateAutoScale ?? true;
|
|
1564
1566
|
orderActionRegions = [];
|
|
1565
1567
|
orderDragRegions = [];
|
|
1566
1568
|
crosshairPriceActionRegion = null;
|
|
@@ -1666,6 +1668,9 @@ function createChart(element, options = {}) {
|
|
|
1666
1668
|
}
|
|
1667
1669
|
const visibleValues = [];
|
|
1668
1670
|
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1671
|
+
if (mergedOptions.autoScaleIgnoreLatestCandle && data.length > 1 && idx === data.length - 1) {
|
|
1672
|
+
continue;
|
|
1673
|
+
}
|
|
1669
1674
|
const value = series[idx];
|
|
1670
1675
|
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1671
1676
|
visibleValues.push(value);
|
|
@@ -1688,7 +1693,7 @@ function createChart(element, options = {}) {
|
|
|
1688
1693
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1689
1694
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
1690
1695
|
const smoothing = clamp(mergedOptions.autoScaleSmoothing, 0, 1);
|
|
1691
|
-
if (yMinOverride === null || yMaxOverride === null) {
|
|
1696
|
+
if ((yMinOverride === null || yMaxOverride === null) && (shouldUpdateAutoScale || autoYMin === null || autoYMax === null)) {
|
|
1692
1697
|
if (autoYMin === null || autoYMax === null) {
|
|
1693
1698
|
autoYMin = autoMin;
|
|
1694
1699
|
autoYMax = autoMax;
|
|
@@ -1830,15 +1835,16 @@ function createChart(element, options = {}) {
|
|
|
1830
1835
|
continue;
|
|
1831
1836
|
}
|
|
1832
1837
|
const isLastCandle = useSmoothedCandle && index === lastDataIndex;
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
1835
|
-
const
|
|
1838
|
+
const actualDirection = point.c >= point.o ? "up" : "down";
|
|
1839
|
+
const displayClose = isLastCandle ? actualDirection === "up" ? Math.max(point.o, smoothedTickerPrice) : Math.min(point.o, smoothedTickerPrice) : point.c;
|
|
1840
|
+
const displayHigh = isLastCandle ? actualDirection === "up" ? Math.max(point.h, displayClose) : point.h : point.h;
|
|
1841
|
+
const displayLow = isLastCandle ? actualDirection === "up" ? point.l : Math.min(point.l, displayClose) : point.l;
|
|
1836
1842
|
const centerX = chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1837
1843
|
const openY = yFromPrice(point.o);
|
|
1838
1844
|
const closeY = yFromPrice(displayClose);
|
|
1839
1845
|
const highY = yFromPrice(displayHigh);
|
|
1840
1846
|
const lowY = yFromPrice(displayLow);
|
|
1841
|
-
const direction = isLastCandle ?
|
|
1847
|
+
const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
|
|
1842
1848
|
const candleColor = direction === "up" ? mergedOptions.upColor : mergedOptions.downColor;
|
|
1843
1849
|
const roundedCenterX = Math.round(centerX);
|
|
1844
1850
|
ctx.strokeStyle = candleColor;
|
|
@@ -1848,10 +1854,13 @@ function createChart(element, options = {}) {
|
|
|
1848
1854
|
ctx.lineTo(roundedCenterX + 0.5, crisp(lowY));
|
|
1849
1855
|
ctx.stroke();
|
|
1850
1856
|
const bodyLeft = roundedCenterX - Math.floor(bodyWidth / 2);
|
|
1851
|
-
const
|
|
1852
|
-
const
|
|
1857
|
+
const openYPx = Math.round(openY);
|
|
1858
|
+
const closeYPx = Math.round(closeY);
|
|
1859
|
+
const bodyIsUp = displayClose >= point.o;
|
|
1860
|
+
const bodyTop = bodyIsUp ? Math.min(closeYPx, openYPx - 1) : openYPx;
|
|
1861
|
+
const bodyBottom = bodyIsUp ? openYPx : Math.max(closeYPx, openYPx + 1);
|
|
1853
1862
|
ctx.fillStyle = candleColor;
|
|
1854
|
-
ctx.fillRect(bodyLeft,
|
|
1863
|
+
ctx.fillRect(bodyLeft, bodyTop, bodyWidth, bodyBottom - bodyTop);
|
|
1855
1864
|
}
|
|
1856
1865
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1857
1866
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
@@ -2779,6 +2788,29 @@ function createChart(element, options = {}) {
|
|
|
2779
2788
|
canvas.addEventListener("pointerleave", endPointerDrag);
|
|
2780
2789
|
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2781
2790
|
canvas.addEventListener("dblclick", onDoubleClick);
|
|
2791
|
+
const updateOptions = (nextOptions) => {
|
|
2792
|
+
const wasTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2793
|
+
const previousWidth = width;
|
|
2794
|
+
const previousHeight = height;
|
|
2795
|
+
mergedOptions = mergeChartOptions(mergedOptions, nextOptions);
|
|
2796
|
+
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
2797
|
+
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
2798
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2799
|
+
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
2800
|
+
doubleClickAction = mergedOptions.doubleClickAction;
|
|
2801
|
+
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
2802
|
+
if (!isTickerSmoothingEnabled) {
|
|
2803
|
+
smoothedTickerPrice = null;
|
|
2804
|
+
tickerPriceTarget = null;
|
|
2805
|
+
if (smoothingRafId !== null) {
|
|
2806
|
+
cancelAnimationFrame(smoothingRafId);
|
|
2807
|
+
smoothingRafId = null;
|
|
2808
|
+
}
|
|
2809
|
+
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2810
|
+
pushSmoothedPrice(data[data.length - 1].c);
|
|
2811
|
+
}
|
|
2812
|
+
draw();
|
|
2813
|
+
};
|
|
2782
2814
|
const resize = (nextWidth, nextHeight) => {
|
|
2783
2815
|
if (nextWidth && nextWidth > 0) {
|
|
2784
2816
|
width = nextWidth;
|
|
@@ -2786,6 +2818,7 @@ function createChart(element, options = {}) {
|
|
|
2786
2818
|
if (nextHeight && nextHeight > 0) {
|
|
2787
2819
|
height = nextHeight;
|
|
2788
2820
|
}
|
|
2821
|
+
mergedOptions = { ...mergedOptions, width, height };
|
|
2789
2822
|
draw();
|
|
2790
2823
|
};
|
|
2791
2824
|
const setData = (nextData) => {
|
|
@@ -2989,6 +3022,7 @@ function createChart(element, options = {}) {
|
|
|
2989
3022
|
};
|
|
2990
3023
|
draw();
|
|
2991
3024
|
return {
|
|
3025
|
+
updateOptions,
|
|
2992
3026
|
setData,
|
|
2993
3027
|
setPriceLines,
|
|
2994
3028
|
addPriceLine,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hyperprop-charting-library",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
4
4
|
"description": "Lightweight TypeScript charting core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/hyperprop-charting-library.cjs",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean && cp \"./dist/index.js\" \"./dist/hyperprop-charting-library.js\" && cp \"./dist/index.cjs\" \"./dist/hyperprop-charting-library.cjs\" && cp \"./dist/index.d.ts\" \"./dist/hyperprop-charting-library.d.ts\"",
|
|
23
|
-
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
23
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch --onSuccess \"cp ./dist/index.js ./dist/hyperprop-charting-library.js && cp ./dist/index.cjs ./dist/hyperprop-charting-library.cjs && cp ./dist/index.d.ts ./dist/hyperprop-charting-library.d.ts\"",
|
|
24
24
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|