hyperprop-charting-library 0.1.151 → 0.1.153
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 +36 -22
- package/dist/hyperprop-charting-library.d.ts +5 -0
- package/dist/hyperprop-charting-library.js +36 -22
- package/dist/index.cjs +36 -22
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +36 -22
- package/package.json +1 -1
|
@@ -3587,8 +3587,10 @@ var DEFAULT_LABELS_OPTIONS = {
|
|
|
3587
3587
|
showIndicatorValues: false,
|
|
3588
3588
|
showIndicatorValueLabels: true,
|
|
3589
3589
|
indicatorLegendPosition: "top-left",
|
|
3590
|
-
|
|
3591
|
-
|
|
3590
|
+
// One inset for the whole top-left block (data line + legend), so the gap
|
|
3591
|
+
// from the left edge matches the gap from the top.
|
|
3592
|
+
indicatorLegendOffsetX: 12,
|
|
3593
|
+
indicatorLegendOffsetY: 12,
|
|
3592
3594
|
showCountdownToBarClose: false,
|
|
3593
3595
|
noOverlapping: true,
|
|
3594
3596
|
backgroundColor: "#0b1220",
|
|
@@ -6287,6 +6289,8 @@ function createChart(element, options = {}) {
|
|
|
6287
6289
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
6288
6290
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
6289
6291
|
const move = p1.price - p0.price;
|
|
6292
|
+
const lineLeft = Math.min(x0, x1, x2);
|
|
6293
|
+
const lineRight = Math.max(x0, x1, x2);
|
|
6290
6294
|
const levelLines = FIB_EXT_RATIOS.map((ratio) => {
|
|
6291
6295
|
const price = p2.price + move * ratio;
|
|
6292
6296
|
return { ratio, price, y: yFromPrice(price) };
|
|
@@ -6299,7 +6303,7 @@ function createChart(element, options = {}) {
|
|
|
6299
6303
|
ctx.save();
|
|
6300
6304
|
ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
|
|
6301
6305
|
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
6302
|
-
ctx.fillRect(
|
|
6306
|
+
ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
|
|
6303
6307
|
ctx.restore();
|
|
6304
6308
|
}
|
|
6305
6309
|
ctx.save();
|
|
@@ -6308,8 +6312,8 @@ function createChart(element, options = {}) {
|
|
|
6308
6312
|
levelLines.forEach((level, index) => {
|
|
6309
6313
|
ctx.strokeStyle = levelColorAt(index);
|
|
6310
6314
|
ctx.beginPath();
|
|
6311
|
-
ctx.moveTo(crisp(
|
|
6312
|
-
ctx.lineTo(crisp(
|
|
6315
|
+
ctx.moveTo(crisp(lineLeft), crisp(level.y));
|
|
6316
|
+
ctx.lineTo(crisp(lineRight), crisp(level.y));
|
|
6313
6317
|
ctx.stroke();
|
|
6314
6318
|
});
|
|
6315
6319
|
ctx.restore();
|
|
@@ -6319,7 +6323,7 @@ function createChart(element, options = {}) {
|
|
|
6319
6323
|
const labelText = `${level.ratio} (${formatPrice(level.price)})`;
|
|
6320
6324
|
const textWidth = measureTextWidth(labelText);
|
|
6321
6325
|
const padding = 4;
|
|
6322
|
-
const bgX = chartLeft + 4;
|
|
6326
|
+
const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
|
|
6323
6327
|
const bgY = level.y - 9;
|
|
6324
6328
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
6325
6329
|
fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
|
|
@@ -8264,6 +8268,8 @@ function createChart(element, options = {}) {
|
|
|
8264
8268
|
for (const orderLine of orderLines) {
|
|
8265
8269
|
drawOrderLine(orderLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
8266
8270
|
}
|
|
8271
|
+
const legendInsetX = Math.max(0, Number(labels.indicatorLegendOffsetX) || 0);
|
|
8272
|
+
const legendInsetY = Math.max(0, Number(labels.indicatorLegendOffsetY) || 0);
|
|
8267
8273
|
let dataLineBottom = chartTop;
|
|
8268
8274
|
const dataLine = mergedOptions.dataLine;
|
|
8269
8275
|
if (dataLine?.visible && data.length > 0) {
|
|
@@ -8280,8 +8286,8 @@ function createChart(element, options = {}) {
|
|
|
8280
8286
|
const textColor = dataLine.textColor || labels.indicatorTextColor;
|
|
8281
8287
|
const changeAbs = bar.c - bar.o;
|
|
8282
8288
|
const changeColor = changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor;
|
|
8283
|
-
const rowY = chartTop +
|
|
8284
|
-
let cursorX = chartLeft +
|
|
8289
|
+
const rowY = chartTop + legendInsetY;
|
|
8290
|
+
let cursorX = chartLeft + legendInsetX;
|
|
8285
8291
|
if (dataLine.statusColor) {
|
|
8286
8292
|
const dotRadius = Math.max(2.5, fontSize / 4);
|
|
8287
8293
|
ctx.fillStyle = dataLine.statusColor;
|
|
@@ -8327,7 +8333,7 @@ function createChart(element, options = {}) {
|
|
|
8327
8333
|
ctx.fillText(text, cursorX, rowY);
|
|
8328
8334
|
cursorX += width2 + 12;
|
|
8329
8335
|
}
|
|
8330
|
-
dataLineBottom = rowY + fontSize +
|
|
8336
|
+
dataLineBottom = rowY + fontSize + 6;
|
|
8331
8337
|
ctx.font = prevFont;
|
|
8332
8338
|
}
|
|
8333
8339
|
}
|
|
@@ -8357,8 +8363,8 @@ function createChart(element, options = {}) {
|
|
|
8357
8363
|
const prevFont = ctx.font;
|
|
8358
8364
|
const legendFontSize = Math.max(8, axis.fontSize);
|
|
8359
8365
|
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
8360
|
-
const offsetX =
|
|
8361
|
-
const offsetY =
|
|
8366
|
+
const offsetX = legendInsetX;
|
|
8367
|
+
const offsetY = legendInsetY;
|
|
8362
8368
|
const position = labels.indicatorLegendPosition;
|
|
8363
8369
|
const isRight = position === "top-right" || position === "bottom-right";
|
|
8364
8370
|
const isBottom = position === "bottom-left" || position === "bottom-right";
|
|
@@ -9383,12 +9389,16 @@ function createChart(element, options = {}) {
|
|
|
9383
9389
|
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
9384
9390
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
9385
9391
|
}
|
|
9386
|
-
const
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
const
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
+
const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
|
|
9393
|
+
const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
|
|
9394
|
+
if (x >= fibLeft && x <= fibRight) {
|
|
9395
|
+
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
9396
|
+
for (const ratio of fibRatios) {
|
|
9397
|
+
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
9398
|
+
const lineY = canvasYFromDrawingPrice(price);
|
|
9399
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9400
|
+
return { drawing, target: "line" };
|
|
9401
|
+
}
|
|
9392
9402
|
}
|
|
9393
9403
|
}
|
|
9394
9404
|
} else if (drawing.type === "fib-extension") {
|
|
@@ -9413,11 +9423,15 @@ function createChart(element, options = {}) {
|
|
|
9413
9423
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
9414
9424
|
}
|
|
9415
9425
|
const move = p1.price - p0.price;
|
|
9416
|
-
const
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9426
|
+
const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
|
|
9427
|
+
const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
|
|
9428
|
+
if (x >= extLeft && x <= extRight) {
|
|
9429
|
+
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
9430
|
+
for (const ratio of fibExtRatios) {
|
|
9431
|
+
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
9432
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9433
|
+
return { drawing, target: "line" };
|
|
9434
|
+
}
|
|
9421
9435
|
}
|
|
9422
9436
|
}
|
|
9423
9437
|
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
|
@@ -844,6 +844,11 @@ interface LabelsOptions {
|
|
|
844
844
|
showIndicatorValues?: boolean;
|
|
845
845
|
showIndicatorValueLabels?: boolean;
|
|
846
846
|
indicatorLegendPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
847
|
+
/**
|
|
848
|
+
* Inset of the whole top-left block — the data line and the indicator
|
|
849
|
+
* legend stacked under it — from the plot edges. Both axes use the same
|
|
850
|
+
* pair so the block never sits closer to the top than to the side.
|
|
851
|
+
*/
|
|
847
852
|
indicatorLegendOffsetX?: number;
|
|
848
853
|
indicatorLegendOffsetY?: number;
|
|
849
854
|
showCountdownToBarClose?: boolean;
|
|
@@ -3551,8 +3551,10 @@ var DEFAULT_LABELS_OPTIONS = {
|
|
|
3551
3551
|
showIndicatorValues: false,
|
|
3552
3552
|
showIndicatorValueLabels: true,
|
|
3553
3553
|
indicatorLegendPosition: "top-left",
|
|
3554
|
-
|
|
3555
|
-
|
|
3554
|
+
// One inset for the whole top-left block (data line + legend), so the gap
|
|
3555
|
+
// from the left edge matches the gap from the top.
|
|
3556
|
+
indicatorLegendOffsetX: 12,
|
|
3557
|
+
indicatorLegendOffsetY: 12,
|
|
3556
3558
|
showCountdownToBarClose: false,
|
|
3557
3559
|
noOverlapping: true,
|
|
3558
3560
|
backgroundColor: "#0b1220",
|
|
@@ -6251,6 +6253,8 @@ function createChart(element, options = {}) {
|
|
|
6251
6253
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
6252
6254
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
6253
6255
|
const move = p1.price - p0.price;
|
|
6256
|
+
const lineLeft = Math.min(x0, x1, x2);
|
|
6257
|
+
const lineRight = Math.max(x0, x1, x2);
|
|
6254
6258
|
const levelLines = FIB_EXT_RATIOS.map((ratio) => {
|
|
6255
6259
|
const price = p2.price + move * ratio;
|
|
6256
6260
|
return { ratio, price, y: yFromPrice(price) };
|
|
@@ -6263,7 +6267,7 @@ function createChart(element, options = {}) {
|
|
|
6263
6267
|
ctx.save();
|
|
6264
6268
|
ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
|
|
6265
6269
|
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
6266
|
-
ctx.fillRect(
|
|
6270
|
+
ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
|
|
6267
6271
|
ctx.restore();
|
|
6268
6272
|
}
|
|
6269
6273
|
ctx.save();
|
|
@@ -6272,8 +6276,8 @@ function createChart(element, options = {}) {
|
|
|
6272
6276
|
levelLines.forEach((level, index) => {
|
|
6273
6277
|
ctx.strokeStyle = levelColorAt(index);
|
|
6274
6278
|
ctx.beginPath();
|
|
6275
|
-
ctx.moveTo(crisp(
|
|
6276
|
-
ctx.lineTo(crisp(
|
|
6279
|
+
ctx.moveTo(crisp(lineLeft), crisp(level.y));
|
|
6280
|
+
ctx.lineTo(crisp(lineRight), crisp(level.y));
|
|
6277
6281
|
ctx.stroke();
|
|
6278
6282
|
});
|
|
6279
6283
|
ctx.restore();
|
|
@@ -6283,7 +6287,7 @@ function createChart(element, options = {}) {
|
|
|
6283
6287
|
const labelText = `${level.ratio} (${formatPrice(level.price)})`;
|
|
6284
6288
|
const textWidth = measureTextWidth(labelText);
|
|
6285
6289
|
const padding = 4;
|
|
6286
|
-
const bgX = chartLeft + 4;
|
|
6290
|
+
const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
|
|
6287
6291
|
const bgY = level.y - 9;
|
|
6288
6292
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
6289
6293
|
fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
|
|
@@ -8228,6 +8232,8 @@ function createChart(element, options = {}) {
|
|
|
8228
8232
|
for (const orderLine of orderLines) {
|
|
8229
8233
|
drawOrderLine(orderLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
8230
8234
|
}
|
|
8235
|
+
const legendInsetX = Math.max(0, Number(labels.indicatorLegendOffsetX) || 0);
|
|
8236
|
+
const legendInsetY = Math.max(0, Number(labels.indicatorLegendOffsetY) || 0);
|
|
8231
8237
|
let dataLineBottom = chartTop;
|
|
8232
8238
|
const dataLine = mergedOptions.dataLine;
|
|
8233
8239
|
if (dataLine?.visible && data.length > 0) {
|
|
@@ -8244,8 +8250,8 @@ function createChart(element, options = {}) {
|
|
|
8244
8250
|
const textColor = dataLine.textColor || labels.indicatorTextColor;
|
|
8245
8251
|
const changeAbs = bar.c - bar.o;
|
|
8246
8252
|
const changeColor = changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor;
|
|
8247
|
-
const rowY = chartTop +
|
|
8248
|
-
let cursorX = chartLeft +
|
|
8253
|
+
const rowY = chartTop + legendInsetY;
|
|
8254
|
+
let cursorX = chartLeft + legendInsetX;
|
|
8249
8255
|
if (dataLine.statusColor) {
|
|
8250
8256
|
const dotRadius = Math.max(2.5, fontSize / 4);
|
|
8251
8257
|
ctx.fillStyle = dataLine.statusColor;
|
|
@@ -8291,7 +8297,7 @@ function createChart(element, options = {}) {
|
|
|
8291
8297
|
ctx.fillText(text, cursorX, rowY);
|
|
8292
8298
|
cursorX += width2 + 12;
|
|
8293
8299
|
}
|
|
8294
|
-
dataLineBottom = rowY + fontSize +
|
|
8300
|
+
dataLineBottom = rowY + fontSize + 6;
|
|
8295
8301
|
ctx.font = prevFont;
|
|
8296
8302
|
}
|
|
8297
8303
|
}
|
|
@@ -8321,8 +8327,8 @@ function createChart(element, options = {}) {
|
|
|
8321
8327
|
const prevFont = ctx.font;
|
|
8322
8328
|
const legendFontSize = Math.max(8, axis.fontSize);
|
|
8323
8329
|
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
8324
|
-
const offsetX =
|
|
8325
|
-
const offsetY =
|
|
8330
|
+
const offsetX = legendInsetX;
|
|
8331
|
+
const offsetY = legendInsetY;
|
|
8326
8332
|
const position = labels.indicatorLegendPosition;
|
|
8327
8333
|
const isRight = position === "top-right" || position === "bottom-right";
|
|
8328
8334
|
const isBottom = position === "bottom-left" || position === "bottom-right";
|
|
@@ -9347,12 +9353,16 @@ function createChart(element, options = {}) {
|
|
|
9347
9353
|
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
9348
9354
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
9349
9355
|
}
|
|
9350
|
-
const
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
const
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
+
const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
|
|
9357
|
+
const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
|
|
9358
|
+
if (x >= fibLeft && x <= fibRight) {
|
|
9359
|
+
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
9360
|
+
for (const ratio of fibRatios) {
|
|
9361
|
+
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
9362
|
+
const lineY = canvasYFromDrawingPrice(price);
|
|
9363
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9364
|
+
return { drawing, target: "line" };
|
|
9365
|
+
}
|
|
9356
9366
|
}
|
|
9357
9367
|
}
|
|
9358
9368
|
} else if (drawing.type === "fib-extension") {
|
|
@@ -9377,11 +9387,15 @@ function createChart(element, options = {}) {
|
|
|
9377
9387
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
9378
9388
|
}
|
|
9379
9389
|
const move = p1.price - p0.price;
|
|
9380
|
-
const
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9390
|
+
const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
|
|
9391
|
+
const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
|
|
9392
|
+
if (x >= extLeft && x <= extRight) {
|
|
9393
|
+
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
9394
|
+
for (const ratio of fibExtRatios) {
|
|
9395
|
+
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
9396
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9397
|
+
return { drawing, target: "line" };
|
|
9398
|
+
}
|
|
9385
9399
|
}
|
|
9386
9400
|
}
|
|
9387
9401
|
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
package/dist/index.cjs
CHANGED
|
@@ -3587,8 +3587,10 @@ var DEFAULT_LABELS_OPTIONS = {
|
|
|
3587
3587
|
showIndicatorValues: false,
|
|
3588
3588
|
showIndicatorValueLabels: true,
|
|
3589
3589
|
indicatorLegendPosition: "top-left",
|
|
3590
|
-
|
|
3591
|
-
|
|
3590
|
+
// One inset for the whole top-left block (data line + legend), so the gap
|
|
3591
|
+
// from the left edge matches the gap from the top.
|
|
3592
|
+
indicatorLegendOffsetX: 12,
|
|
3593
|
+
indicatorLegendOffsetY: 12,
|
|
3592
3594
|
showCountdownToBarClose: false,
|
|
3593
3595
|
noOverlapping: true,
|
|
3594
3596
|
backgroundColor: "#0b1220",
|
|
@@ -6287,6 +6289,8 @@ function createChart(element, options = {}) {
|
|
|
6287
6289
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
6288
6290
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
6289
6291
|
const move = p1.price - p0.price;
|
|
6292
|
+
const lineLeft = Math.min(x0, x1, x2);
|
|
6293
|
+
const lineRight = Math.max(x0, x1, x2);
|
|
6290
6294
|
const levelLines = FIB_EXT_RATIOS.map((ratio) => {
|
|
6291
6295
|
const price = p2.price + move * ratio;
|
|
6292
6296
|
return { ratio, price, y: yFromPrice(price) };
|
|
@@ -6299,7 +6303,7 @@ function createChart(element, options = {}) {
|
|
|
6299
6303
|
ctx.save();
|
|
6300
6304
|
ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
|
|
6301
6305
|
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
6302
|
-
ctx.fillRect(
|
|
6306
|
+
ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
|
|
6303
6307
|
ctx.restore();
|
|
6304
6308
|
}
|
|
6305
6309
|
ctx.save();
|
|
@@ -6308,8 +6312,8 @@ function createChart(element, options = {}) {
|
|
|
6308
6312
|
levelLines.forEach((level, index) => {
|
|
6309
6313
|
ctx.strokeStyle = levelColorAt(index);
|
|
6310
6314
|
ctx.beginPath();
|
|
6311
|
-
ctx.moveTo(crisp(
|
|
6312
|
-
ctx.lineTo(crisp(
|
|
6315
|
+
ctx.moveTo(crisp(lineLeft), crisp(level.y));
|
|
6316
|
+
ctx.lineTo(crisp(lineRight), crisp(level.y));
|
|
6313
6317
|
ctx.stroke();
|
|
6314
6318
|
});
|
|
6315
6319
|
ctx.restore();
|
|
@@ -6319,7 +6323,7 @@ function createChart(element, options = {}) {
|
|
|
6319
6323
|
const labelText = `${level.ratio} (${formatPrice(level.price)})`;
|
|
6320
6324
|
const textWidth = measureTextWidth(labelText);
|
|
6321
6325
|
const padding = 4;
|
|
6322
|
-
const bgX = chartLeft + 4;
|
|
6326
|
+
const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
|
|
6323
6327
|
const bgY = level.y - 9;
|
|
6324
6328
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
6325
6329
|
fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
|
|
@@ -8264,6 +8268,8 @@ function createChart(element, options = {}) {
|
|
|
8264
8268
|
for (const orderLine of orderLines) {
|
|
8265
8269
|
drawOrderLine(orderLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
8266
8270
|
}
|
|
8271
|
+
const legendInsetX = Math.max(0, Number(labels.indicatorLegendOffsetX) || 0);
|
|
8272
|
+
const legendInsetY = Math.max(0, Number(labels.indicatorLegendOffsetY) || 0);
|
|
8267
8273
|
let dataLineBottom = chartTop;
|
|
8268
8274
|
const dataLine = mergedOptions.dataLine;
|
|
8269
8275
|
if (dataLine?.visible && data.length > 0) {
|
|
@@ -8280,8 +8286,8 @@ function createChart(element, options = {}) {
|
|
|
8280
8286
|
const textColor = dataLine.textColor || labels.indicatorTextColor;
|
|
8281
8287
|
const changeAbs = bar.c - bar.o;
|
|
8282
8288
|
const changeColor = changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor;
|
|
8283
|
-
const rowY = chartTop +
|
|
8284
|
-
let cursorX = chartLeft +
|
|
8289
|
+
const rowY = chartTop + legendInsetY;
|
|
8290
|
+
let cursorX = chartLeft + legendInsetX;
|
|
8285
8291
|
if (dataLine.statusColor) {
|
|
8286
8292
|
const dotRadius = Math.max(2.5, fontSize / 4);
|
|
8287
8293
|
ctx.fillStyle = dataLine.statusColor;
|
|
@@ -8327,7 +8333,7 @@ function createChart(element, options = {}) {
|
|
|
8327
8333
|
ctx.fillText(text, cursorX, rowY);
|
|
8328
8334
|
cursorX += width2 + 12;
|
|
8329
8335
|
}
|
|
8330
|
-
dataLineBottom = rowY + fontSize +
|
|
8336
|
+
dataLineBottom = rowY + fontSize + 6;
|
|
8331
8337
|
ctx.font = prevFont;
|
|
8332
8338
|
}
|
|
8333
8339
|
}
|
|
@@ -8357,8 +8363,8 @@ function createChart(element, options = {}) {
|
|
|
8357
8363
|
const prevFont = ctx.font;
|
|
8358
8364
|
const legendFontSize = Math.max(8, axis.fontSize);
|
|
8359
8365
|
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
8360
|
-
const offsetX =
|
|
8361
|
-
const offsetY =
|
|
8366
|
+
const offsetX = legendInsetX;
|
|
8367
|
+
const offsetY = legendInsetY;
|
|
8362
8368
|
const position = labels.indicatorLegendPosition;
|
|
8363
8369
|
const isRight = position === "top-right" || position === "bottom-right";
|
|
8364
8370
|
const isBottom = position === "bottom-left" || position === "bottom-right";
|
|
@@ -9383,12 +9389,16 @@ function createChart(element, options = {}) {
|
|
|
9383
9389
|
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
9384
9390
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
9385
9391
|
}
|
|
9386
|
-
const
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
const
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
+
const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
|
|
9393
|
+
const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
|
|
9394
|
+
if (x >= fibLeft && x <= fibRight) {
|
|
9395
|
+
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
9396
|
+
for (const ratio of fibRatios) {
|
|
9397
|
+
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
9398
|
+
const lineY = canvasYFromDrawingPrice(price);
|
|
9399
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9400
|
+
return { drawing, target: "line" };
|
|
9401
|
+
}
|
|
9392
9402
|
}
|
|
9393
9403
|
}
|
|
9394
9404
|
} else if (drawing.type === "fib-extension") {
|
|
@@ -9413,11 +9423,15 @@ function createChart(element, options = {}) {
|
|
|
9413
9423
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
9414
9424
|
}
|
|
9415
9425
|
const move = p1.price - p0.price;
|
|
9416
|
-
const
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9426
|
+
const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
|
|
9427
|
+
const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
|
|
9428
|
+
if (x >= extLeft && x <= extRight) {
|
|
9429
|
+
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
9430
|
+
for (const ratio of fibExtRatios) {
|
|
9431
|
+
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
9432
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9433
|
+
return { drawing, target: "line" };
|
|
9434
|
+
}
|
|
9421
9435
|
}
|
|
9422
9436
|
}
|
|
9423
9437
|
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|
package/dist/index.d.cts
CHANGED
|
@@ -844,6 +844,11 @@ interface LabelsOptions {
|
|
|
844
844
|
showIndicatorValues?: boolean;
|
|
845
845
|
showIndicatorValueLabels?: boolean;
|
|
846
846
|
indicatorLegendPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
847
|
+
/**
|
|
848
|
+
* Inset of the whole top-left block — the data line and the indicator
|
|
849
|
+
* legend stacked under it — from the plot edges. Both axes use the same
|
|
850
|
+
* pair so the block never sits closer to the top than to the side.
|
|
851
|
+
*/
|
|
847
852
|
indicatorLegendOffsetX?: number;
|
|
848
853
|
indicatorLegendOffsetY?: number;
|
|
849
854
|
showCountdownToBarClose?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -844,6 +844,11 @@ interface LabelsOptions {
|
|
|
844
844
|
showIndicatorValues?: boolean;
|
|
845
845
|
showIndicatorValueLabels?: boolean;
|
|
846
846
|
indicatorLegendPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
847
|
+
/**
|
|
848
|
+
* Inset of the whole top-left block — the data line and the indicator
|
|
849
|
+
* legend stacked under it — from the plot edges. Both axes use the same
|
|
850
|
+
* pair so the block never sits closer to the top than to the side.
|
|
851
|
+
*/
|
|
847
852
|
indicatorLegendOffsetX?: number;
|
|
848
853
|
indicatorLegendOffsetY?: number;
|
|
849
854
|
showCountdownToBarClose?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -3551,8 +3551,10 @@ var DEFAULT_LABELS_OPTIONS = {
|
|
|
3551
3551
|
showIndicatorValues: false,
|
|
3552
3552
|
showIndicatorValueLabels: true,
|
|
3553
3553
|
indicatorLegendPosition: "top-left",
|
|
3554
|
-
|
|
3555
|
-
|
|
3554
|
+
// One inset for the whole top-left block (data line + legend), so the gap
|
|
3555
|
+
// from the left edge matches the gap from the top.
|
|
3556
|
+
indicatorLegendOffsetX: 12,
|
|
3557
|
+
indicatorLegendOffsetY: 12,
|
|
3556
3558
|
showCountdownToBarClose: false,
|
|
3557
3559
|
noOverlapping: true,
|
|
3558
3560
|
backgroundColor: "#0b1220",
|
|
@@ -6251,6 +6253,8 @@ function createChart(element, options = {}) {
|
|
|
6251
6253
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
6252
6254
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
6253
6255
|
const move = p1.price - p0.price;
|
|
6256
|
+
const lineLeft = Math.min(x0, x1, x2);
|
|
6257
|
+
const lineRight = Math.max(x0, x1, x2);
|
|
6254
6258
|
const levelLines = FIB_EXT_RATIOS.map((ratio) => {
|
|
6255
6259
|
const price = p2.price + move * ratio;
|
|
6256
6260
|
return { ratio, price, y: yFromPrice(price) };
|
|
@@ -6263,7 +6267,7 @@ function createChart(element, options = {}) {
|
|
|
6263
6267
|
ctx.save();
|
|
6264
6268
|
ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
|
|
6265
6269
|
ctx.globalAlpha = draft ? 0.5 : 1;
|
|
6266
|
-
ctx.fillRect(
|
|
6270
|
+
ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
|
|
6267
6271
|
ctx.restore();
|
|
6268
6272
|
}
|
|
6269
6273
|
ctx.save();
|
|
@@ -6272,8 +6276,8 @@ function createChart(element, options = {}) {
|
|
|
6272
6276
|
levelLines.forEach((level, index) => {
|
|
6273
6277
|
ctx.strokeStyle = levelColorAt(index);
|
|
6274
6278
|
ctx.beginPath();
|
|
6275
|
-
ctx.moveTo(crisp(
|
|
6276
|
-
ctx.lineTo(crisp(
|
|
6279
|
+
ctx.moveTo(crisp(lineLeft), crisp(level.y));
|
|
6280
|
+
ctx.lineTo(crisp(lineRight), crisp(level.y));
|
|
6277
6281
|
ctx.stroke();
|
|
6278
6282
|
});
|
|
6279
6283
|
ctx.restore();
|
|
@@ -6283,7 +6287,7 @@ function createChart(element, options = {}) {
|
|
|
6283
6287
|
const labelText = `${level.ratio} (${formatPrice(level.price)})`;
|
|
6284
6288
|
const textWidth = measureTextWidth(labelText);
|
|
6285
6289
|
const padding = 4;
|
|
6286
|
-
const bgX = chartLeft + 4;
|
|
6290
|
+
const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
|
|
6287
6291
|
const bgY = level.y - 9;
|
|
6288
6292
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
6289
6293
|
fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
|
|
@@ -8228,6 +8232,8 @@ function createChart(element, options = {}) {
|
|
|
8228
8232
|
for (const orderLine of orderLines) {
|
|
8229
8233
|
drawOrderLine(orderLine, yFromPrice, chartLeft, chartTop, chartRight, chartBottom);
|
|
8230
8234
|
}
|
|
8235
|
+
const legendInsetX = Math.max(0, Number(labels.indicatorLegendOffsetX) || 0);
|
|
8236
|
+
const legendInsetY = Math.max(0, Number(labels.indicatorLegendOffsetY) || 0);
|
|
8231
8237
|
let dataLineBottom = chartTop;
|
|
8232
8238
|
const dataLine = mergedOptions.dataLine;
|
|
8233
8239
|
if (dataLine?.visible && data.length > 0) {
|
|
@@ -8244,8 +8250,8 @@ function createChart(element, options = {}) {
|
|
|
8244
8250
|
const textColor = dataLine.textColor || labels.indicatorTextColor;
|
|
8245
8251
|
const changeAbs = bar.c - bar.o;
|
|
8246
8252
|
const changeColor = changeAbs >= 0 ? mergedOptions.upColor : mergedOptions.downColor;
|
|
8247
|
-
const rowY = chartTop +
|
|
8248
|
-
let cursorX = chartLeft +
|
|
8253
|
+
const rowY = chartTop + legendInsetY;
|
|
8254
|
+
let cursorX = chartLeft + legendInsetX;
|
|
8249
8255
|
if (dataLine.statusColor) {
|
|
8250
8256
|
const dotRadius = Math.max(2.5, fontSize / 4);
|
|
8251
8257
|
ctx.fillStyle = dataLine.statusColor;
|
|
@@ -8291,7 +8297,7 @@ function createChart(element, options = {}) {
|
|
|
8291
8297
|
ctx.fillText(text, cursorX, rowY);
|
|
8292
8298
|
cursorX += width2 + 12;
|
|
8293
8299
|
}
|
|
8294
|
-
dataLineBottom = rowY + fontSize +
|
|
8300
|
+
dataLineBottom = rowY + fontSize + 6;
|
|
8295
8301
|
ctx.font = prevFont;
|
|
8296
8302
|
}
|
|
8297
8303
|
}
|
|
@@ -8321,8 +8327,8 @@ function createChart(element, options = {}) {
|
|
|
8321
8327
|
const prevFont = ctx.font;
|
|
8322
8328
|
const legendFontSize = Math.max(8, axis.fontSize);
|
|
8323
8329
|
ctx.font = `${legendFontSize}px ${mergedOptions.fontFamily}`;
|
|
8324
|
-
const offsetX =
|
|
8325
|
-
const offsetY =
|
|
8330
|
+
const offsetX = legendInsetX;
|
|
8331
|
+
const offsetY = legendInsetY;
|
|
8326
8332
|
const position = labels.indicatorLegendPosition;
|
|
8327
8333
|
const isRight = position === "top-right" || position === "bottom-right";
|
|
8328
8334
|
const isBottom = position === "bottom-left" || position === "bottom-right";
|
|
@@ -9347,12 +9353,16 @@ function createChart(element, options = {}) {
|
|
|
9347
9353
|
if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
|
|
9348
9354
|
return { drawing, target: "handle", pointIndex: 1 };
|
|
9349
9355
|
}
|
|
9350
|
-
const
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
const
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
+
const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
|
|
9357
|
+
const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
|
|
9358
|
+
if (x >= fibLeft && x <= fibRight) {
|
|
9359
|
+
const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
|
|
9360
|
+
for (const ratio of fibRatios) {
|
|
9361
|
+
const price = first.price + (second.price - first.price) * (1 - ratio);
|
|
9362
|
+
const lineY = canvasYFromDrawingPrice(price);
|
|
9363
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9364
|
+
return { drawing, target: "line" };
|
|
9365
|
+
}
|
|
9356
9366
|
}
|
|
9357
9367
|
}
|
|
9358
9368
|
} else if (drawing.type === "fib-extension") {
|
|
@@ -9377,11 +9387,15 @@ function createChart(element, options = {}) {
|
|
|
9377
9387
|
return { drawing, target: "handle", pointIndex: 2 };
|
|
9378
9388
|
}
|
|
9379
9389
|
const move = p1.price - p0.price;
|
|
9380
|
-
const
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9390
|
+
const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
|
|
9391
|
+
const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
|
|
9392
|
+
if (x >= extLeft && x <= extRight) {
|
|
9393
|
+
const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
|
|
9394
|
+
for (const ratio of fibExtRatios) {
|
|
9395
|
+
const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
|
|
9396
|
+
if (Math.abs(y - lineY) <= 5 * hitTolerance) {
|
|
9397
|
+
return { drawing, target: "line" };
|
|
9398
|
+
}
|
|
9385
9399
|
}
|
|
9386
9400
|
}
|
|
9387
9401
|
if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
|