hyperprop-charting-library 0.1.44 → 0.1.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/hyperprop-charting-library.cjs +260 -19
- package/dist/hyperprop-charting-library.d.ts +35 -1
- package/dist/hyperprop-charting-library.js +260 -19
- package/dist/index.cjs +260 -19
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +260 -19
- package/docs/API.md +45 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,6 +60,18 @@ const chart = createChart(root, {
|
|
|
60
60
|
});
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
## Current Price Label Subtext
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const chart = createChart(root, {
|
|
67
|
+
tickerLine: {
|
|
68
|
+
labelSubtext: "MNQ"
|
|
69
|
+
// or:
|
|
70
|
+
// showCountdownInLabel: true
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
63
75
|
## Candle Color Behavior
|
|
64
76
|
|
|
65
77
|
You can control how up/down candle color is decided:
|
|
@@ -94,6 +106,28 @@ const chart = createChart(root, {
|
|
|
94
106
|
});
|
|
95
107
|
```
|
|
96
108
|
|
|
109
|
+
## TradingView-Style Labels
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const chart = createChart(root, {
|
|
113
|
+
labels: {
|
|
114
|
+
symbolName: "ESH6",
|
|
115
|
+
showSymbolName: true,
|
|
116
|
+
showLastPrice: true,
|
|
117
|
+
showPreviousClose: true,
|
|
118
|
+
previousClosePrice: 5231.25,
|
|
119
|
+
showHighLow: true,
|
|
120
|
+
showBidAsk: true,
|
|
121
|
+
bidPrice: 5234.75,
|
|
122
|
+
askPrice: 5235.0,
|
|
123
|
+
showIndicatorNames: true,
|
|
124
|
+
showIndicatorValues: true,
|
|
125
|
+
showCountdownToBarClose: true,
|
|
126
|
+
noOverlapping: true
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
97
131
|
## Axis Label Density
|
|
98
132
|
|
|
99
133
|
```ts
|
|
@@ -85,6 +85,35 @@ var DEFAULT_DASH_PATTERNS = {
|
|
|
85
85
|
borderDotted: [2, 2],
|
|
86
86
|
borderDashed: [6, 4]
|
|
87
87
|
};
|
|
88
|
+
var DEFAULT_LABELS_OPTIONS = {
|
|
89
|
+
visible: true,
|
|
90
|
+
symbolName: "",
|
|
91
|
+
showSymbolName: false,
|
|
92
|
+
showLastPrice: true,
|
|
93
|
+
showPreviousClose: false,
|
|
94
|
+
previousClosePrice: Number.NaN,
|
|
95
|
+
showHighLow: false,
|
|
96
|
+
showBidAsk: false,
|
|
97
|
+
bidPrice: Number.NaN,
|
|
98
|
+
askPrice: Number.NaN,
|
|
99
|
+
showIndicatorNames: false,
|
|
100
|
+
showIndicatorValues: false,
|
|
101
|
+
showCountdownToBarClose: false,
|
|
102
|
+
noOverlapping: true,
|
|
103
|
+
backgroundColor: "#0b1220",
|
|
104
|
+
textColor: "#cbd5e1",
|
|
105
|
+
mutedTextColor: "#94a3b8",
|
|
106
|
+
symbolNameBackgroundColor: "#1f2937",
|
|
107
|
+
symbolNameTextColor: "#e5e7eb",
|
|
108
|
+
previousCloseColor: "#94a3b8",
|
|
109
|
+
highLowColor: "#a78bfa",
|
|
110
|
+
bidColor: "#ef4444",
|
|
111
|
+
askColor: "#22c55e",
|
|
112
|
+
indicatorTextColor: "#cbd5e1",
|
|
113
|
+
borderRadius: 3,
|
|
114
|
+
labelHeight: 20,
|
|
115
|
+
labelPaddingX: 8
|
|
116
|
+
};
|
|
88
117
|
var DEFAULT_PRICE_LINE_OPTIONS = {
|
|
89
118
|
visible: true,
|
|
90
119
|
style: "solid",
|
|
@@ -172,8 +201,13 @@ var DEFAULT_OPTIONS = {
|
|
|
172
201
|
style: "dotted",
|
|
173
202
|
thickness: 1,
|
|
174
203
|
labelTextColor: "#0b1220",
|
|
204
|
+
labelSubtext: "",
|
|
205
|
+
labelSubtextColor: "#0b1220",
|
|
206
|
+
labelSubtextFontSize: 0,
|
|
207
|
+
showCountdownInLabel: false,
|
|
175
208
|
labelBorderRadius: 3
|
|
176
209
|
},
|
|
210
|
+
labels: DEFAULT_LABELS_OPTIONS,
|
|
177
211
|
dashPatterns: DEFAULT_DASH_PATTERNS,
|
|
178
212
|
indicators: []
|
|
179
213
|
};
|
|
@@ -213,6 +247,10 @@ var mergeChartOptions = (baseOptions, options = {}) => ({
|
|
|
213
247
|
...baseOptions.tickerLine,
|
|
214
248
|
...options.tickerLine ?? {}
|
|
215
249
|
},
|
|
250
|
+
labels: {
|
|
251
|
+
...baseOptions.labels,
|
|
252
|
+
...options.labels ?? {}
|
|
253
|
+
},
|
|
216
254
|
dashPatterns: {
|
|
217
255
|
...baseOptions.dashPatterns,
|
|
218
256
|
...options.dashPatterns ?? {}
|
|
@@ -1279,6 +1317,14 @@ function createChart(element, options = {}) {
|
|
|
1279
1317
|
ctx.textBaseline = baseline;
|
|
1280
1318
|
ctx.fillText(text, x, y);
|
|
1281
1319
|
};
|
|
1320
|
+
const formatDuration = (ms) => {
|
|
1321
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1e3));
|
|
1322
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
1323
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
1324
|
+
const seconds = totalSeconds % 60;
|
|
1325
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
1326
|
+
return hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;
|
|
1327
|
+
};
|
|
1282
1328
|
const drawPriceLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
1283
1329
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1284
1330
|
if (!mergedLine.visible || !Number.isFinite(mergedLine.price)) {
|
|
@@ -2038,14 +2084,49 @@ function createChart(element, options = {}) {
|
|
|
2038
2084
|
drawText(formatPrice(price), chartRight + 6, y, "left", "middle", yAxis.textColor);
|
|
2039
2085
|
ctx.font = prevFont;
|
|
2040
2086
|
}
|
|
2087
|
+
const labels = { ...DEFAULT_LABELS_OPTIONS, ...mergedOptions.labels ?? {} };
|
|
2088
|
+
const priceAxisLabels = [];
|
|
2089
|
+
const addPriceAxisLabel = (label) => {
|
|
2090
|
+
if (!labels.visible || !Number.isFinite(label.price) || label.text.length === 0) {
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
priceAxisLabels.push(label);
|
|
2094
|
+
};
|
|
2095
|
+
const drawReferenceLine = (price, color, style = "dotted") => {
|
|
2096
|
+
if (!Number.isFinite(price)) {
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
const y = clamp(yFromPrice(price), chartTop + 1, chartBottom - 1);
|
|
2100
|
+
ctx.save();
|
|
2101
|
+
ctx.strokeStyle = color;
|
|
2102
|
+
ctx.lineWidth = 1;
|
|
2103
|
+
applyDashPattern(style, dashPatterns.dotted, dashPatterns.dashed);
|
|
2104
|
+
ctx.beginPath();
|
|
2105
|
+
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2106
|
+
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2107
|
+
ctx.stroke();
|
|
2108
|
+
ctx.restore();
|
|
2109
|
+
};
|
|
2110
|
+
const getCountdownText = () => {
|
|
2111
|
+
const last = data[data.length - 1];
|
|
2112
|
+
if (!last) {
|
|
2113
|
+
return null;
|
|
2114
|
+
}
|
|
2115
|
+
const stepMs = getTimeStepMs();
|
|
2116
|
+
const rawRemainingMs = last.time.getTime() + stepMs - Date.now();
|
|
2117
|
+
const countdownMs = rawRemainingMs >= 0 && rawRemainingMs <= stepMs * 2 ? rawRemainingMs : stepMs - Date.now() % stepMs;
|
|
2118
|
+
return formatDuration(countdownMs);
|
|
2119
|
+
};
|
|
2041
2120
|
const ticker = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
2042
2121
|
const lastPoint = data[data.length - 1];
|
|
2122
|
+
let tickerPrice = null;
|
|
2123
|
+
let tickerColor = null;
|
|
2043
2124
|
if ((ticker.visible ?? true) && lastPoint) {
|
|
2044
|
-
|
|
2125
|
+
tickerPrice = ticker.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint.c;
|
|
2045
2126
|
const tickerY = yFromPrice(tickerPrice);
|
|
2046
2127
|
const lineY = clamp(tickerY, chartTop + 1, chartBottom - 1);
|
|
2047
2128
|
const lastDirection = ticker.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice >= lastPoint.o ? "up" : "down" : getCandleDirectionByIndex(data.length - 1);
|
|
2048
|
-
|
|
2129
|
+
tickerColor = ticker.color ?? (lastDirection === "up" ? mergedOptions.upColor : mergedOptions.downColor);
|
|
2049
2130
|
const tickerThickness = Math.max(1, ticker.thickness ?? 1);
|
|
2050
2131
|
const tickerStyle = ticker.style ?? "solid";
|
|
2051
2132
|
ctx.save();
|
|
@@ -2058,24 +2139,155 @@ function createChart(element, options = {}) {
|
|
|
2058
2139
|
ctx.stroke();
|
|
2059
2140
|
ctx.setLineDash([]);
|
|
2060
2141
|
ctx.restore();
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
const
|
|
2064
|
-
|
|
2065
|
-
|
|
2142
|
+
}
|
|
2143
|
+
if ((ticker.visible ?? true) && labels.showLastPrice && tickerPrice !== null && tickerColor !== null) {
|
|
2144
|
+
const tickerSubtext = ticker.showCountdownInLabel ? getCountdownText() : ticker.labelSubtext?.trim();
|
|
2145
|
+
addPriceAxisLabel({
|
|
2146
|
+
text: formatPrice(tickerPrice),
|
|
2147
|
+
...tickerSubtext ? { subtext: tickerSubtext } : {},
|
|
2148
|
+
subtextColor: ticker.labelSubtextColor ?? ticker.labelTextColor ?? "#0b1220",
|
|
2149
|
+
...ticker.labelSubtextFontSize === void 0 ? {} : { subtextFontSize: ticker.labelSubtextFontSize },
|
|
2150
|
+
price: tickerPrice,
|
|
2151
|
+
backgroundColor: ticker.labelBackgroundColor ?? tickerColor,
|
|
2152
|
+
textColor: ticker.labelTextColor ?? "#0b1220",
|
|
2153
|
+
color: tickerColor,
|
|
2154
|
+
priority: 100
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
if (labels.showSymbolName && labels.symbolName.trim().length > 0 && tickerPrice !== null) {
|
|
2158
|
+
addPriceAxisLabel({
|
|
2159
|
+
text: labels.symbolName.trim(),
|
|
2160
|
+
price: tickerPrice,
|
|
2161
|
+
backgroundColor: labels.symbolNameBackgroundColor,
|
|
2162
|
+
textColor: labels.symbolNameTextColor,
|
|
2163
|
+
color: labels.symbolNameBackgroundColor,
|
|
2164
|
+
priority: 95
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
if (labels.showPreviousClose) {
|
|
2168
|
+
const previousCloseCandidate = Number.isFinite(labels.previousClosePrice) ? labels.previousClosePrice : data.length > 1 ? data[data.length - 2]?.c : Number.NaN;
|
|
2169
|
+
if (previousCloseCandidate !== void 0 && Number.isFinite(previousCloseCandidate)) {
|
|
2170
|
+
const previousClose = previousCloseCandidate;
|
|
2171
|
+
drawReferenceLine(previousClose, labels.previousCloseColor, "dashed");
|
|
2172
|
+
addPriceAxisLabel({
|
|
2173
|
+
text: `PDC ${formatPrice(previousClose)}`,
|
|
2174
|
+
price: previousClose,
|
|
2175
|
+
backgroundColor: labels.backgroundColor,
|
|
2176
|
+
textColor: labels.mutedTextColor,
|
|
2177
|
+
color: labels.previousCloseColor,
|
|
2178
|
+
priority: 50
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
if (labels.showHighLow && visibleData.length > 0) {
|
|
2183
|
+
const visibleHigh = Math.max(...visibleData.map((point) => point.h));
|
|
2184
|
+
const visibleLow = Math.min(...visibleData.map((point) => point.l));
|
|
2185
|
+
addPriceAxisLabel({
|
|
2186
|
+
text: `H ${formatPrice(visibleHigh)}`,
|
|
2187
|
+
price: visibleHigh,
|
|
2188
|
+
backgroundColor: labels.backgroundColor,
|
|
2189
|
+
textColor: labels.textColor,
|
|
2190
|
+
color: labels.highLowColor,
|
|
2191
|
+
priority: 40
|
|
2192
|
+
});
|
|
2193
|
+
addPriceAxisLabel({
|
|
2194
|
+
text: `L ${formatPrice(visibleLow)}`,
|
|
2195
|
+
price: visibleLow,
|
|
2196
|
+
backgroundColor: labels.backgroundColor,
|
|
2197
|
+
textColor: labels.textColor,
|
|
2198
|
+
color: labels.highLowColor,
|
|
2199
|
+
priority: 40
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
if (labels.showBidAsk) {
|
|
2203
|
+
if (Number.isFinite(labels.bidPrice)) {
|
|
2204
|
+
drawReferenceLine(labels.bidPrice, labels.bidColor, "dotted");
|
|
2205
|
+
addPriceAxisLabel({
|
|
2206
|
+
text: `B ${formatPrice(labels.bidPrice)}`,
|
|
2207
|
+
price: labels.bidPrice,
|
|
2208
|
+
backgroundColor: labels.bidColor,
|
|
2209
|
+
textColor: "#0b1220",
|
|
2210
|
+
color: labels.bidColor,
|
|
2211
|
+
priority: 80
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
if (Number.isFinite(labels.askPrice)) {
|
|
2215
|
+
drawReferenceLine(labels.askPrice, labels.askColor, "dotted");
|
|
2216
|
+
addPriceAxisLabel({
|
|
2217
|
+
text: `A ${formatPrice(labels.askPrice)}`,
|
|
2218
|
+
price: labels.askPrice,
|
|
2219
|
+
backgroundColor: labels.askColor,
|
|
2220
|
+
textColor: "#0b1220",
|
|
2221
|
+
color: labels.askColor,
|
|
2222
|
+
priority: 80
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
if (priceAxisLabels.length > 0) {
|
|
2227
|
+
const labelPaddingX = Math.max(4, labels.labelPaddingX);
|
|
2228
|
+
const baseLabelHeight = Math.max(14, labels.labelHeight);
|
|
2229
|
+
const labelRadius = Math.max(0, labels.borderRadius);
|
|
2230
|
+
const priceLabelFontSize = Math.max(8, axis.fontSize);
|
|
2231
|
+
ctx.font = `${priceLabelFontSize}px ${mergedOptions.fontFamily}`;
|
|
2232
|
+
const positionedLabels = priceAxisLabels.map((label) => {
|
|
2233
|
+
const subtext = label.subtext?.trim();
|
|
2234
|
+
const subtextFontSize = label.subtextFontSize !== void 0 && label.subtextFontSize > 0 ? Math.max(8, Math.round(label.subtextFontSize)) : priceLabelFontSize;
|
|
2235
|
+
const labelHeight = baseLabelHeight + (subtext ? subtextFontSize + 5 : 0);
|
|
2236
|
+
const primaryWidth = label.text === formatPrice(label.price) ? getPriceLabelWidth(label.text, labelPaddingX) : Math.ceil(ctx.measureText(label.text).width) + labelPaddingX * 2;
|
|
2237
|
+
let subtextWidth = 0;
|
|
2238
|
+
if (subtext) {
|
|
2239
|
+
const baseFont = ctx.font;
|
|
2240
|
+
ctx.font = `${subtextFontSize}px ${mergedOptions.fontFamily}`;
|
|
2241
|
+
subtextWidth = Math.ceil(ctx.measureText(subtext).width) + labelPaddingX * 2;
|
|
2242
|
+
ctx.font = baseFont;
|
|
2243
|
+
}
|
|
2244
|
+
const labelTextWidth = Math.max(primaryWidth, subtextWidth);
|
|
2245
|
+
return {
|
|
2246
|
+
...label,
|
|
2247
|
+
subtext,
|
|
2248
|
+
subtextFontSize,
|
|
2249
|
+
height: labelHeight,
|
|
2250
|
+
width: labelTextWidth,
|
|
2251
|
+
targetY: clamp(yFromPrice(label.price), chartTop + 1, chartBottom - 1) - labelHeight / 2,
|
|
2252
|
+
y: 0
|
|
2253
|
+
};
|
|
2254
|
+
}).sort((a, b) => a.targetY - b.targetY || b.priority - a.priority);
|
|
2255
|
+
const minY = chartTop;
|
|
2256
|
+
let cursorY = minY;
|
|
2257
|
+
for (const label of positionedLabels) {
|
|
2258
|
+
const maxY = chartBottom - label.height;
|
|
2259
|
+
label.y = labels.noOverlapping ? Math.max(clamp(label.targetY, minY, maxY), cursorY) : clamp(label.targetY, minY, maxY);
|
|
2260
|
+
cursorY = label.y + label.height + 2;
|
|
2261
|
+
}
|
|
2262
|
+
if (labels.noOverlapping && positionedLabels.length > 0) {
|
|
2263
|
+
const lastLabel = positionedLabels[positionedLabels.length - 1];
|
|
2264
|
+
const overflow = lastLabel ? lastLabel.y + lastLabel.height - chartBottom : 0;
|
|
2265
|
+
if (overflow > 0) {
|
|
2266
|
+
for (const label of positionedLabels) {
|
|
2267
|
+
label.y = Math.max(minY, label.y - overflow);
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2066
2271
|
const labelX = chartRight + 4;
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2272
|
+
for (const label of positionedLabels) {
|
|
2273
|
+
ctx.fillStyle = label.backgroundColor;
|
|
2274
|
+
fillRoundedRect(Math.round(labelX), Math.round(label.y), label.width, label.height, labelRadius);
|
|
2275
|
+
const primaryY = label.subtext ? label.y + baseLabelHeight / 2 - 1 : label.y + label.height / 2;
|
|
2276
|
+
drawText(label.text, labelX + labelPaddingX, primaryY, "left", "middle", label.textColor);
|
|
2277
|
+
if (label.subtext) {
|
|
2278
|
+
const baseFont = ctx.font;
|
|
2279
|
+
ctx.font = `${label.subtextFontSize}px ${mergedOptions.fontFamily}`;
|
|
2280
|
+
drawText(
|
|
2281
|
+
label.subtext,
|
|
2282
|
+
labelX + labelPaddingX,
|
|
2283
|
+
label.y + baseLabelHeight + label.subtextFontSize / 2,
|
|
2284
|
+
"left",
|
|
2285
|
+
"middle",
|
|
2286
|
+
label.subtextColor ?? label.textColor
|
|
2287
|
+
);
|
|
2288
|
+
ctx.font = baseFont;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2079
2291
|
}
|
|
2080
2292
|
for (const priceLine of priceLines) {
|
|
2081
2293
|
drawPriceLine(priceLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
@@ -2083,6 +2295,25 @@ function createChart(element, options = {}) {
|
|
|
2083
2295
|
for (const orderLine of orderLines) {
|
|
2084
2296
|
drawOrderLine(orderLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
2085
2297
|
}
|
|
2298
|
+
if (labels.visible && (labels.showIndicatorNames || labels.showIndicatorValues)) {
|
|
2299
|
+
const labelEntries = [...activeOverlayIndicators, ...activeSeparateIndicators].map(({ indicator, plugin }) => {
|
|
2300
|
+
const inputValues = Object.entries(indicator.inputs).filter(([, value]) => typeof value === "number" || typeof value === "string" || typeof value === "boolean").slice(0, 2).map(([, value]) => String(value));
|
|
2301
|
+
if (labels.showIndicatorNames && labels.showIndicatorValues && inputValues.length > 0) {
|
|
2302
|
+
return `${plugin.name} ${inputValues.join(" ")}`;
|
|
2303
|
+
}
|
|
2304
|
+
if (labels.showIndicatorNames) {
|
|
2305
|
+
return plugin.name;
|
|
2306
|
+
}
|
|
2307
|
+
return inputValues.join(" ");
|
|
2308
|
+
}).filter((entry) => entry.length > 0);
|
|
2309
|
+
if (labelEntries.length > 0) {
|
|
2310
|
+
const prevFont = ctx.font;
|
|
2311
|
+
ctx.font = `${Math.max(8, axis.fontSize)}px ${mergedOptions.fontFamily}`;
|
|
2312
|
+
const legendText = labelEntries.join(" ");
|
|
2313
|
+
drawText(legendText, chartLeft + 10, chartTop + 10, "left", "top", labels.indicatorTextColor);
|
|
2314
|
+
ctx.font = prevFont;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2086
2317
|
for (let index = tickStartIndex; index <= visibleTickEnd; index += xStep) {
|
|
2087
2318
|
const tickTime = getTimeForIndex(index);
|
|
2088
2319
|
if (!tickTime) {
|
|
@@ -2098,6 +2329,16 @@ function createChart(element, options = {}) {
|
|
|
2098
2329
|
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
|
2099
2330
|
ctx.font = prevFont;
|
|
2100
2331
|
}
|
|
2332
|
+
if (labels.visible && labels.showCountdownToBarClose && lastPoint) {
|
|
2333
|
+
const stepMs = getTimeStepMs();
|
|
2334
|
+
const rawRemainingMs = lastPoint.time.getTime() + stepMs - Date.now();
|
|
2335
|
+
const countdownMs = rawRemainingMs >= 0 && rawRemainingMs <= stepMs * 2 ? rawRemainingMs : stepMs - Date.now() % stepMs;
|
|
2336
|
+
const countdownText = formatDuration(countdownMs);
|
|
2337
|
+
const prevFont = ctx.font;
|
|
2338
|
+
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
2339
|
+
drawText(countdownText, chartRight + 6, fullChartBottom + 8, "left", "top", xAxis.textColor);
|
|
2340
|
+
ctx.font = prevFont;
|
|
2341
|
+
}
|
|
2101
2342
|
if (crosshair.visible && crosshairPoint) {
|
|
2102
2343
|
const cx = clamp(crosshairPoint.x, chartLeft, chartRight);
|
|
2103
2344
|
const cy = clamp(crosshairPoint.y, chartTop, chartBottom);
|
|
@@ -37,6 +37,7 @@ interface ChartOptions {
|
|
|
37
37
|
priceLines?: PriceLineOptions[];
|
|
38
38
|
orderLines?: OrderLineOptions[];
|
|
39
39
|
tickerLine?: TickerLineOptions;
|
|
40
|
+
labels?: LabelsOptions;
|
|
40
41
|
dashPatterns?: Partial<DashPatternOptions>;
|
|
41
42
|
indicators?: IndicatorInstanceOptions[];
|
|
42
43
|
}
|
|
@@ -259,10 +260,43 @@ interface TickerLineOptions {
|
|
|
259
260
|
color?: string;
|
|
260
261
|
labelBackgroundColor?: string;
|
|
261
262
|
labelTextColor?: string;
|
|
263
|
+
labelSubtext?: string;
|
|
264
|
+
labelSubtextColor?: string;
|
|
265
|
+
labelSubtextFontSize?: number;
|
|
266
|
+
showCountdownInLabel?: boolean;
|
|
262
267
|
labelBorderRadius?: number;
|
|
263
268
|
smoothing?: boolean;
|
|
264
269
|
smoothingSpeed?: number;
|
|
265
270
|
}
|
|
271
|
+
interface LabelsOptions {
|
|
272
|
+
visible?: boolean;
|
|
273
|
+
symbolName?: string;
|
|
274
|
+
showSymbolName?: boolean;
|
|
275
|
+
showLastPrice?: boolean;
|
|
276
|
+
showPreviousClose?: boolean;
|
|
277
|
+
previousClosePrice?: number;
|
|
278
|
+
showHighLow?: boolean;
|
|
279
|
+
showBidAsk?: boolean;
|
|
280
|
+
bidPrice?: number;
|
|
281
|
+
askPrice?: number;
|
|
282
|
+
showIndicatorNames?: boolean;
|
|
283
|
+
showIndicatorValues?: boolean;
|
|
284
|
+
showCountdownToBarClose?: boolean;
|
|
285
|
+
noOverlapping?: boolean;
|
|
286
|
+
backgroundColor?: string;
|
|
287
|
+
textColor?: string;
|
|
288
|
+
mutedTextColor?: string;
|
|
289
|
+
symbolNameBackgroundColor?: string;
|
|
290
|
+
symbolNameTextColor?: string;
|
|
291
|
+
previousCloseColor?: string;
|
|
292
|
+
highLowColor?: string;
|
|
293
|
+
bidColor?: string;
|
|
294
|
+
askColor?: string;
|
|
295
|
+
indicatorTextColor?: string;
|
|
296
|
+
borderRadius?: number;
|
|
297
|
+
labelHeight?: number;
|
|
298
|
+
labelPaddingX?: number;
|
|
299
|
+
}
|
|
266
300
|
interface ChartInstance {
|
|
267
301
|
updateOptions: (options: ChartOptions) => void;
|
|
268
302
|
setData: (data: OhlcDataPoint[]) => void;
|
|
@@ -326,4 +360,4 @@ interface ViewportState {
|
|
|
326
360
|
}
|
|
327
361
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
328
362
|
|
|
329
|
-
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
|
363
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|