hyperprop-charting-library 0.1.62 → 0.1.63
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 +53 -8
- package/dist/hyperprop-charting-library.js +53 -8
- package/dist/index.cjs +53 -8
- package/dist/index.js +53 -8
- package/package.json +1 -1
|
@@ -1068,6 +1068,7 @@ function createChart(element, options = {}) {
|
|
|
1068
1068
|
element.innerHTML = "";
|
|
1069
1069
|
element.appendChild(canvas);
|
|
1070
1070
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
1071
|
+
let cachedRightMargin = margin.right;
|
|
1071
1072
|
const minVisibleBars = Math.max(1, Math.floor(mergedOptions.minVisibleBars));
|
|
1072
1073
|
const maxVisibleBars = Math.max(minVisibleBars, Math.floor(mergedOptions.maxVisibleBars));
|
|
1073
1074
|
const maxPanBars = Math.max(0, Math.floor(mergedOptions.maxPanBars));
|
|
@@ -1289,14 +1290,34 @@ function createChart(element, options = {}) {
|
|
|
1289
1290
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1290
1291
|
return `${integerPart}${decimalPart}`;
|
|
1291
1292
|
};
|
|
1293
|
+
const getMeasuredLabelWidth = (text, paddingX) => {
|
|
1294
|
+
return Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1295
|
+
};
|
|
1296
|
+
const getStabilizedNumericLabelWidth = (text, paddingX) => {
|
|
1297
|
+
const measured = getMeasuredLabelWidth(text, paddingX);
|
|
1298
|
+
if (!mergedOptions.stabilizePriceLabels || !/\d/.test(text)) {
|
|
1299
|
+
return measured;
|
|
1300
|
+
}
|
|
1301
|
+
let stableWidth = measured;
|
|
1302
|
+
for (const digit of ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
|
|
1303
|
+
stableWidth = Math.max(stableWidth, getMeasuredLabelWidth(text.replace(/\d/g, digit), paddingX));
|
|
1304
|
+
}
|
|
1305
|
+
return stableWidth;
|
|
1306
|
+
};
|
|
1292
1307
|
const getPriceLabelWidth = (priceText, paddingX) => {
|
|
1293
|
-
const measured =
|
|
1308
|
+
const measured = getStabilizedNumericLabelWidth(priceText, paddingX);
|
|
1294
1309
|
if (!mergedOptions.stabilizePriceLabels) {
|
|
1295
1310
|
return measured;
|
|
1296
1311
|
}
|
|
1297
|
-
const templateWidth =
|
|
1312
|
+
const templateWidth = getStabilizedNumericLabelWidth(getStabilizedPriceTemplate(), paddingX);
|
|
1298
1313
|
return Math.max(measured, templateWidth);
|
|
1299
1314
|
};
|
|
1315
|
+
const getStableLabelWidth = (text, paddingX) => {
|
|
1316
|
+
return getStabilizedNumericLabelWidth(text, paddingX);
|
|
1317
|
+
};
|
|
1318
|
+
const resetRightMarginCache = () => {
|
|
1319
|
+
cachedRightMargin = margin.right;
|
|
1320
|
+
};
|
|
1300
1321
|
const parseData = (nextData) => {
|
|
1301
1322
|
const dedupedByTime = /* @__PURE__ */ new Map();
|
|
1302
1323
|
for (const point of nextData) {
|
|
@@ -1822,22 +1843,33 @@ function createChart(element, options = {}) {
|
|
|
1822
1843
|
const labels = { ...DEFAULT_LABELS_OPTIONS, ...mergedOptions.labels ?? {} };
|
|
1823
1844
|
const estimateRightMargin = () => {
|
|
1824
1845
|
const paddingX = Math.max(4, labels.labelPaddingX);
|
|
1825
|
-
const measure = (text) => Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1826
1846
|
let required = margin.right - 1;
|
|
1847
|
+
const includeWidth = (contentWidth) => {
|
|
1848
|
+
if (Number.isFinite(contentWidth)) {
|
|
1849
|
+
required = Math.max(required, contentWidth);
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1827
1852
|
const include = (text) => {
|
|
1828
1853
|
const normalized = text?.trim();
|
|
1829
1854
|
if (normalized) {
|
|
1830
|
-
|
|
1855
|
+
includeWidth(getStableLabelWidth(normalized, paddingX));
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
const includePrice = (price) => {
|
|
1859
|
+
if (Number.isFinite(price)) {
|
|
1860
|
+
includeWidth(getPriceLabelWidth(formatPrice(price), paddingX));
|
|
1831
1861
|
}
|
|
1832
1862
|
};
|
|
1833
1863
|
const ticker2 = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1834
1864
|
const lastPoint2 = data[data.length - 1];
|
|
1835
1865
|
if ((ticker2.visible ?? true) && labels.showLastPrice && lastPoint2) {
|
|
1836
|
-
|
|
1866
|
+
const tickerPrice2 = ticker2.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint2.c;
|
|
1867
|
+
includePrice(tickerPrice2);
|
|
1837
1868
|
if (ticker2.labelSubtext) include(String(ticker2.labelSubtext));
|
|
1838
1869
|
for (const subtext of ticker2.labelSubtexts ?? []) {
|
|
1839
1870
|
include(String(subtext));
|
|
1840
1871
|
}
|
|
1872
|
+
if (ticker2.showCountdownInLabel) include("88:88");
|
|
1841
1873
|
}
|
|
1842
1874
|
if (labels.showSymbolName) {
|
|
1843
1875
|
include(labels.symbolName);
|
|
@@ -1859,18 +1891,24 @@ function createChart(element, options = {}) {
|
|
|
1859
1891
|
for (const line of priceLines) {
|
|
1860
1892
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1861
1893
|
if (mergedLine.visible && Number.isFinite(mergedLine.price)) {
|
|
1862
|
-
|
|
1894
|
+
if (mergedLine.label) {
|
|
1895
|
+
include(mergedLine.label);
|
|
1896
|
+
} else {
|
|
1897
|
+
includePrice(mergedLine.price);
|
|
1898
|
+
}
|
|
1863
1899
|
}
|
|
1864
1900
|
}
|
|
1865
1901
|
for (const line of orderLines) {
|
|
1866
1902
|
const mergedLine = { ...DEFAULT_ORDER_LINE_OPTIONS, ...line };
|
|
1867
1903
|
const renderPrice = mergedLine.behavior === "follow" && Number.isFinite(mergedLine.followPrice) ? mergedLine.followPrice : mergedLine.price;
|
|
1868
1904
|
if (mergedLine.visible && Number.isFinite(renderPrice)) {
|
|
1869
|
-
|
|
1905
|
+
includePrice(renderPrice);
|
|
1870
1906
|
}
|
|
1871
1907
|
}
|
|
1872
1908
|
const maxRightMargin = Math.max(margin.right, width - margin.left - 160);
|
|
1873
|
-
|
|
1909
|
+
const nextRightMargin = Math.min(maxRightMargin, Math.max(margin.right, Math.ceil(required + 1)));
|
|
1910
|
+
cachedRightMargin = Math.max(cachedRightMargin, nextRightMargin);
|
|
1911
|
+
return Math.min(maxRightMargin, cachedRightMargin);
|
|
1874
1912
|
};
|
|
1875
1913
|
const rightMargin = estimateRightMargin();
|
|
1876
1914
|
const chartLeft = margin.left;
|
|
@@ -3943,6 +3981,7 @@ function createChart(element, options = {}) {
|
|
|
3943
3981
|
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
3944
3982
|
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
3945
3983
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3984
|
+
resetRightMarginCache();
|
|
3946
3985
|
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
3947
3986
|
doubleClickAction = mergedOptions.doubleClickAction;
|
|
3948
3987
|
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
@@ -3969,6 +4008,7 @@ function createChart(element, options = {}) {
|
|
|
3969
4008
|
height = nextHeight;
|
|
3970
4009
|
}
|
|
3971
4010
|
mergedOptions = { ...mergedOptions, width, height };
|
|
4011
|
+
resetRightMarginCache();
|
|
3972
4012
|
draw();
|
|
3973
4013
|
};
|
|
3974
4014
|
const setData = (nextData) => {
|
|
@@ -3985,6 +4025,7 @@ function createChart(element, options = {}) {
|
|
|
3985
4025
|
tickerPriceTarget = null;
|
|
3986
4026
|
smoothedTickerVolume = null;
|
|
3987
4027
|
tickerVolumeTarget = null;
|
|
4028
|
+
resetRightMarginCache();
|
|
3988
4029
|
resetYViewport();
|
|
3989
4030
|
draw();
|
|
3990
4031
|
return;
|
|
@@ -4018,6 +4059,7 @@ function createChart(element, options = {}) {
|
|
|
4018
4059
|
...line,
|
|
4019
4060
|
id: line.id ?? `line-${index + 1}`
|
|
4020
4061
|
}));
|
|
4062
|
+
resetRightMarginCache();
|
|
4021
4063
|
draw();
|
|
4022
4064
|
};
|
|
4023
4065
|
const addPriceLine = (line) => {
|
|
@@ -4028,6 +4070,7 @@ function createChart(element, options = {}) {
|
|
|
4028
4070
|
};
|
|
4029
4071
|
const removePriceLine = (id) => {
|
|
4030
4072
|
priceLines = priceLines.filter((line) => line.id !== id);
|
|
4073
|
+
resetRightMarginCache();
|
|
4031
4074
|
draw();
|
|
4032
4075
|
};
|
|
4033
4076
|
const setOrderLines = (lines) => {
|
|
@@ -4035,6 +4078,7 @@ function createChart(element, options = {}) {
|
|
|
4035
4078
|
...line,
|
|
4036
4079
|
id: line.id ?? `order-${index + 1}`
|
|
4037
4080
|
}));
|
|
4081
|
+
resetRightMarginCache();
|
|
4038
4082
|
const activeIds = new Set(orderLines.map((line) => line.id));
|
|
4039
4083
|
for (const id of Array.from(orderWidgetWidthById.keys())) {
|
|
4040
4084
|
if (!activeIds.has(id)) {
|
|
@@ -4062,6 +4106,7 @@ function createChart(element, options = {}) {
|
|
|
4062
4106
|
orderLines = orderLines.filter((line) => line.id !== id);
|
|
4063
4107
|
orderWidgetWidthById.delete(id);
|
|
4064
4108
|
orderPriceTagWidthById.delete(id);
|
|
4109
|
+
resetRightMarginCache();
|
|
4065
4110
|
draw();
|
|
4066
4111
|
};
|
|
4067
4112
|
const onOrderAction = (handler) => {
|
|
@@ -1044,6 +1044,7 @@ function createChart(element, options = {}) {
|
|
|
1044
1044
|
element.innerHTML = "";
|
|
1045
1045
|
element.appendChild(canvas);
|
|
1046
1046
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
1047
|
+
let cachedRightMargin = margin.right;
|
|
1047
1048
|
const minVisibleBars = Math.max(1, Math.floor(mergedOptions.minVisibleBars));
|
|
1048
1049
|
const maxVisibleBars = Math.max(minVisibleBars, Math.floor(mergedOptions.maxVisibleBars));
|
|
1049
1050
|
const maxPanBars = Math.max(0, Math.floor(mergedOptions.maxPanBars));
|
|
@@ -1265,14 +1266,34 @@ function createChart(element, options = {}) {
|
|
|
1265
1266
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1266
1267
|
return `${integerPart}${decimalPart}`;
|
|
1267
1268
|
};
|
|
1269
|
+
const getMeasuredLabelWidth = (text, paddingX) => {
|
|
1270
|
+
return Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1271
|
+
};
|
|
1272
|
+
const getStabilizedNumericLabelWidth = (text, paddingX) => {
|
|
1273
|
+
const measured = getMeasuredLabelWidth(text, paddingX);
|
|
1274
|
+
if (!mergedOptions.stabilizePriceLabels || !/\d/.test(text)) {
|
|
1275
|
+
return measured;
|
|
1276
|
+
}
|
|
1277
|
+
let stableWidth = measured;
|
|
1278
|
+
for (const digit of ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
|
|
1279
|
+
stableWidth = Math.max(stableWidth, getMeasuredLabelWidth(text.replace(/\d/g, digit), paddingX));
|
|
1280
|
+
}
|
|
1281
|
+
return stableWidth;
|
|
1282
|
+
};
|
|
1268
1283
|
const getPriceLabelWidth = (priceText, paddingX) => {
|
|
1269
|
-
const measured =
|
|
1284
|
+
const measured = getStabilizedNumericLabelWidth(priceText, paddingX);
|
|
1270
1285
|
if (!mergedOptions.stabilizePriceLabels) {
|
|
1271
1286
|
return measured;
|
|
1272
1287
|
}
|
|
1273
|
-
const templateWidth =
|
|
1288
|
+
const templateWidth = getStabilizedNumericLabelWidth(getStabilizedPriceTemplate(), paddingX);
|
|
1274
1289
|
return Math.max(measured, templateWidth);
|
|
1275
1290
|
};
|
|
1291
|
+
const getStableLabelWidth = (text, paddingX) => {
|
|
1292
|
+
return getStabilizedNumericLabelWidth(text, paddingX);
|
|
1293
|
+
};
|
|
1294
|
+
const resetRightMarginCache = () => {
|
|
1295
|
+
cachedRightMargin = margin.right;
|
|
1296
|
+
};
|
|
1276
1297
|
const parseData = (nextData) => {
|
|
1277
1298
|
const dedupedByTime = /* @__PURE__ */ new Map();
|
|
1278
1299
|
for (const point of nextData) {
|
|
@@ -1798,22 +1819,33 @@ function createChart(element, options = {}) {
|
|
|
1798
1819
|
const labels = { ...DEFAULT_LABELS_OPTIONS, ...mergedOptions.labels ?? {} };
|
|
1799
1820
|
const estimateRightMargin = () => {
|
|
1800
1821
|
const paddingX = Math.max(4, labels.labelPaddingX);
|
|
1801
|
-
const measure = (text) => Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1802
1822
|
let required = margin.right - 1;
|
|
1823
|
+
const includeWidth = (contentWidth) => {
|
|
1824
|
+
if (Number.isFinite(contentWidth)) {
|
|
1825
|
+
required = Math.max(required, contentWidth);
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1803
1828
|
const include = (text) => {
|
|
1804
1829
|
const normalized = text?.trim();
|
|
1805
1830
|
if (normalized) {
|
|
1806
|
-
|
|
1831
|
+
includeWidth(getStableLabelWidth(normalized, paddingX));
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
const includePrice = (price) => {
|
|
1835
|
+
if (Number.isFinite(price)) {
|
|
1836
|
+
includeWidth(getPriceLabelWidth(formatPrice(price), paddingX));
|
|
1807
1837
|
}
|
|
1808
1838
|
};
|
|
1809
1839
|
const ticker2 = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1810
1840
|
const lastPoint2 = data[data.length - 1];
|
|
1811
1841
|
if ((ticker2.visible ?? true) && labels.showLastPrice && lastPoint2) {
|
|
1812
|
-
|
|
1842
|
+
const tickerPrice2 = ticker2.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint2.c;
|
|
1843
|
+
includePrice(tickerPrice2);
|
|
1813
1844
|
if (ticker2.labelSubtext) include(String(ticker2.labelSubtext));
|
|
1814
1845
|
for (const subtext of ticker2.labelSubtexts ?? []) {
|
|
1815
1846
|
include(String(subtext));
|
|
1816
1847
|
}
|
|
1848
|
+
if (ticker2.showCountdownInLabel) include("88:88");
|
|
1817
1849
|
}
|
|
1818
1850
|
if (labels.showSymbolName) {
|
|
1819
1851
|
include(labels.symbolName);
|
|
@@ -1835,18 +1867,24 @@ function createChart(element, options = {}) {
|
|
|
1835
1867
|
for (const line of priceLines) {
|
|
1836
1868
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1837
1869
|
if (mergedLine.visible && Number.isFinite(mergedLine.price)) {
|
|
1838
|
-
|
|
1870
|
+
if (mergedLine.label) {
|
|
1871
|
+
include(mergedLine.label);
|
|
1872
|
+
} else {
|
|
1873
|
+
includePrice(mergedLine.price);
|
|
1874
|
+
}
|
|
1839
1875
|
}
|
|
1840
1876
|
}
|
|
1841
1877
|
for (const line of orderLines) {
|
|
1842
1878
|
const mergedLine = { ...DEFAULT_ORDER_LINE_OPTIONS, ...line };
|
|
1843
1879
|
const renderPrice = mergedLine.behavior === "follow" && Number.isFinite(mergedLine.followPrice) ? mergedLine.followPrice : mergedLine.price;
|
|
1844
1880
|
if (mergedLine.visible && Number.isFinite(renderPrice)) {
|
|
1845
|
-
|
|
1881
|
+
includePrice(renderPrice);
|
|
1846
1882
|
}
|
|
1847
1883
|
}
|
|
1848
1884
|
const maxRightMargin = Math.max(margin.right, width - margin.left - 160);
|
|
1849
|
-
|
|
1885
|
+
const nextRightMargin = Math.min(maxRightMargin, Math.max(margin.right, Math.ceil(required + 1)));
|
|
1886
|
+
cachedRightMargin = Math.max(cachedRightMargin, nextRightMargin);
|
|
1887
|
+
return Math.min(maxRightMargin, cachedRightMargin);
|
|
1850
1888
|
};
|
|
1851
1889
|
const rightMargin = estimateRightMargin();
|
|
1852
1890
|
const chartLeft = margin.left;
|
|
@@ -3919,6 +3957,7 @@ function createChart(element, options = {}) {
|
|
|
3919
3957
|
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
3920
3958
|
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
3921
3959
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3960
|
+
resetRightMarginCache();
|
|
3922
3961
|
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
3923
3962
|
doubleClickAction = mergedOptions.doubleClickAction;
|
|
3924
3963
|
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
@@ -3945,6 +3984,7 @@ function createChart(element, options = {}) {
|
|
|
3945
3984
|
height = nextHeight;
|
|
3946
3985
|
}
|
|
3947
3986
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3987
|
+
resetRightMarginCache();
|
|
3948
3988
|
draw();
|
|
3949
3989
|
};
|
|
3950
3990
|
const setData = (nextData) => {
|
|
@@ -3961,6 +4001,7 @@ function createChart(element, options = {}) {
|
|
|
3961
4001
|
tickerPriceTarget = null;
|
|
3962
4002
|
smoothedTickerVolume = null;
|
|
3963
4003
|
tickerVolumeTarget = null;
|
|
4004
|
+
resetRightMarginCache();
|
|
3964
4005
|
resetYViewport();
|
|
3965
4006
|
draw();
|
|
3966
4007
|
return;
|
|
@@ -3994,6 +4035,7 @@ function createChart(element, options = {}) {
|
|
|
3994
4035
|
...line,
|
|
3995
4036
|
id: line.id ?? `line-${index + 1}`
|
|
3996
4037
|
}));
|
|
4038
|
+
resetRightMarginCache();
|
|
3997
4039
|
draw();
|
|
3998
4040
|
};
|
|
3999
4041
|
const addPriceLine = (line) => {
|
|
@@ -4004,6 +4046,7 @@ function createChart(element, options = {}) {
|
|
|
4004
4046
|
};
|
|
4005
4047
|
const removePriceLine = (id) => {
|
|
4006
4048
|
priceLines = priceLines.filter((line) => line.id !== id);
|
|
4049
|
+
resetRightMarginCache();
|
|
4007
4050
|
draw();
|
|
4008
4051
|
};
|
|
4009
4052
|
const setOrderLines = (lines) => {
|
|
@@ -4011,6 +4054,7 @@ function createChart(element, options = {}) {
|
|
|
4011
4054
|
...line,
|
|
4012
4055
|
id: line.id ?? `order-${index + 1}`
|
|
4013
4056
|
}));
|
|
4057
|
+
resetRightMarginCache();
|
|
4014
4058
|
const activeIds = new Set(orderLines.map((line) => line.id));
|
|
4015
4059
|
for (const id of Array.from(orderWidgetWidthById.keys())) {
|
|
4016
4060
|
if (!activeIds.has(id)) {
|
|
@@ -4038,6 +4082,7 @@ function createChart(element, options = {}) {
|
|
|
4038
4082
|
orderLines = orderLines.filter((line) => line.id !== id);
|
|
4039
4083
|
orderWidgetWidthById.delete(id);
|
|
4040
4084
|
orderPriceTagWidthById.delete(id);
|
|
4085
|
+
resetRightMarginCache();
|
|
4041
4086
|
draw();
|
|
4042
4087
|
};
|
|
4043
4088
|
const onOrderAction = (handler) => {
|
package/dist/index.cjs
CHANGED
|
@@ -1068,6 +1068,7 @@ function createChart(element, options = {}) {
|
|
|
1068
1068
|
element.innerHTML = "";
|
|
1069
1069
|
element.appendChild(canvas);
|
|
1070
1070
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
1071
|
+
let cachedRightMargin = margin.right;
|
|
1071
1072
|
const minVisibleBars = Math.max(1, Math.floor(mergedOptions.minVisibleBars));
|
|
1072
1073
|
const maxVisibleBars = Math.max(minVisibleBars, Math.floor(mergedOptions.maxVisibleBars));
|
|
1073
1074
|
const maxPanBars = Math.max(0, Math.floor(mergedOptions.maxPanBars));
|
|
@@ -1289,14 +1290,34 @@ function createChart(element, options = {}) {
|
|
|
1289
1290
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1290
1291
|
return `${integerPart}${decimalPart}`;
|
|
1291
1292
|
};
|
|
1293
|
+
const getMeasuredLabelWidth = (text, paddingX) => {
|
|
1294
|
+
return Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1295
|
+
};
|
|
1296
|
+
const getStabilizedNumericLabelWidth = (text, paddingX) => {
|
|
1297
|
+
const measured = getMeasuredLabelWidth(text, paddingX);
|
|
1298
|
+
if (!mergedOptions.stabilizePriceLabels || !/\d/.test(text)) {
|
|
1299
|
+
return measured;
|
|
1300
|
+
}
|
|
1301
|
+
let stableWidth = measured;
|
|
1302
|
+
for (const digit of ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
|
|
1303
|
+
stableWidth = Math.max(stableWidth, getMeasuredLabelWidth(text.replace(/\d/g, digit), paddingX));
|
|
1304
|
+
}
|
|
1305
|
+
return stableWidth;
|
|
1306
|
+
};
|
|
1292
1307
|
const getPriceLabelWidth = (priceText, paddingX) => {
|
|
1293
|
-
const measured =
|
|
1308
|
+
const measured = getStabilizedNumericLabelWidth(priceText, paddingX);
|
|
1294
1309
|
if (!mergedOptions.stabilizePriceLabels) {
|
|
1295
1310
|
return measured;
|
|
1296
1311
|
}
|
|
1297
|
-
const templateWidth =
|
|
1312
|
+
const templateWidth = getStabilizedNumericLabelWidth(getStabilizedPriceTemplate(), paddingX);
|
|
1298
1313
|
return Math.max(measured, templateWidth);
|
|
1299
1314
|
};
|
|
1315
|
+
const getStableLabelWidth = (text, paddingX) => {
|
|
1316
|
+
return getStabilizedNumericLabelWidth(text, paddingX);
|
|
1317
|
+
};
|
|
1318
|
+
const resetRightMarginCache = () => {
|
|
1319
|
+
cachedRightMargin = margin.right;
|
|
1320
|
+
};
|
|
1300
1321
|
const parseData = (nextData) => {
|
|
1301
1322
|
const dedupedByTime = /* @__PURE__ */ new Map();
|
|
1302
1323
|
for (const point of nextData) {
|
|
@@ -1822,22 +1843,33 @@ function createChart(element, options = {}) {
|
|
|
1822
1843
|
const labels = { ...DEFAULT_LABELS_OPTIONS, ...mergedOptions.labels ?? {} };
|
|
1823
1844
|
const estimateRightMargin = () => {
|
|
1824
1845
|
const paddingX = Math.max(4, labels.labelPaddingX);
|
|
1825
|
-
const measure = (text) => Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1826
1846
|
let required = margin.right - 1;
|
|
1847
|
+
const includeWidth = (contentWidth) => {
|
|
1848
|
+
if (Number.isFinite(contentWidth)) {
|
|
1849
|
+
required = Math.max(required, contentWidth);
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1827
1852
|
const include = (text) => {
|
|
1828
1853
|
const normalized = text?.trim();
|
|
1829
1854
|
if (normalized) {
|
|
1830
|
-
|
|
1855
|
+
includeWidth(getStableLabelWidth(normalized, paddingX));
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
const includePrice = (price) => {
|
|
1859
|
+
if (Number.isFinite(price)) {
|
|
1860
|
+
includeWidth(getPriceLabelWidth(formatPrice(price), paddingX));
|
|
1831
1861
|
}
|
|
1832
1862
|
};
|
|
1833
1863
|
const ticker2 = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1834
1864
|
const lastPoint2 = data[data.length - 1];
|
|
1835
1865
|
if ((ticker2.visible ?? true) && labels.showLastPrice && lastPoint2) {
|
|
1836
|
-
|
|
1866
|
+
const tickerPrice2 = ticker2.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint2.c;
|
|
1867
|
+
includePrice(tickerPrice2);
|
|
1837
1868
|
if (ticker2.labelSubtext) include(String(ticker2.labelSubtext));
|
|
1838
1869
|
for (const subtext of ticker2.labelSubtexts ?? []) {
|
|
1839
1870
|
include(String(subtext));
|
|
1840
1871
|
}
|
|
1872
|
+
if (ticker2.showCountdownInLabel) include("88:88");
|
|
1841
1873
|
}
|
|
1842
1874
|
if (labels.showSymbolName) {
|
|
1843
1875
|
include(labels.symbolName);
|
|
@@ -1859,18 +1891,24 @@ function createChart(element, options = {}) {
|
|
|
1859
1891
|
for (const line of priceLines) {
|
|
1860
1892
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1861
1893
|
if (mergedLine.visible && Number.isFinite(mergedLine.price)) {
|
|
1862
|
-
|
|
1894
|
+
if (mergedLine.label) {
|
|
1895
|
+
include(mergedLine.label);
|
|
1896
|
+
} else {
|
|
1897
|
+
includePrice(mergedLine.price);
|
|
1898
|
+
}
|
|
1863
1899
|
}
|
|
1864
1900
|
}
|
|
1865
1901
|
for (const line of orderLines) {
|
|
1866
1902
|
const mergedLine = { ...DEFAULT_ORDER_LINE_OPTIONS, ...line };
|
|
1867
1903
|
const renderPrice = mergedLine.behavior === "follow" && Number.isFinite(mergedLine.followPrice) ? mergedLine.followPrice : mergedLine.price;
|
|
1868
1904
|
if (mergedLine.visible && Number.isFinite(renderPrice)) {
|
|
1869
|
-
|
|
1905
|
+
includePrice(renderPrice);
|
|
1870
1906
|
}
|
|
1871
1907
|
}
|
|
1872
1908
|
const maxRightMargin = Math.max(margin.right, width - margin.left - 160);
|
|
1873
|
-
|
|
1909
|
+
const nextRightMargin = Math.min(maxRightMargin, Math.max(margin.right, Math.ceil(required + 1)));
|
|
1910
|
+
cachedRightMargin = Math.max(cachedRightMargin, nextRightMargin);
|
|
1911
|
+
return Math.min(maxRightMargin, cachedRightMargin);
|
|
1874
1912
|
};
|
|
1875
1913
|
const rightMargin = estimateRightMargin();
|
|
1876
1914
|
const chartLeft = margin.left;
|
|
@@ -3943,6 +3981,7 @@ function createChart(element, options = {}) {
|
|
|
3943
3981
|
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
3944
3982
|
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
3945
3983
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3984
|
+
resetRightMarginCache();
|
|
3946
3985
|
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
3947
3986
|
doubleClickAction = mergedOptions.doubleClickAction;
|
|
3948
3987
|
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
@@ -3969,6 +4008,7 @@ function createChart(element, options = {}) {
|
|
|
3969
4008
|
height = nextHeight;
|
|
3970
4009
|
}
|
|
3971
4010
|
mergedOptions = { ...mergedOptions, width, height };
|
|
4011
|
+
resetRightMarginCache();
|
|
3972
4012
|
draw();
|
|
3973
4013
|
};
|
|
3974
4014
|
const setData = (nextData) => {
|
|
@@ -3985,6 +4025,7 @@ function createChart(element, options = {}) {
|
|
|
3985
4025
|
tickerPriceTarget = null;
|
|
3986
4026
|
smoothedTickerVolume = null;
|
|
3987
4027
|
tickerVolumeTarget = null;
|
|
4028
|
+
resetRightMarginCache();
|
|
3988
4029
|
resetYViewport();
|
|
3989
4030
|
draw();
|
|
3990
4031
|
return;
|
|
@@ -4018,6 +4059,7 @@ function createChart(element, options = {}) {
|
|
|
4018
4059
|
...line,
|
|
4019
4060
|
id: line.id ?? `line-${index + 1}`
|
|
4020
4061
|
}));
|
|
4062
|
+
resetRightMarginCache();
|
|
4021
4063
|
draw();
|
|
4022
4064
|
};
|
|
4023
4065
|
const addPriceLine = (line) => {
|
|
@@ -4028,6 +4070,7 @@ function createChart(element, options = {}) {
|
|
|
4028
4070
|
};
|
|
4029
4071
|
const removePriceLine = (id) => {
|
|
4030
4072
|
priceLines = priceLines.filter((line) => line.id !== id);
|
|
4073
|
+
resetRightMarginCache();
|
|
4031
4074
|
draw();
|
|
4032
4075
|
};
|
|
4033
4076
|
const setOrderLines = (lines) => {
|
|
@@ -4035,6 +4078,7 @@ function createChart(element, options = {}) {
|
|
|
4035
4078
|
...line,
|
|
4036
4079
|
id: line.id ?? `order-${index + 1}`
|
|
4037
4080
|
}));
|
|
4081
|
+
resetRightMarginCache();
|
|
4038
4082
|
const activeIds = new Set(orderLines.map((line) => line.id));
|
|
4039
4083
|
for (const id of Array.from(orderWidgetWidthById.keys())) {
|
|
4040
4084
|
if (!activeIds.has(id)) {
|
|
@@ -4062,6 +4106,7 @@ function createChart(element, options = {}) {
|
|
|
4062
4106
|
orderLines = orderLines.filter((line) => line.id !== id);
|
|
4063
4107
|
orderWidgetWidthById.delete(id);
|
|
4064
4108
|
orderPriceTagWidthById.delete(id);
|
|
4109
|
+
resetRightMarginCache();
|
|
4065
4110
|
draw();
|
|
4066
4111
|
};
|
|
4067
4112
|
const onOrderAction = (handler) => {
|
package/dist/index.js
CHANGED
|
@@ -1044,6 +1044,7 @@ function createChart(element, options = {}) {
|
|
|
1044
1044
|
element.innerHTML = "";
|
|
1045
1045
|
element.appendChild(canvas);
|
|
1046
1046
|
const margin = { top: 16, right: 72, bottom: 34, left: 12 };
|
|
1047
|
+
let cachedRightMargin = margin.right;
|
|
1047
1048
|
const minVisibleBars = Math.max(1, Math.floor(mergedOptions.minVisibleBars));
|
|
1048
1049
|
const maxVisibleBars = Math.max(minVisibleBars, Math.floor(mergedOptions.maxVisibleBars));
|
|
1049
1050
|
const maxPanBars = Math.max(0, Math.floor(mergedOptions.maxPanBars));
|
|
@@ -1265,14 +1266,34 @@ function createChart(element, options = {}) {
|
|
|
1265
1266
|
const decimalPart = decimals > 0 ? `.${"8".repeat(decimals)}` : "";
|
|
1266
1267
|
return `${integerPart}${decimalPart}`;
|
|
1267
1268
|
};
|
|
1269
|
+
const getMeasuredLabelWidth = (text, paddingX) => {
|
|
1270
|
+
return Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1271
|
+
};
|
|
1272
|
+
const getStabilizedNumericLabelWidth = (text, paddingX) => {
|
|
1273
|
+
const measured = getMeasuredLabelWidth(text, paddingX);
|
|
1274
|
+
if (!mergedOptions.stabilizePriceLabels || !/\d/.test(text)) {
|
|
1275
|
+
return measured;
|
|
1276
|
+
}
|
|
1277
|
+
let stableWidth = measured;
|
|
1278
|
+
for (const digit of ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
|
|
1279
|
+
stableWidth = Math.max(stableWidth, getMeasuredLabelWidth(text.replace(/\d/g, digit), paddingX));
|
|
1280
|
+
}
|
|
1281
|
+
return stableWidth;
|
|
1282
|
+
};
|
|
1268
1283
|
const getPriceLabelWidth = (priceText, paddingX) => {
|
|
1269
|
-
const measured =
|
|
1284
|
+
const measured = getStabilizedNumericLabelWidth(priceText, paddingX);
|
|
1270
1285
|
if (!mergedOptions.stabilizePriceLabels) {
|
|
1271
1286
|
return measured;
|
|
1272
1287
|
}
|
|
1273
|
-
const templateWidth =
|
|
1288
|
+
const templateWidth = getStabilizedNumericLabelWidth(getStabilizedPriceTemplate(), paddingX);
|
|
1274
1289
|
return Math.max(measured, templateWidth);
|
|
1275
1290
|
};
|
|
1291
|
+
const getStableLabelWidth = (text, paddingX) => {
|
|
1292
|
+
return getStabilizedNumericLabelWidth(text, paddingX);
|
|
1293
|
+
};
|
|
1294
|
+
const resetRightMarginCache = () => {
|
|
1295
|
+
cachedRightMargin = margin.right;
|
|
1296
|
+
};
|
|
1276
1297
|
const parseData = (nextData) => {
|
|
1277
1298
|
const dedupedByTime = /* @__PURE__ */ new Map();
|
|
1278
1299
|
for (const point of nextData) {
|
|
@@ -1798,22 +1819,33 @@ function createChart(element, options = {}) {
|
|
|
1798
1819
|
const labels = { ...DEFAULT_LABELS_OPTIONS, ...mergedOptions.labels ?? {} };
|
|
1799
1820
|
const estimateRightMargin = () => {
|
|
1800
1821
|
const paddingX = Math.max(4, labels.labelPaddingX);
|
|
1801
|
-
const measure = (text) => Math.ceil(ctx.measureText(text).width) + paddingX * 2;
|
|
1802
1822
|
let required = margin.right - 1;
|
|
1823
|
+
const includeWidth = (contentWidth) => {
|
|
1824
|
+
if (Number.isFinite(contentWidth)) {
|
|
1825
|
+
required = Math.max(required, contentWidth);
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1803
1828
|
const include = (text) => {
|
|
1804
1829
|
const normalized = text?.trim();
|
|
1805
1830
|
if (normalized) {
|
|
1806
|
-
|
|
1831
|
+
includeWidth(getStableLabelWidth(normalized, paddingX));
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
const includePrice = (price) => {
|
|
1835
|
+
if (Number.isFinite(price)) {
|
|
1836
|
+
includeWidth(getPriceLabelWidth(formatPrice(price), paddingX));
|
|
1807
1837
|
}
|
|
1808
1838
|
};
|
|
1809
1839
|
const ticker2 = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1810
1840
|
const lastPoint2 = data[data.length - 1];
|
|
1811
1841
|
if ((ticker2.visible ?? true) && labels.showLastPrice && lastPoint2) {
|
|
1812
|
-
|
|
1842
|
+
const tickerPrice2 = ticker2.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint2.c;
|
|
1843
|
+
includePrice(tickerPrice2);
|
|
1813
1844
|
if (ticker2.labelSubtext) include(String(ticker2.labelSubtext));
|
|
1814
1845
|
for (const subtext of ticker2.labelSubtexts ?? []) {
|
|
1815
1846
|
include(String(subtext));
|
|
1816
1847
|
}
|
|
1848
|
+
if (ticker2.showCountdownInLabel) include("88:88");
|
|
1817
1849
|
}
|
|
1818
1850
|
if (labels.showSymbolName) {
|
|
1819
1851
|
include(labels.symbolName);
|
|
@@ -1835,18 +1867,24 @@ function createChart(element, options = {}) {
|
|
|
1835
1867
|
for (const line of priceLines) {
|
|
1836
1868
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1837
1869
|
if (mergedLine.visible && Number.isFinite(mergedLine.price)) {
|
|
1838
|
-
|
|
1870
|
+
if (mergedLine.label) {
|
|
1871
|
+
include(mergedLine.label);
|
|
1872
|
+
} else {
|
|
1873
|
+
includePrice(mergedLine.price);
|
|
1874
|
+
}
|
|
1839
1875
|
}
|
|
1840
1876
|
}
|
|
1841
1877
|
for (const line of orderLines) {
|
|
1842
1878
|
const mergedLine = { ...DEFAULT_ORDER_LINE_OPTIONS, ...line };
|
|
1843
1879
|
const renderPrice = mergedLine.behavior === "follow" && Number.isFinite(mergedLine.followPrice) ? mergedLine.followPrice : mergedLine.price;
|
|
1844
1880
|
if (mergedLine.visible && Number.isFinite(renderPrice)) {
|
|
1845
|
-
|
|
1881
|
+
includePrice(renderPrice);
|
|
1846
1882
|
}
|
|
1847
1883
|
}
|
|
1848
1884
|
const maxRightMargin = Math.max(margin.right, width - margin.left - 160);
|
|
1849
|
-
|
|
1885
|
+
const nextRightMargin = Math.min(maxRightMargin, Math.max(margin.right, Math.ceil(required + 1)));
|
|
1886
|
+
cachedRightMargin = Math.max(cachedRightMargin, nextRightMargin);
|
|
1887
|
+
return Math.min(maxRightMargin, cachedRightMargin);
|
|
1850
1888
|
};
|
|
1851
1889
|
const rightMargin = estimateRightMargin();
|
|
1852
1890
|
const chartLeft = margin.left;
|
|
@@ -3919,6 +3957,7 @@ function createChart(element, options = {}) {
|
|
|
3919
3957
|
width = nextOptions.width !== void 0 && nextOptions.width > 0 ? mergedOptions.width : previousWidth;
|
|
3920
3958
|
height = nextOptions.height !== void 0 && nextOptions.height > 0 ? mergedOptions.height : previousHeight;
|
|
3921
3959
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3960
|
+
resetRightMarginCache();
|
|
3922
3961
|
doubleClickEnabled = mergedOptions.doubleClickEnabled;
|
|
3923
3962
|
doubleClickAction = mergedOptions.doubleClickAction;
|
|
3924
3963
|
const isTickerSmoothingEnabled = mergedOptions.tickerLine?.smoothing ?? false;
|
|
@@ -3945,6 +3984,7 @@ function createChart(element, options = {}) {
|
|
|
3945
3984
|
height = nextHeight;
|
|
3946
3985
|
}
|
|
3947
3986
|
mergedOptions = { ...mergedOptions, width, height };
|
|
3987
|
+
resetRightMarginCache();
|
|
3948
3988
|
draw();
|
|
3949
3989
|
};
|
|
3950
3990
|
const setData = (nextData) => {
|
|
@@ -3961,6 +4001,7 @@ function createChart(element, options = {}) {
|
|
|
3961
4001
|
tickerPriceTarget = null;
|
|
3962
4002
|
smoothedTickerVolume = null;
|
|
3963
4003
|
tickerVolumeTarget = null;
|
|
4004
|
+
resetRightMarginCache();
|
|
3964
4005
|
resetYViewport();
|
|
3965
4006
|
draw();
|
|
3966
4007
|
return;
|
|
@@ -3994,6 +4035,7 @@ function createChart(element, options = {}) {
|
|
|
3994
4035
|
...line,
|
|
3995
4036
|
id: line.id ?? `line-${index + 1}`
|
|
3996
4037
|
}));
|
|
4038
|
+
resetRightMarginCache();
|
|
3997
4039
|
draw();
|
|
3998
4040
|
};
|
|
3999
4041
|
const addPriceLine = (line) => {
|
|
@@ -4004,6 +4046,7 @@ function createChart(element, options = {}) {
|
|
|
4004
4046
|
};
|
|
4005
4047
|
const removePriceLine = (id) => {
|
|
4006
4048
|
priceLines = priceLines.filter((line) => line.id !== id);
|
|
4049
|
+
resetRightMarginCache();
|
|
4007
4050
|
draw();
|
|
4008
4051
|
};
|
|
4009
4052
|
const setOrderLines = (lines) => {
|
|
@@ -4011,6 +4054,7 @@ function createChart(element, options = {}) {
|
|
|
4011
4054
|
...line,
|
|
4012
4055
|
id: line.id ?? `order-${index + 1}`
|
|
4013
4056
|
}));
|
|
4057
|
+
resetRightMarginCache();
|
|
4014
4058
|
const activeIds = new Set(orderLines.map((line) => line.id));
|
|
4015
4059
|
for (const id of Array.from(orderWidgetWidthById.keys())) {
|
|
4016
4060
|
if (!activeIds.has(id)) {
|
|
@@ -4038,6 +4082,7 @@ function createChart(element, options = {}) {
|
|
|
4038
4082
|
orderLines = orderLines.filter((line) => line.id !== id);
|
|
4039
4083
|
orderWidgetWidthById.delete(id);
|
|
4040
4084
|
orderPriceTagWidthById.delete(id);
|
|
4085
|
+
resetRightMarginCache();
|
|
4041
4086
|
draw();
|
|
4042
4087
|
};
|
|
4043
4088
|
const onOrderAction = (handler) => {
|