hyperprop-charting-library 0.1.129 → 0.1.130
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 +382 -62
- package/dist/hyperprop-charting-library.d.ts +26 -1
- package/dist/hyperprop-charting-library.js +382 -62
- package/dist/index.cjs +382 -62
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +382 -62
- package/docs/API.md +9 -1
- package/package.json +1 -1
|
@@ -785,6 +785,40 @@ var fillBetweenSeries = (ctx, renderContext, upper, lower, color, opacity) => {
|
|
|
785
785
|
flushRun(renderContext.endIndex + 1);
|
|
786
786
|
ctx.restore();
|
|
787
787
|
};
|
|
788
|
+
var drawPaneHorizontalGrid = (ctx, renderContext, minValue, maxValue) => {
|
|
789
|
+
const grid = renderContext.grid;
|
|
790
|
+
if (!grid || !grid.horizontalLines) return;
|
|
791
|
+
const range = maxValue - minValue;
|
|
792
|
+
if (!(range > 0) || !Number.isFinite(range)) return;
|
|
793
|
+
const targetCount = Math.max(2, Math.round(renderContext.chartHeight / 42));
|
|
794
|
+
const targetStep = range / targetCount;
|
|
795
|
+
if (!(targetStep > 0) || !Number.isFinite(targetStep)) return;
|
|
796
|
+
const base = Math.pow(10, Math.floor(Math.log10(targetStep)));
|
|
797
|
+
const frac = targetStep / base;
|
|
798
|
+
const step = (frac <= 1 ? 1 : frac <= 2 ? 2 : frac <= 2.5 ? 2.5 : frac <= 5 ? 5 : 10) * base;
|
|
799
|
+
ctx.save();
|
|
800
|
+
ctx.globalAlpha = Math.min(1, Math.max(0, grid.opacity));
|
|
801
|
+
ctx.strokeStyle = grid.color;
|
|
802
|
+
ctx.lineWidth = 1;
|
|
803
|
+
ctx.setLineDash([]);
|
|
804
|
+
ctx.beginPath();
|
|
805
|
+
const firstTick = Math.ceil(minValue / step) * step;
|
|
806
|
+
const edgeInset = renderContext.chartHeight * 0.04;
|
|
807
|
+
for (let i = 0; i < 64; i += 1) {
|
|
808
|
+
const value = firstTick + i * step;
|
|
809
|
+
if (value > maxValue) break;
|
|
810
|
+
const ratio = (value - minValue) / range;
|
|
811
|
+
const y = renderContext.chartBottom - ratio * renderContext.chartHeight;
|
|
812
|
+
if (y > renderContext.chartBottom - edgeInset || y < renderContext.chartBottom - renderContext.chartHeight + edgeInset) {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
const crispY = Math.round(y) + 0.5;
|
|
816
|
+
ctx.moveTo(renderContext.chartLeft, crispY);
|
|
817
|
+
ctx.lineTo(renderContext.chartRight, crispY);
|
|
818
|
+
}
|
|
819
|
+
ctx.stroke();
|
|
820
|
+
ctx.restore();
|
|
821
|
+
};
|
|
788
822
|
var drawSeparateSeries = (ctx, renderContext, values, color, width, minOverride, maxOverride, guideLines, options = {}) => {
|
|
789
823
|
const visible = [];
|
|
790
824
|
for (let index = renderContext.startIndex; index <= renderContext.endIndex; index += 1) {
|
|
@@ -796,6 +830,7 @@ var drawSeparateSeries = (ctx, renderContext, values, color, width, minOverride,
|
|
|
796
830
|
if (visible.length === 0) return void 0;
|
|
797
831
|
const minValue = minOverride ?? Math.min(...visible);
|
|
798
832
|
const maxValue = maxOverride ?? Math.max(...visible);
|
|
833
|
+
drawPaneHorizontalGrid(ctx, renderContext, minValue, maxValue);
|
|
799
834
|
const range = maxValue - minValue || 1;
|
|
800
835
|
const yFromValue = (value) => {
|
|
801
836
|
const ratio = (value - minValue) / range;
|
|
@@ -1190,7 +1225,7 @@ var BUILTIN_STDDEV_INDICATOR = {
|
|
|
1190
1225
|
name: "StdDev",
|
|
1191
1226
|
pane: "separate",
|
|
1192
1227
|
paneHeightRatio: 0.16,
|
|
1193
|
-
defaultInputs: { length: 20, source: "close", color: "#f97316", width: 2, showValueLine:
|
|
1228
|
+
defaultInputs: { length: 20, source: "close", color: "#f97316", width: 2, showValueLine: true },
|
|
1194
1229
|
draw: (ctx, renderContext, inputs) => {
|
|
1195
1230
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
1196
1231
|
const values = withCachedSeries(
|
|
@@ -1201,7 +1236,7 @@ var BUILTIN_STDDEV_INDICATOR = {
|
|
|
1201
1236
|
return drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#f97316", Number(inputs.width) || 2, void 0, void 0, void 0, {
|
|
1202
1237
|
title: `StdDev ${length}`,
|
|
1203
1238
|
decimals: 2,
|
|
1204
|
-
valueLine: inputs.showValueLine
|
|
1239
|
+
valueLine: inputs.showValueLine !== false
|
|
1205
1240
|
});
|
|
1206
1241
|
}
|
|
1207
1242
|
};
|
|
@@ -1210,14 +1245,14 @@ var BUILTIN_ATR_INDICATOR = {
|
|
|
1210
1245
|
name: "ATR",
|
|
1211
1246
|
pane: "separate",
|
|
1212
1247
|
paneHeightRatio: 0.16,
|
|
1213
|
-
defaultInputs: { length: 14, color: "#eab308", width: 2, showValueLine:
|
|
1248
|
+
defaultInputs: { length: 14, color: "#eab308", width: 2, showValueLine: true },
|
|
1214
1249
|
draw: (ctx, renderContext, inputs) => {
|
|
1215
1250
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
1216
1251
|
const values = withCachedSeries(`atr|${length}`, renderContext.data, () => computeAtrSeries(renderContext.data, length));
|
|
1217
1252
|
return drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#eab308", Number(inputs.width) || 2, void 0, void 0, void 0, {
|
|
1218
1253
|
title: `ATR ${length}`,
|
|
1219
1254
|
decimals: 2,
|
|
1220
|
-
valueLine: inputs.showValueLine
|
|
1255
|
+
valueLine: inputs.showValueLine !== false
|
|
1221
1256
|
});
|
|
1222
1257
|
}
|
|
1223
1258
|
};
|
|
@@ -1234,7 +1269,7 @@ var BUILTIN_RSI_INDICATOR = {
|
|
|
1234
1269
|
showValueLabel: true,
|
|
1235
1270
|
showGuideLines: true,
|
|
1236
1271
|
showScaleLabels: true,
|
|
1237
|
-
showValueLine:
|
|
1272
|
+
showValueLine: true
|
|
1238
1273
|
},
|
|
1239
1274
|
draw: (ctx, renderContext, inputs) => {
|
|
1240
1275
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
@@ -1258,7 +1293,7 @@ var BUILTIN_RSI_INDICATOR = {
|
|
|
1258
1293
|
valueLabelBackgroundColor: "#9E9E9E",
|
|
1259
1294
|
valueLabelTextColor: "#0f172a",
|
|
1260
1295
|
showLegend: inputs.showLegend !== false,
|
|
1261
|
-
valueLine: inputs.showValueLine
|
|
1296
|
+
valueLine: inputs.showValueLine !== false
|
|
1262
1297
|
}
|
|
1263
1298
|
);
|
|
1264
1299
|
}
|
|
@@ -1315,6 +1350,7 @@ var drawSeparateMultiSeries = (ctx, renderContext, seriesList, options = {}) =>
|
|
|
1315
1350
|
const ratio = (value - minValue) / range;
|
|
1316
1351
|
return renderContext.chartBottom - ratio * renderContext.chartHeight;
|
|
1317
1352
|
};
|
|
1353
|
+
drawPaneHorizontalGrid(ctx, renderContext, minValue, maxValue);
|
|
1318
1354
|
if (options.guideLines && options.guideLines.length > 0) {
|
|
1319
1355
|
ctx.save();
|
|
1320
1356
|
ctx.strokeStyle = "rgba(148,163,184,0.35)";
|
|
@@ -1766,7 +1802,7 @@ var BUILTIN_MACD_INDICATOR = {
|
|
|
1766
1802
|
signalColor: "#ff6d00",
|
|
1767
1803
|
histUpColor: "#26a69a",
|
|
1768
1804
|
histDownColor: "#ef5350",
|
|
1769
|
-
showValueLine:
|
|
1805
|
+
showValueLine: true
|
|
1770
1806
|
},
|
|
1771
1807
|
draw: (ctx, renderContext, inputs) => {
|
|
1772
1808
|
const fast = clampIndicatorLength(inputs.fast, 12);
|
|
@@ -1796,7 +1832,7 @@ var BUILTIN_MACD_INDICATOR = {
|
|
|
1796
1832
|
guideLines: [0],
|
|
1797
1833
|
decimals: 2,
|
|
1798
1834
|
valueLabelSeriesIndex: 1,
|
|
1799
|
-
valueLines: inputs.showValueLine
|
|
1835
|
+
valueLines: inputs.showValueLine !== false
|
|
1800
1836
|
}
|
|
1801
1837
|
);
|
|
1802
1838
|
}
|
|
@@ -1806,7 +1842,7 @@ var BUILTIN_STOCHASTIC_INDICATOR = {
|
|
|
1806
1842
|
name: "Stoch",
|
|
1807
1843
|
pane: "separate",
|
|
1808
1844
|
paneHeightRatio: 0.18,
|
|
1809
|
-
defaultInputs: { kLength: 14, kSmoothing: 1, dLength: 3, kColor: "#2962ff", dColor: "#ff6d00", showValueLine:
|
|
1845
|
+
defaultInputs: { kLength: 14, kSmoothing: 1, dLength: 3, kColor: "#2962ff", dColor: "#ff6d00", showValueLine: true },
|
|
1810
1846
|
draw: (ctx, renderContext, inputs) => {
|
|
1811
1847
|
const kLength = clampIndicatorLength(inputs.kLength, 14);
|
|
1812
1848
|
const kSmoothing = clampIndicatorLength(inputs.kSmoothing, 1);
|
|
@@ -1830,7 +1866,7 @@ var BUILTIN_STOCHASTIC_INDICATOR = {
|
|
|
1830
1866
|
guideLines: [20, 80],
|
|
1831
1867
|
axisTicks: [0, 20, 50, 80, 100],
|
|
1832
1868
|
decimals: 2,
|
|
1833
|
-
valueLines: inputs.showValueLine
|
|
1869
|
+
valueLines: inputs.showValueLine !== false
|
|
1834
1870
|
}
|
|
1835
1871
|
);
|
|
1836
1872
|
}
|
|
@@ -1847,7 +1883,7 @@ var BUILTIN_STOCHRSI_INDICATOR = {
|
|
|
1847
1883
|
dSmoothing: 3,
|
|
1848
1884
|
kColor: "#2962ff",
|
|
1849
1885
|
dColor: "#ff6d00",
|
|
1850
|
-
showValueLine:
|
|
1886
|
+
showValueLine: true
|
|
1851
1887
|
},
|
|
1852
1888
|
draw: (ctx, renderContext, inputs) => {
|
|
1853
1889
|
const rsiLength = clampIndicatorLength(inputs.rsiLength, 14);
|
|
@@ -1873,7 +1909,7 @@ var BUILTIN_STOCHRSI_INDICATOR = {
|
|
|
1873
1909
|
guideLines: [20, 80],
|
|
1874
1910
|
axisTicks: [0, 20, 50, 80, 100],
|
|
1875
1911
|
decimals: 2,
|
|
1876
|
-
valueLines: inputs.showValueLine
|
|
1912
|
+
valueLines: inputs.showValueLine !== false
|
|
1877
1913
|
}
|
|
1878
1914
|
);
|
|
1879
1915
|
}
|
|
@@ -1889,7 +1925,7 @@ var BUILTIN_ADX_INDICATOR = {
|
|
|
1889
1925
|
plusDiColor: "#26a69a",
|
|
1890
1926
|
minusDiColor: "#ef5350",
|
|
1891
1927
|
showDi: true,
|
|
1892
|
-
showValueLine:
|
|
1928
|
+
showValueLine: true
|
|
1893
1929
|
},
|
|
1894
1930
|
draw: (ctx, renderContext, inputs) => {
|
|
1895
1931
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
@@ -1912,7 +1948,7 @@ var BUILTIN_ADX_INDICATOR = {
|
|
|
1912
1948
|
minOverride: 0,
|
|
1913
1949
|
guideLines: [20],
|
|
1914
1950
|
decimals: 2,
|
|
1915
|
-
valueLines: inputs.showValueLine
|
|
1951
|
+
valueLines: inputs.showValueLine !== false
|
|
1916
1952
|
});
|
|
1917
1953
|
}
|
|
1918
1954
|
};
|
|
@@ -1921,14 +1957,14 @@ var BUILTIN_OBV_INDICATOR = {
|
|
|
1921
1957
|
name: "OBV",
|
|
1922
1958
|
pane: "separate",
|
|
1923
1959
|
paneHeightRatio: 0.16,
|
|
1924
|
-
defaultInputs: { color: "#2962ff", width: 2, showValueLine:
|
|
1960
|
+
defaultInputs: { color: "#2962ff", width: 2, showValueLine: true },
|
|
1925
1961
|
draw: (ctx, renderContext, inputs) => {
|
|
1926
1962
|
const values = withCachedSeries("obv", renderContext.data, () => computeObvSeries(renderContext.data));
|
|
1927
1963
|
return drawSeparateMultiSeries(
|
|
1928
1964
|
ctx,
|
|
1929
1965
|
renderContext,
|
|
1930
1966
|
[{ values, color: inputs.color ?? "#2962ff", width: Number(inputs.width) || 2, label: "OBV" }],
|
|
1931
|
-
{ title: "OBV", format: formatCompactNumber, valueLines: inputs.showValueLine
|
|
1967
|
+
{ title: "OBV", format: formatCompactNumber, valueLines: inputs.showValueLine !== false }
|
|
1932
1968
|
);
|
|
1933
1969
|
}
|
|
1934
1970
|
};
|
|
@@ -1937,7 +1973,7 @@ var BUILTIN_MFI_INDICATOR = {
|
|
|
1937
1973
|
name: "MFI",
|
|
1938
1974
|
pane: "separate",
|
|
1939
1975
|
paneHeightRatio: 0.16,
|
|
1940
|
-
defaultInputs: { length: 14, color: "#7e57c2", width: 2, showValueLine:
|
|
1976
|
+
defaultInputs: { length: 14, color: "#7e57c2", width: 2, showValueLine: true },
|
|
1941
1977
|
draw: (ctx, renderContext, inputs) => {
|
|
1942
1978
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
1943
1979
|
const values = withCachedSeries(
|
|
@@ -1956,7 +1992,7 @@ var BUILTIN_MFI_INDICATOR = {
|
|
|
1956
1992
|
guideLines: [20, 80],
|
|
1957
1993
|
axisTicks: [0, 20, 50, 80, 100],
|
|
1958
1994
|
decimals: 2,
|
|
1959
|
-
valueLines: inputs.showValueLine
|
|
1995
|
+
valueLines: inputs.showValueLine !== false
|
|
1960
1996
|
}
|
|
1961
1997
|
);
|
|
1962
1998
|
}
|
|
@@ -1966,7 +2002,7 @@ var BUILTIN_CCI_INDICATOR = {
|
|
|
1966
2002
|
name: "CCI",
|
|
1967
2003
|
pane: "separate",
|
|
1968
2004
|
paneHeightRatio: 0.16,
|
|
1969
|
-
defaultInputs: { length: 20, color: "#2962ff", width: 2, showValueLine:
|
|
2005
|
+
defaultInputs: { length: 20, color: "#2962ff", width: 2, showValueLine: true },
|
|
1970
2006
|
draw: (ctx, renderContext, inputs) => {
|
|
1971
2007
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
1972
2008
|
const values = withCachedSeries(
|
|
@@ -1978,7 +2014,7 @@ var BUILTIN_CCI_INDICATOR = {
|
|
|
1978
2014
|
ctx,
|
|
1979
2015
|
renderContext,
|
|
1980
2016
|
[{ values, color: inputs.color ?? "#2962ff", width: Number(inputs.width) || 2 }],
|
|
1981
|
-
{ title: `CCI ${length}`, guideLines: [-100, 0, 100], decimals: 2, valueLines: inputs.showValueLine
|
|
2017
|
+
{ title: `CCI ${length}`, guideLines: [-100, 0, 100], decimals: 2, valueLines: inputs.showValueLine !== false }
|
|
1982
2018
|
);
|
|
1983
2019
|
}
|
|
1984
2020
|
};
|
|
@@ -1987,7 +2023,7 @@ var BUILTIN_WILLIAMSR_INDICATOR = {
|
|
|
1987
2023
|
name: "Williams %R",
|
|
1988
2024
|
pane: "separate",
|
|
1989
2025
|
paneHeightRatio: 0.16,
|
|
1990
|
-
defaultInputs: { length: 14, color: "#7e57c2", width: 2, showValueLine:
|
|
2026
|
+
defaultInputs: { length: 14, color: "#7e57c2", width: 2, showValueLine: true },
|
|
1991
2027
|
draw: (ctx, renderContext, inputs) => {
|
|
1992
2028
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
1993
2029
|
const values = withCachedSeries(
|
|
@@ -2006,7 +2042,7 @@ var BUILTIN_WILLIAMSR_INDICATOR = {
|
|
|
2006
2042
|
guideLines: [-80, -20],
|
|
2007
2043
|
axisTicks: [-100, -80, -50, -20, 0],
|
|
2008
2044
|
decimals: 2,
|
|
2009
|
-
valueLines: inputs.showValueLine
|
|
2045
|
+
valueLines: inputs.showValueLine !== false
|
|
2010
2046
|
}
|
|
2011
2047
|
);
|
|
2012
2048
|
}
|
|
@@ -2016,7 +2052,7 @@ var BUILTIN_ROC_INDICATOR = {
|
|
|
2016
2052
|
name: "ROC",
|
|
2017
2053
|
pane: "separate",
|
|
2018
2054
|
paneHeightRatio: 0.16,
|
|
2019
|
-
defaultInputs: { length: 9, color: "#2962ff", width: 2, showValueLine:
|
|
2055
|
+
defaultInputs: { length: 9, color: "#2962ff", width: 2, showValueLine: true },
|
|
2020
2056
|
draw: (ctx, renderContext, inputs) => {
|
|
2021
2057
|
const length = clampIndicatorLength(inputs.length, 9);
|
|
2022
2058
|
const values = withCachedSeries(
|
|
@@ -2028,7 +2064,7 @@ var BUILTIN_ROC_INDICATOR = {
|
|
|
2028
2064
|
ctx,
|
|
2029
2065
|
renderContext,
|
|
2030
2066
|
[{ values, color: inputs.color ?? "#2962ff", width: Number(inputs.width) || 2 }],
|
|
2031
|
-
{ title: `ROC ${length}`, includeZero: true, guideLines: [0], decimals: 2, valueLines: inputs.showValueLine
|
|
2067
|
+
{ title: `ROC ${length}`, includeZero: true, guideLines: [0], decimals: 2, valueLines: inputs.showValueLine !== false }
|
|
2032
2068
|
);
|
|
2033
2069
|
}
|
|
2034
2070
|
};
|
|
@@ -2037,7 +2073,7 @@ var BUILTIN_MOMENTUM_INDICATOR = {
|
|
|
2037
2073
|
name: "Momentum",
|
|
2038
2074
|
pane: "separate",
|
|
2039
2075
|
paneHeightRatio: 0.16,
|
|
2040
|
-
defaultInputs: { length: 10, color: "#2962ff", width: 2, showValueLine:
|
|
2076
|
+
defaultInputs: { length: 10, color: "#2962ff", width: 2, showValueLine: true },
|
|
2041
2077
|
draw: (ctx, renderContext, inputs) => {
|
|
2042
2078
|
const length = clampIndicatorLength(inputs.length, 10);
|
|
2043
2079
|
const values = withCachedSeries(
|
|
@@ -2049,7 +2085,7 @@ var BUILTIN_MOMENTUM_INDICATOR = {
|
|
|
2049
2085
|
ctx,
|
|
2050
2086
|
renderContext,
|
|
2051
2087
|
[{ values, color: inputs.color ?? "#2962ff", width: Number(inputs.width) || 2 }],
|
|
2052
|
-
{ title: `Mom ${length}`, includeZero: true, guideLines: [0], decimals: 2, valueLines: inputs.showValueLine
|
|
2088
|
+
{ title: `Mom ${length}`, includeZero: true, guideLines: [0], decimals: 2, valueLines: inputs.showValueLine !== false }
|
|
2053
2089
|
);
|
|
2054
2090
|
}
|
|
2055
2091
|
};
|
|
@@ -2473,6 +2509,14 @@ function createChart(element, options = {}) {
|
|
|
2473
2509
|
let watermarkImageReady = false;
|
|
2474
2510
|
let drawState = null;
|
|
2475
2511
|
let plotBottomForHit = 0;
|
|
2512
|
+
let paneLayoutFullChartHeight = 0;
|
|
2513
|
+
let paneLayoutInfos = [];
|
|
2514
|
+
let paneButtonRegions = [];
|
|
2515
|
+
let hoveredPaneId = null;
|
|
2516
|
+
let hoveredPaneButton = null;
|
|
2517
|
+
let paneDividerDrag = null;
|
|
2518
|
+
let indicatorPaneActionHandler = null;
|
|
2519
|
+
let indicatorPaneHeightChangeHandler = null;
|
|
2476
2520
|
let orderDragState = null;
|
|
2477
2521
|
let actionDragState = null;
|
|
2478
2522
|
let pointerDownInfo = null;
|
|
@@ -3574,20 +3618,24 @@ function createChart(element, options = {}) {
|
|
|
3574
3618
|
const watermark = { ...DEFAULT_WATERMARK_OPTIONS, ...mergedOptions.watermark ?? {} };
|
|
3575
3619
|
const paneGap = 0;
|
|
3576
3620
|
const separatePaneSpacing = 6;
|
|
3577
|
-
const
|
|
3621
|
+
const collapsedPaneHeight = 26;
|
|
3622
|
+
const activeSeparateIndicators = indicators.map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
3578
3623
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "separate"
|
|
3579
3624
|
).sort((a, b) => a.indicator.zIndex - b.indicator.zIndex);
|
|
3580
3625
|
const overlayIndicatorsForScale = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
3581
3626
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
3582
3627
|
);
|
|
3583
3628
|
const separatePaneHeightDefaults = activeSeparateIndicators.map(({ indicator, plugin }) => {
|
|
3629
|
+
if (!indicator.visible) return collapsedPaneHeight;
|
|
3584
3630
|
const ratio = Math.min(0.45, Math.max(0.08, indicator.paneHeightRatio ?? plugin.paneHeightRatio ?? 0.22));
|
|
3585
3631
|
return Math.round(fullChartHeight * ratio);
|
|
3586
3632
|
});
|
|
3587
3633
|
const separatePaneDesiredTotal = separatePaneHeightDefaults.reduce((sum, value) => sum + value, 0) + Math.max(0, activeSeparateIndicators.length - 1) * separatePaneSpacing;
|
|
3588
3634
|
const maxSeparatePaneTotal = Math.max(0, fullChartHeight - 140);
|
|
3589
3635
|
const separatePaneScale = separatePaneDesiredTotal > 0 && separatePaneDesiredTotal > maxSeparatePaneTotal ? maxSeparatePaneTotal / separatePaneDesiredTotal : 1;
|
|
3590
|
-
const separatePaneHeights = separatePaneHeightDefaults.map(
|
|
3636
|
+
const separatePaneHeights = separatePaneHeightDefaults.map(
|
|
3637
|
+
(value, index) => activeSeparateIndicators[index].indicator.visible ? Math.max(48, Math.round(value * separatePaneScale)) : collapsedPaneHeight
|
|
3638
|
+
);
|
|
3591
3639
|
const separatePaneTotal = separatePaneHeights.reduce((sum, value) => sum + value, 0) + Math.max(0, activeSeparateIndicators.length - 1) * separatePaneSpacing;
|
|
3592
3640
|
const pricePaneGap = activeSeparateIndicators.length > 0 ? paneGap : 0;
|
|
3593
3641
|
const chartHeight = Math.max(120, fullChartHeight - separatePaneTotal - pricePaneGap);
|
|
@@ -4838,43 +4886,138 @@ function createChart(element, options = {}) {
|
|
|
4838
4886
|
ctx.restore();
|
|
4839
4887
|
}
|
|
4840
4888
|
}
|
|
4889
|
+
paneLayoutFullChartHeight = fullChartHeight;
|
|
4890
|
+
paneLayoutInfos = [];
|
|
4891
|
+
paneButtonRegions = [];
|
|
4841
4892
|
if (activeSeparateIndicators.length > 0) {
|
|
4842
4893
|
const xFromIndex = (index) => chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
4843
4894
|
let paneTopCursor = chartBottom + paneGap;
|
|
4895
|
+
const paneButtonSize = 16;
|
|
4896
|
+
const paneButtonGap = 4;
|
|
4897
|
+
const drawPaneButtons = (indicatorId, indicatorType, indicatorVisible, startX, centerY) => {
|
|
4898
|
+
const actionList = [
|
|
4899
|
+
"visibility",
|
|
4900
|
+
"settings",
|
|
4901
|
+
"source",
|
|
4902
|
+
"remove"
|
|
4903
|
+
];
|
|
4904
|
+
let buttonX = startX;
|
|
4905
|
+
for (const action of actionList) {
|
|
4906
|
+
const buttonY = centerY - paneButtonSize / 2;
|
|
4907
|
+
const hovered = hoveredPaneButton?.id === indicatorId && hoveredPaneButton.action === action;
|
|
4908
|
+
const iconColor = labels.indicatorTextColor;
|
|
4909
|
+
ctx.save();
|
|
4910
|
+
ctx.fillStyle = hovered ? "rgba(148,163,184,0.30)" : "rgba(148,163,184,0.12)";
|
|
4911
|
+
fillRoundedRect(Math.round(buttonX), Math.round(buttonY), paneButtonSize, paneButtonSize, 4);
|
|
4912
|
+
ctx.strokeStyle = iconColor;
|
|
4913
|
+
ctx.fillStyle = iconColor;
|
|
4914
|
+
ctx.globalAlpha = hovered ? 1 : 0.75;
|
|
4915
|
+
ctx.lineWidth = 1.2;
|
|
4916
|
+
ctx.setLineDash([]);
|
|
4917
|
+
const cx = buttonX + paneButtonSize / 2;
|
|
4918
|
+
const cy = centerY;
|
|
4919
|
+
if (action === "visibility") {
|
|
4920
|
+
ctx.beginPath();
|
|
4921
|
+
ctx.ellipse(cx, cy, 4.6, 3, 0, 0, Math.PI * 2);
|
|
4922
|
+
ctx.stroke();
|
|
4923
|
+
ctx.beginPath();
|
|
4924
|
+
ctx.arc(cx, cy, 1.3, 0, Math.PI * 2);
|
|
4925
|
+
ctx.fill();
|
|
4926
|
+
if (!indicatorVisible) {
|
|
4927
|
+
ctx.beginPath();
|
|
4928
|
+
ctx.moveTo(cx - 5.2, cy + 4.6);
|
|
4929
|
+
ctx.lineTo(cx + 5.2, cy - 4.6);
|
|
4930
|
+
ctx.stroke();
|
|
4931
|
+
}
|
|
4932
|
+
} else if (action === "settings") {
|
|
4933
|
+
ctx.beginPath();
|
|
4934
|
+
ctx.arc(cx, cy, 3.4, 0, Math.PI * 2);
|
|
4935
|
+
ctx.stroke();
|
|
4936
|
+
for (let toothIndex = 0; toothIndex < 8; toothIndex += 1) {
|
|
4937
|
+
const angle = Math.PI / 4 * toothIndex;
|
|
4938
|
+
ctx.beginPath();
|
|
4939
|
+
ctx.moveTo(cx + Math.cos(angle) * 3.4, cy + Math.sin(angle) * 3.4);
|
|
4940
|
+
ctx.lineTo(cx + Math.cos(angle) * 5.2, cy + Math.sin(angle) * 5.2);
|
|
4941
|
+
ctx.stroke();
|
|
4942
|
+
}
|
|
4943
|
+
ctx.beginPath();
|
|
4944
|
+
ctx.arc(cx, cy, 1.1, 0, Math.PI * 2);
|
|
4945
|
+
ctx.fill();
|
|
4946
|
+
} else if (action === "source") {
|
|
4947
|
+
const prevSourceFont = ctx.font;
|
|
4948
|
+
ctx.font = `bold 9px ${mergedOptions.fontFamily}`;
|
|
4949
|
+
drawText("{}", cx, cy + 0.5, "center", "middle", iconColor);
|
|
4950
|
+
ctx.font = prevSourceFont;
|
|
4951
|
+
} else {
|
|
4952
|
+
ctx.beginPath();
|
|
4953
|
+
ctx.moveTo(cx - 3.4, cy - 3.4);
|
|
4954
|
+
ctx.lineTo(cx + 3.4, cy + 3.4);
|
|
4955
|
+
ctx.moveTo(cx + 3.4, cy - 3.4);
|
|
4956
|
+
ctx.lineTo(cx - 3.4, cy + 3.4);
|
|
4957
|
+
ctx.stroke();
|
|
4958
|
+
}
|
|
4959
|
+
ctx.restore();
|
|
4960
|
+
paneButtonRegions.push({
|
|
4961
|
+
id: indicatorId,
|
|
4962
|
+
type: indicatorType,
|
|
4963
|
+
action,
|
|
4964
|
+
x: buttonX,
|
|
4965
|
+
y: buttonY,
|
|
4966
|
+
width: paneButtonSize,
|
|
4967
|
+
height: paneButtonSize
|
|
4968
|
+
});
|
|
4969
|
+
buttonX += paneButtonSize + paneButtonGap;
|
|
4970
|
+
}
|
|
4971
|
+
};
|
|
4844
4972
|
activeSeparateIndicators.forEach(({ indicator, plugin }, paneIndex) => {
|
|
4845
4973
|
const paneHeight = separatePaneHeights[paneIndex] ?? 80;
|
|
4846
4974
|
const paneTop = paneTopCursor;
|
|
4847
4975
|
const paneBottom = paneTop + paneHeight;
|
|
4848
4976
|
paneTopCursor = paneBottom + separatePaneSpacing;
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4977
|
+
paneLayoutInfos.push({
|
|
4978
|
+
id: indicator.id,
|
|
4979
|
+
type: indicator.type,
|
|
4980
|
+
top: paneTop,
|
|
4981
|
+
bottom: paneBottom,
|
|
4982
|
+
visible: indicator.visible
|
|
4983
|
+
});
|
|
4984
|
+
let paneInfo;
|
|
4985
|
+
if (indicator.visible) {
|
|
4986
|
+
ctx.save();
|
|
4987
|
+
ctx.beginPath();
|
|
4988
|
+
ctx.rect(chartLeft + 1, paneTop + 1, Math.max(0, chartWidth - 2), Math.max(0, paneHeight - 2));
|
|
4989
|
+
ctx.clip();
|
|
4990
|
+
paneInfo = plugin.draw(
|
|
4991
|
+
ctx,
|
|
4992
|
+
{
|
|
4993
|
+
data,
|
|
4994
|
+
startIndex,
|
|
4995
|
+
endIndex,
|
|
4996
|
+
xStart,
|
|
4997
|
+
xSpan,
|
|
4998
|
+
chartLeft,
|
|
4999
|
+
chartRight,
|
|
5000
|
+
chartTop: paneTop,
|
|
5001
|
+
chartBottom: paneBottom,
|
|
5002
|
+
chartWidth,
|
|
5003
|
+
chartHeight: paneHeight,
|
|
5004
|
+
xFromIndex,
|
|
5005
|
+
yFromPrice: null,
|
|
5006
|
+
getCandleDirectionByIndex,
|
|
5007
|
+
getVolumeByIndex,
|
|
5008
|
+
candleSpacing,
|
|
5009
|
+
upColor: mergedOptions.upColor,
|
|
5010
|
+
downColor: mergedOptions.downColor,
|
|
5011
|
+
grid: {
|
|
5012
|
+
color: gridColor,
|
|
5013
|
+
opacity: gridOpacity,
|
|
5014
|
+
horizontalLines: grid.horizontalLines !== false
|
|
5015
|
+
}
|
|
5016
|
+
},
|
|
5017
|
+
indicator.inputs
|
|
5018
|
+
) ?? void 0;
|
|
5019
|
+
ctx.restore();
|
|
5020
|
+
}
|
|
4878
5021
|
ctx.save();
|
|
4879
5022
|
ctx.strokeStyle = axis.lineColor;
|
|
4880
5023
|
ctx.lineWidth = Math.max(1, axis.lineWidth);
|
|
@@ -4883,6 +5026,27 @@ function createChart(element, options = {}) {
|
|
|
4883
5026
|
ctx.lineTo(crisp(chartRight), crisp(paneTop));
|
|
4884
5027
|
ctx.stroke();
|
|
4885
5028
|
ctx.restore();
|
|
5029
|
+
if (!indicator.visible) {
|
|
5030
|
+
if (labels.visible) {
|
|
5031
|
+
const prevFont = ctx.font;
|
|
5032
|
+
ctx.font = `${Math.max(8, axis.fontSize)}px ${mergedOptions.fontFamily}`;
|
|
5033
|
+
const hiddenText = `${plugin.name} (hidden)`;
|
|
5034
|
+
const rowCenterY = (paneTop + paneBottom) / 2;
|
|
5035
|
+
ctx.save();
|
|
5036
|
+
ctx.globalAlpha = 0.55;
|
|
5037
|
+
drawText(hiddenText, chartLeft + 10, rowCenterY, "left", "middle", labels.indicatorTextColor);
|
|
5038
|
+
ctx.restore();
|
|
5039
|
+
drawPaneButtons(
|
|
5040
|
+
indicator.id,
|
|
5041
|
+
indicator.type,
|
|
5042
|
+
false,
|
|
5043
|
+
chartLeft + 10 + Math.ceil(measureTextWidth(hiddenText)) + 10,
|
|
5044
|
+
rowCenterY
|
|
5045
|
+
);
|
|
5046
|
+
ctx.font = prevFont;
|
|
5047
|
+
}
|
|
5048
|
+
return;
|
|
5049
|
+
}
|
|
4886
5050
|
const axisInfo = paneInfo?.axis;
|
|
4887
5051
|
if (axisInfo && Number.isFinite(axisInfo.min) && Number.isFinite(axisInfo.max) && axisInfo.max !== axisInfo.min) {
|
|
4888
5052
|
const paneRange = axisInfo.max - axisInfo.min;
|
|
@@ -4912,17 +5076,28 @@ function createChart(element, options = {}) {
|
|
|
4912
5076
|
ctx.restore();
|
|
4913
5077
|
if (labels.visible) {
|
|
4914
5078
|
const prevFont = ctx.font;
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
const
|
|
5079
|
+
const legendFontSize = Math.max(8, axis.fontSize);
|
|
5080
|
+
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
5081
|
+
const legendTitle = paneInfo?.title ?? plugin.name;
|
|
5082
|
+
const legendValues = paneInfo?.legendValues ?? [];
|
|
4918
5083
|
const legendParts = [
|
|
4919
5084
|
legendTitle,
|
|
4920
5085
|
...legendValues.map((value) => value.text ?? (value.value === void 0 ? "" : formatPaneValue(value.value))).filter(Boolean)
|
|
4921
5086
|
].filter(Boolean);
|
|
5087
|
+
const legendText = legendParts.join(" ");
|
|
4922
5088
|
if (legendParts.length > 0) {
|
|
4923
|
-
drawText(
|
|
5089
|
+
drawText(legendText, chartLeft + 10, paneTop + 8, "left", "top", labels.indicatorTextColor);
|
|
4924
5090
|
}
|
|
4925
|
-
|
|
5091
|
+
if (hoveredPaneId === indicator.id) {
|
|
5092
|
+
drawPaneButtons(
|
|
5093
|
+
indicator.id,
|
|
5094
|
+
indicator.type,
|
|
5095
|
+
true,
|
|
5096
|
+
chartLeft + 10 + Math.ceil(measureTextWidth(legendText)) + 10,
|
|
5097
|
+
paneTop + 8 + legendFontSize / 2
|
|
5098
|
+
);
|
|
5099
|
+
}
|
|
5100
|
+
for (const label of paneInfo?.valueLabels ?? []) {
|
|
4926
5101
|
if (!labels.showIndicatorValueLabels) {
|
|
4927
5102
|
continue;
|
|
4928
5103
|
}
|
|
@@ -6134,6 +6309,54 @@ function createChart(element, options = {}) {
|
|
|
6134
6309
|
}
|
|
6135
6310
|
return "outside";
|
|
6136
6311
|
};
|
|
6312
|
+
const getPaneButtonHit = (x, y) => {
|
|
6313
|
+
for (const region of paneButtonRegions) {
|
|
6314
|
+
if (x >= region.x && x <= region.x + region.width && y >= region.y && y <= region.y + region.height) {
|
|
6315
|
+
return { id: region.id, type: region.type, action: region.action };
|
|
6316
|
+
}
|
|
6317
|
+
}
|
|
6318
|
+
return null;
|
|
6319
|
+
};
|
|
6320
|
+
const getPaneAt = (x, y) => {
|
|
6321
|
+
if (!drawState || x < drawState.chartLeft || x > drawState.chartRight) {
|
|
6322
|
+
return null;
|
|
6323
|
+
}
|
|
6324
|
+
for (const pane of paneLayoutInfos) {
|
|
6325
|
+
if (y >= pane.top && y <= pane.bottom) {
|
|
6326
|
+
return pane;
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
6329
|
+
return null;
|
|
6330
|
+
};
|
|
6331
|
+
const getPaneDividerHit = (x, y) => {
|
|
6332
|
+
if (!drawState || x < drawState.chartLeft || x > drawState.chartRight) {
|
|
6333
|
+
return null;
|
|
6334
|
+
}
|
|
6335
|
+
for (const pane of paneLayoutInfos) {
|
|
6336
|
+
if (pane.visible && Math.abs(y - pane.top) <= 4) {
|
|
6337
|
+
return { id: pane.id, heightPx: pane.bottom - pane.top };
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6340
|
+
return null;
|
|
6341
|
+
};
|
|
6342
|
+
const handlePaneButtonAction = (hit) => {
|
|
6343
|
+
const indicator = indicators.find((entry) => entry.id === hit.id);
|
|
6344
|
+
if (!indicator) {
|
|
6345
|
+
return;
|
|
6346
|
+
}
|
|
6347
|
+
if (hit.action === "visibility") {
|
|
6348
|
+
indicator.visible = !indicator.visible;
|
|
6349
|
+
scheduleDraw();
|
|
6350
|
+
indicatorPaneActionHandler?.({ id: hit.id, type: hit.type, action: "visibility", visible: indicator.visible });
|
|
6351
|
+
return;
|
|
6352
|
+
}
|
|
6353
|
+
if (hit.action === "remove" && !indicatorPaneActionHandler) {
|
|
6354
|
+
indicators = indicators.filter((entry) => entry.id !== hit.id);
|
|
6355
|
+
scheduleDraw();
|
|
6356
|
+
return;
|
|
6357
|
+
}
|
|
6358
|
+
indicatorPaneActionHandler?.({ id: hit.id, type: hit.type, action: hit.action });
|
|
6359
|
+
};
|
|
6137
6360
|
const handleDrawingToolPointerDown = (x, y) => {
|
|
6138
6361
|
if (!activeDrawingTool || !drawState) {
|
|
6139
6362
|
return false;
|
|
@@ -6613,6 +6836,26 @@ function createChart(element, options = {}) {
|
|
|
6613
6836
|
setCrosshairPoint(null);
|
|
6614
6837
|
return;
|
|
6615
6838
|
}
|
|
6839
|
+
const paneButtonHit = getPaneButtonHit(point.x, point.y);
|
|
6840
|
+
if (paneButtonHit) {
|
|
6841
|
+
setCrosshairPoint(null);
|
|
6842
|
+
handlePaneButtonAction(paneButtonHit);
|
|
6843
|
+
return;
|
|
6844
|
+
}
|
|
6845
|
+
const paneDividerHit = getPaneDividerHit(point.x, point.y);
|
|
6846
|
+
if (paneDividerHit) {
|
|
6847
|
+
activePointerId = event.pointerId;
|
|
6848
|
+
paneDividerDrag = {
|
|
6849
|
+
id: paneDividerHit.id,
|
|
6850
|
+
startY: point.y,
|
|
6851
|
+
startHeightPx: paneDividerHit.heightPx,
|
|
6852
|
+
lastRatio: paneLayoutFullChartHeight > 0 ? paneDividerHit.heightPx / paneLayoutFullChartHeight : 0.2
|
|
6853
|
+
};
|
|
6854
|
+
capturePointer(event.pointerId);
|
|
6855
|
+
canvas.style.cursor = "row-resize";
|
|
6856
|
+
setCrosshairPoint(null);
|
|
6857
|
+
return;
|
|
6858
|
+
}
|
|
6616
6859
|
}
|
|
6617
6860
|
const region = getHitRegion(point.x, point.y);
|
|
6618
6861
|
if (region === "outside") {
|
|
@@ -6737,6 +6980,32 @@ function createChart(element, options = {}) {
|
|
|
6737
6980
|
return;
|
|
6738
6981
|
}
|
|
6739
6982
|
}
|
|
6983
|
+
if (paneDividerDrag) {
|
|
6984
|
+
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
6985
|
+
return;
|
|
6986
|
+
}
|
|
6987
|
+
const fullHeight = paneLayoutFullChartHeight;
|
|
6988
|
+
if (fullHeight > 0) {
|
|
6989
|
+
const nextHeightPx = clamp(
|
|
6990
|
+
paneDividerDrag.startHeightPx + (paneDividerDrag.startY - point.y),
|
|
6991
|
+
48,
|
|
6992
|
+
Math.round(fullHeight * 0.45)
|
|
6993
|
+
);
|
|
6994
|
+
const nextRatio = nextHeightPx / fullHeight;
|
|
6995
|
+
if (Math.abs(nextRatio - paneDividerDrag.lastRatio) > 5e-4) {
|
|
6996
|
+
paneDividerDrag.lastRatio = nextRatio;
|
|
6997
|
+
const targetIndicator = indicators.find((entry) => entry.id === paneDividerDrag?.id);
|
|
6998
|
+
if (targetIndicator) {
|
|
6999
|
+
targetIndicator.paneHeightRatio = nextRatio;
|
|
7000
|
+
indicatorPaneHeightChangeHandler?.({ id: paneDividerDrag.id, paneHeightRatio: nextRatio, dragging: true });
|
|
7001
|
+
scheduleDraw();
|
|
7002
|
+
}
|
|
7003
|
+
}
|
|
7004
|
+
}
|
|
7005
|
+
canvas.style.cursor = "row-resize";
|
|
7006
|
+
setCrosshairPoint(null);
|
|
7007
|
+
return;
|
|
7008
|
+
}
|
|
6740
7009
|
if (orderDragState) {
|
|
6741
7010
|
if (activePointerId !== null && event.pointerId !== activePointerId) {
|
|
6742
7011
|
return;
|
|
@@ -6809,6 +7078,33 @@ function createChart(element, options = {}) {
|
|
|
6809
7078
|
setCrosshairPoint(null);
|
|
6810
7079
|
return;
|
|
6811
7080
|
}
|
|
7081
|
+
const hoveredPane = getPaneAt(point.x, point.y);
|
|
7082
|
+
const nextHoveredPaneId = hoveredPane?.id ?? null;
|
|
7083
|
+
if (nextHoveredPaneId !== hoveredPaneId) {
|
|
7084
|
+
hoveredPaneId = nextHoveredPaneId;
|
|
7085
|
+
scheduleDraw();
|
|
7086
|
+
}
|
|
7087
|
+
const paneButtonHover = getPaneButtonHit(point.x, point.y);
|
|
7088
|
+
const nextHoveredButton = paneButtonHover ? { id: paneButtonHover.id, action: paneButtonHover.action } : null;
|
|
7089
|
+
if ((nextHoveredButton?.id ?? null) !== (hoveredPaneButton?.id ?? null) || nextHoveredButton?.action !== hoveredPaneButton?.action) {
|
|
7090
|
+
hoveredPaneButton = nextHoveredButton;
|
|
7091
|
+
scheduleDraw();
|
|
7092
|
+
}
|
|
7093
|
+
if (paneButtonHover) {
|
|
7094
|
+
const indicatorForTitle = indicators.find((entry) => entry.id === paneButtonHover.id);
|
|
7095
|
+
canvas.title = paneButtonHover.action === "visibility" ? indicatorForTitle?.visible === false ? "Show" : "Hide" : paneButtonHover.action === "settings" ? "Settings" : paneButtonHover.action === "source" ? "View source" : "Remove";
|
|
7096
|
+
canvas.style.cursor = "pointer";
|
|
7097
|
+
setCrosshairPoint(null);
|
|
7098
|
+
return;
|
|
7099
|
+
}
|
|
7100
|
+
if (canvas.title) {
|
|
7101
|
+
canvas.title = "";
|
|
7102
|
+
}
|
|
7103
|
+
if (getPaneDividerHit(point.x, point.y)) {
|
|
7104
|
+
canvas.style.cursor = "row-resize";
|
|
7105
|
+
setCrosshairPoint(null);
|
|
7106
|
+
return;
|
|
7107
|
+
}
|
|
6812
7108
|
}
|
|
6813
7109
|
if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
|
|
6814
7110
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
@@ -6928,6 +7224,22 @@ function createChart(element, options = {}) {
|
|
|
6928
7224
|
drawingDragState = null;
|
|
6929
7225
|
emitDrawingsChange();
|
|
6930
7226
|
}
|
|
7227
|
+
if (paneDividerDrag) {
|
|
7228
|
+
indicatorPaneHeightChangeHandler?.({
|
|
7229
|
+
id: paneDividerDrag.id,
|
|
7230
|
+
paneHeightRatio: paneDividerDrag.lastRatio,
|
|
7231
|
+
dragging: false
|
|
7232
|
+
});
|
|
7233
|
+
paneDividerDrag = null;
|
|
7234
|
+
}
|
|
7235
|
+
if (event?.type === "pointerleave" && (hoveredPaneId !== null || hoveredPaneButton !== null)) {
|
|
7236
|
+
hoveredPaneId = null;
|
|
7237
|
+
hoveredPaneButton = null;
|
|
7238
|
+
if (canvas.title) {
|
|
7239
|
+
canvas.title = "";
|
|
7240
|
+
}
|
|
7241
|
+
scheduleDraw();
|
|
7242
|
+
}
|
|
6931
7243
|
const endedPlotDrag = isDragging && dragMode === "plot";
|
|
6932
7244
|
isDragging = false;
|
|
6933
7245
|
dragMode = null;
|
|
@@ -7273,6 +7585,12 @@ function createChart(element, options = {}) {
|
|
|
7273
7585
|
const onCrosshairPriceAction = (handler) => {
|
|
7274
7586
|
crosshairPriceActionHandler = handler;
|
|
7275
7587
|
};
|
|
7588
|
+
const onIndicatorPaneAction = (handler) => {
|
|
7589
|
+
indicatorPaneActionHandler = handler;
|
|
7590
|
+
};
|
|
7591
|
+
const onIndicatorPaneHeightChange = (handler) => {
|
|
7592
|
+
indicatorPaneHeightChangeHandler = handler;
|
|
7593
|
+
};
|
|
7276
7594
|
const setDoubleClickEnabled = (enabled) => {
|
|
7277
7595
|
doubleClickEnabled = enabled;
|
|
7278
7596
|
};
|
|
@@ -7478,6 +7796,8 @@ function createChart(element, options = {}) {
|
|
|
7478
7796
|
onChartClick,
|
|
7479
7797
|
onCrosshairMove,
|
|
7480
7798
|
onCrosshairPriceAction,
|
|
7799
|
+
onIndicatorPaneAction,
|
|
7800
|
+
onIndicatorPaneHeightChange,
|
|
7481
7801
|
zoomInX,
|
|
7482
7802
|
zoomOutX,
|
|
7483
7803
|
zoomInY,
|