hyperprop-charting-library 0.1.66 → 0.1.68
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 +199 -36
- package/dist/hyperprop-charting-library.d.ts +4 -1
- package/dist/hyperprop-charting-library.js +199 -36
- package/dist/index.cjs +199 -36
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +199 -36
- package/docs/API.md +13 -3
- package/docs/RECIPES.md +21 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -102,7 +102,8 @@ var DEFAULT_PRICE_LINE_OPTIONS = {
|
|
|
102
102
|
labelBackgroundColor: "#0b1220",
|
|
103
103
|
labelTextColor: "#60a5fa",
|
|
104
104
|
labelBorderRadius: 3,
|
|
105
|
-
showLabel: true
|
|
105
|
+
showLabel: true,
|
|
106
|
+
pinOutOfRange: false
|
|
106
107
|
};
|
|
107
108
|
var DEFAULT_ORDER_LINE_OPTIONS = {
|
|
108
109
|
visible: true,
|
|
@@ -136,7 +137,8 @@ var DEFAULT_ORDER_LINE_OPTIONS = {
|
|
|
136
137
|
connectorThickness: 1,
|
|
137
138
|
connectorAnchorPaddingRight: 10,
|
|
138
139
|
fillToPrice: Number.NaN,
|
|
139
|
-
fillColor: "rgba(37,99,235,0.18)"
|
|
140
|
+
fillColor: "rgba(37,99,235,0.18)",
|
|
141
|
+
pinOutOfRange: false
|
|
140
142
|
};
|
|
141
143
|
var DEFAULT_OPTIONS = {
|
|
142
144
|
width: 720,
|
|
@@ -169,6 +171,7 @@ var DEFAULT_OPTIONS = {
|
|
|
169
171
|
candleColorEpsilon: -1,
|
|
170
172
|
autoScaleSmoothing: 0.16,
|
|
171
173
|
autoScaleIgnoreLatestCandle: true,
|
|
174
|
+
pinOutOfRangeLines: false,
|
|
172
175
|
doubleClickEnabled: true,
|
|
173
176
|
doubleClickAction: "reset",
|
|
174
177
|
crosshair: DEFAULT_CROSSHAIR_OPTIONS,
|
|
@@ -1477,12 +1480,27 @@ function createChart(element, options = {}) {
|
|
|
1477
1480
|
const scaleWidth = Math.max(0, Math.floor(width - getRightAxisLabelX(chartRight)));
|
|
1478
1481
|
return Math.max(contentWidth, scaleWidth);
|
|
1479
1482
|
};
|
|
1483
|
+
const getLineY = (price, yFromPrice, chartTop, chartBottom, pinOutOfRange = mergedOptions.pinOutOfRangeLines) => {
|
|
1484
|
+
const y = yFromPrice(price);
|
|
1485
|
+
if (!Number.isFinite(y)) {
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
const minY = chartTop + 1;
|
|
1489
|
+
const maxY = chartBottom - 1;
|
|
1490
|
+
if (y < minY || y > maxY) {
|
|
1491
|
+
return pinOutOfRange ? clamp(y, minY, maxY) : null;
|
|
1492
|
+
}
|
|
1493
|
+
return y;
|
|
1494
|
+
};
|
|
1480
1495
|
const drawPriceLine = (line, yFromPrice, chartLeft, chartTop, chartRight, chartBottom) => {
|
|
1481
1496
|
const mergedLine = { ...DEFAULT_PRICE_LINE_OPTIONS, ...line };
|
|
1482
1497
|
if (!mergedLine.visible || !Number.isFinite(mergedLine.price)) {
|
|
1483
1498
|
return;
|
|
1484
1499
|
}
|
|
1485
|
-
const lineY =
|
|
1500
|
+
const lineY = getLineY(mergedLine.price, yFromPrice, chartTop, chartBottom, mergedLine.pinOutOfRange);
|
|
1501
|
+
if (lineY === null) {
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1486
1504
|
const color = mergedLine.color;
|
|
1487
1505
|
ctx.save();
|
|
1488
1506
|
ctx.strokeStyle = color;
|
|
@@ -1528,10 +1546,16 @@ function createChart(element, options = {}) {
|
|
|
1528
1546
|
if (!mergedLine.visible || !Number.isFinite(renderPrice)) {
|
|
1529
1547
|
return;
|
|
1530
1548
|
}
|
|
1531
|
-
const lineY =
|
|
1549
|
+
const lineY = getLineY(renderPrice, yFromPrice, chartTop, chartBottom, mergedLine.pinOutOfRange);
|
|
1550
|
+
if (lineY === null) {
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1532
1553
|
const color = line.color ?? (mergedLine.type === "takeProfit" ? "rgba(45,212,191,0.86)" : mergedLine.type === "stop" ? "rgba(245,158,11,0.86)" : "rgba(59,130,246,0.8)");
|
|
1533
1554
|
if (Number.isFinite(mergedLine.fillToPrice)) {
|
|
1534
|
-
const fillY =
|
|
1555
|
+
const fillY = getLineY(mergedLine.fillToPrice, yFromPrice, chartTop, chartBottom, true);
|
|
1556
|
+
if (fillY === null) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1535
1559
|
const topY = Math.min(lineY, fillY);
|
|
1536
1560
|
const heightY = Math.max(1, Math.abs(lineY - fillY));
|
|
1537
1561
|
ctx.save();
|
|
@@ -1549,21 +1573,29 @@ function createChart(element, options = {}) {
|
|
|
1549
1573
|
ctx.stroke();
|
|
1550
1574
|
ctx.restore();
|
|
1551
1575
|
if (Number.isFinite(mergedLine.connectorToPrice)) {
|
|
1552
|
-
const connectorY =
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
mergedLine.connectorStyle,
|
|
1559
|
-
dashPatterns.connectorDotted,
|
|
1560
|
-
dashPatterns.connectorDashed
|
|
1576
|
+
const connectorY = getLineY(
|
|
1577
|
+
mergedLine.connectorToPrice,
|
|
1578
|
+
yFromPrice,
|
|
1579
|
+
chartTop,
|
|
1580
|
+
chartBottom,
|
|
1581
|
+
mergedLine.pinOutOfRange
|
|
1561
1582
|
);
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1583
|
+
if (connectorY !== null) {
|
|
1584
|
+
const connectorX = chartRight - Math.max(6, mergedLine.connectorAnchorPaddingRight);
|
|
1585
|
+
ctx.save();
|
|
1586
|
+
ctx.strokeStyle = mergedLine.connectorColor ?? color;
|
|
1587
|
+
ctx.lineWidth = Math.max(1, mergedLine.connectorThickness);
|
|
1588
|
+
applyDashPattern(
|
|
1589
|
+
mergedLine.connectorStyle,
|
|
1590
|
+
dashPatterns.connectorDotted,
|
|
1591
|
+
dashPatterns.connectorDashed
|
|
1592
|
+
);
|
|
1593
|
+
ctx.beginPath();
|
|
1594
|
+
ctx.moveTo(crisp(connectorX), crisp(lineY));
|
|
1595
|
+
ctx.lineTo(crisp(connectorX), crisp(connectorY));
|
|
1596
|
+
ctx.stroke();
|
|
1597
|
+
ctx.restore();
|
|
1598
|
+
}
|
|
1567
1599
|
}
|
|
1568
1600
|
const qtyText = mergedLine.qty === void 0 ? "" : String(mergedLine.qty);
|
|
1569
1601
|
const typeTextMap = {
|
|
@@ -2096,7 +2128,11 @@ function createChart(element, options = {}) {
|
|
|
2096
2128
|
if (drawing.type === "horizontal-line") {
|
|
2097
2129
|
const point = drawing.points[0];
|
|
2098
2130
|
if (point) {
|
|
2099
|
-
const y =
|
|
2131
|
+
const y = getLineY(point.price, yFromPrice, chartTop, chartBottom);
|
|
2132
|
+
if (y === null) {
|
|
2133
|
+
ctx.restore();
|
|
2134
|
+
return;
|
|
2135
|
+
}
|
|
2100
2136
|
const handleX = chartRight - 64;
|
|
2101
2137
|
ctx.beginPath();
|
|
2102
2138
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
@@ -2108,6 +2144,20 @@ function createChart(element, options = {}) {
|
|
|
2108
2144
|
drawDrawingLabel(drawing.label, midX, y, drawing.color);
|
|
2109
2145
|
}
|
|
2110
2146
|
}
|
|
2147
|
+
} else if (drawing.type === "vertical-line") {
|
|
2148
|
+
const point = drawing.points[0];
|
|
2149
|
+
if (point) {
|
|
2150
|
+
const x = xFromDrawingPoint(point);
|
|
2151
|
+
ctx.beginPath();
|
|
2152
|
+
ctx.moveTo(crisp(x), crisp(chartTop));
|
|
2153
|
+
ctx.lineTo(crisp(x), crisp(chartBottom));
|
|
2154
|
+
ctx.stroke();
|
|
2155
|
+
const handleY = (chartTop + chartBottom) / 2;
|
|
2156
|
+
drawDrawingHandle(x, handleY, drawing.color);
|
|
2157
|
+
if (drawing.label) {
|
|
2158
|
+
drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2111
2161
|
} else if (drawing.type === "trendline") {
|
|
2112
2162
|
const first = drawing.points[0];
|
|
2113
2163
|
const second = drawing.points[1];
|
|
@@ -2128,6 +2178,36 @@ function createChart(element, options = {}) {
|
|
|
2128
2178
|
drawDrawingLabel(drawing.label, midX, midY, drawing.color);
|
|
2129
2179
|
}
|
|
2130
2180
|
}
|
|
2181
|
+
} else if (drawing.type === "ray") {
|
|
2182
|
+
const first = drawing.points[0];
|
|
2183
|
+
const second = drawing.points[1];
|
|
2184
|
+
if (first && second) {
|
|
2185
|
+
const firstX = xFromDrawingPoint(first);
|
|
2186
|
+
const firstY = yFromPrice(first.price);
|
|
2187
|
+
const secondX = xFromDrawingPoint(second);
|
|
2188
|
+
const secondY = yFromPrice(second.price);
|
|
2189
|
+
const dx = secondX - firstX;
|
|
2190
|
+
const dy = secondY - firstY;
|
|
2191
|
+
let endX = secondX;
|
|
2192
|
+
let endY = secondY;
|
|
2193
|
+
const len = Math.hypot(dx, dy);
|
|
2194
|
+
if (len > 0) {
|
|
2195
|
+
const far = Math.abs(chartRight - chartLeft) + Math.abs(chartBottom - chartTop) + 2e3;
|
|
2196
|
+
endX = firstX + dx / len * far;
|
|
2197
|
+
endY = firstY + dy / len * far;
|
|
2198
|
+
}
|
|
2199
|
+
ctx.beginPath();
|
|
2200
|
+
ctx.moveTo(firstX, firstY);
|
|
2201
|
+
ctx.lineTo(endX, endY);
|
|
2202
|
+
ctx.stroke();
|
|
2203
|
+
drawDrawingHandle(firstX, firstY, drawing.color);
|
|
2204
|
+
drawDrawingHandle(secondX, secondY, drawing.color);
|
|
2205
|
+
if (drawing.label) {
|
|
2206
|
+
const midX = (firstX + secondX) / 2;
|
|
2207
|
+
const midY = (firstY + secondY) / 2;
|
|
2208
|
+
drawDrawingLabel(drawing.label, midX, midY, drawing.color);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2131
2211
|
} else if (drawing.type === "fib-retracement") {
|
|
2132
2212
|
const first = drawing.points[0];
|
|
2133
2213
|
const second = drawing.points[1];
|
|
@@ -2536,13 +2616,19 @@ function createChart(element, options = {}) {
|
|
|
2536
2616
|
if (!labels.visible || !Number.isFinite(label.price) || label.text.length === 0) {
|
|
2537
2617
|
return;
|
|
2538
2618
|
}
|
|
2619
|
+
if (getLineY(label.price, yFromPrice, chartTop, chartBottom, label.pinOutOfRange) === null) {
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2539
2622
|
priceAxisLabels.push(label);
|
|
2540
2623
|
};
|
|
2541
|
-
const drawReferenceLine = (price, color, style = "dotted") => {
|
|
2624
|
+
const drawReferenceLine = (price, color, style = "dotted", pinOutOfRange = mergedOptions.pinOutOfRangeLines) => {
|
|
2542
2625
|
if (!Number.isFinite(price)) {
|
|
2543
2626
|
return;
|
|
2544
2627
|
}
|
|
2545
|
-
const y =
|
|
2628
|
+
const y = getLineY(price, yFromPrice, chartTop, chartBottom, pinOutOfRange);
|
|
2629
|
+
if (y === null) {
|
|
2630
|
+
return;
|
|
2631
|
+
}
|
|
2546
2632
|
ctx.save();
|
|
2547
2633
|
ctx.strokeStyle = color;
|
|
2548
2634
|
ctx.lineWidth = 1;
|
|
@@ -2569,22 +2655,23 @@ function createChart(element, options = {}) {
|
|
|
2569
2655
|
let tickerColor = null;
|
|
2570
2656
|
if ((ticker.visible ?? true) && lastPoint) {
|
|
2571
2657
|
tickerPrice = ticker.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice : lastPoint.c;
|
|
2572
|
-
const
|
|
2573
|
-
const lineY = clamp(tickerY, chartTop + 1, chartBottom - 1);
|
|
2658
|
+
const lineY = getLineY(tickerPrice, yFromPrice, chartTop, chartBottom);
|
|
2574
2659
|
const lastDirection = ticker.smoothing && smoothedTickerPrice !== null ? smoothedTickerPrice >= lastPoint.o ? "up" : "down" : getCandleDirectionByIndex(data.length - 1);
|
|
2575
2660
|
tickerColor = ticker.color ?? (lastDirection === "up" ? mergedOptions.upColor : mergedOptions.downColor);
|
|
2576
2661
|
const tickerThickness = Math.max(1, ticker.thickness ?? 1);
|
|
2577
2662
|
const tickerStyle = ticker.style ?? "solid";
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2663
|
+
if (lineY !== null) {
|
|
2664
|
+
ctx.save();
|
|
2665
|
+
ctx.strokeStyle = tickerColor;
|
|
2666
|
+
ctx.lineWidth = tickerThickness;
|
|
2667
|
+
applyDashPattern(tickerStyle, dashPatterns.dotted, dashPatterns.dashed);
|
|
2668
|
+
ctx.beginPath();
|
|
2669
|
+
ctx.moveTo(crisp(chartLeft), crisp(lineY));
|
|
2670
|
+
ctx.lineTo(crisp(chartRight), crisp(lineY));
|
|
2671
|
+
ctx.stroke();
|
|
2672
|
+
ctx.setLineDash([]);
|
|
2673
|
+
ctx.restore();
|
|
2674
|
+
}
|
|
2588
2675
|
}
|
|
2589
2676
|
if ((ticker.visible ?? true) && labels.showLastPrice && tickerPrice !== null && tickerColor !== null) {
|
|
2590
2677
|
const tickerSubtexts = [
|
|
@@ -2694,13 +2781,14 @@ function createChart(element, options = {}) {
|
|
|
2694
2781
|
}
|
|
2695
2782
|
const labelTextWidth = Math.max(primaryWidth, subtextWidth);
|
|
2696
2783
|
const labelWidth = getRightAxisLabelWidth(chartRight, labelTextWidth);
|
|
2784
|
+
const labelLineY = getLineY(label.price, yFromPrice, chartTop, chartBottom, label.pinOutOfRange);
|
|
2697
2785
|
return {
|
|
2698
2786
|
...label,
|
|
2699
2787
|
subtexts,
|
|
2700
2788
|
subtextFontSize,
|
|
2701
2789
|
height: labelHeight,
|
|
2702
2790
|
width: labelWidth,
|
|
2703
|
-
targetY:
|
|
2791
|
+
targetY: (labelLineY ?? yFromPrice(label.price)) - labelHeight / 2,
|
|
2704
2792
|
y: 0
|
|
2705
2793
|
};
|
|
2706
2794
|
}).sort((a, b) => a.targetY - b.targetY || b.priority - a.priority);
|
|
@@ -3262,6 +3350,17 @@ function createChart(element, options = {}) {
|
|
|
3262
3350
|
if (Math.abs(y - lineY) <= 7) {
|
|
3263
3351
|
return { drawing, target: "line" };
|
|
3264
3352
|
}
|
|
3353
|
+
} else if (drawing.type === "vertical-line") {
|
|
3354
|
+
const point = drawing.points[0];
|
|
3355
|
+
if (!point) continue;
|
|
3356
|
+
const lineX = canvasXFromDrawingPoint(point);
|
|
3357
|
+
const handleY = drawState ? (drawState.chartTop + drawState.chartBottom) / 2 : 0;
|
|
3358
|
+
if (Math.hypot(x - lineX, y - handleY) <= 8) {
|
|
3359
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3360
|
+
}
|
|
3361
|
+
if (Math.abs(x - lineX) <= 7) {
|
|
3362
|
+
return { drawing, target: "line" };
|
|
3363
|
+
}
|
|
3265
3364
|
} else if (drawing.type === "trendline") {
|
|
3266
3365
|
const first = drawing.points[0];
|
|
3267
3366
|
const second = drawing.points[1];
|
|
@@ -3279,6 +3378,31 @@ function createChart(element, options = {}) {
|
|
|
3279
3378
|
if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
|
|
3280
3379
|
return { drawing, target: "line" };
|
|
3281
3380
|
}
|
|
3381
|
+
} else if (drawing.type === "ray") {
|
|
3382
|
+
const first = drawing.points[0];
|
|
3383
|
+
const second = drawing.points[1];
|
|
3384
|
+
if (!first || !second) continue;
|
|
3385
|
+
const x1 = canvasXFromDrawingPoint(first);
|
|
3386
|
+
const y1 = canvasYFromDrawingPrice(first.price);
|
|
3387
|
+
const x2 = canvasXFromDrawingPoint(second);
|
|
3388
|
+
const y2 = canvasYFromDrawingPrice(second.price);
|
|
3389
|
+
if (Math.hypot(x - x1, y - y1) <= 8) {
|
|
3390
|
+
return { drawing, target: "handle", pointIndex: 0 };
|
|
3391
|
+
}
|
|
3392
|
+
if (Math.hypot(x - x2, y - y2) <= 8) {
|
|
3393
|
+
return { drawing, target: "handle", pointIndex: 1 };
|
|
3394
|
+
}
|
|
3395
|
+
const dx = x2 - x1;
|
|
3396
|
+
const dy = y2 - y1;
|
|
3397
|
+
const lengthSq = dx * dx + dy * dy;
|
|
3398
|
+
if (lengthSq > 0) {
|
|
3399
|
+
const t = Math.max(0, ((x - x1) * dx + (y - y1) * dy) / lengthSq);
|
|
3400
|
+
const projX = x1 + t * dx;
|
|
3401
|
+
const projY = y1 + t * dy;
|
|
3402
|
+
if (Math.hypot(x - projX, y - projY) <= 6) {
|
|
3403
|
+
return { drawing, target: "line" };
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3282
3406
|
} else if (drawing.type === "fib-retracement") {
|
|
3283
3407
|
const first = drawing.points[0];
|
|
3284
3408
|
const second = drawing.points[1];
|
|
@@ -3380,6 +3504,21 @@ function createChart(element, options = {}) {
|
|
|
3380
3504
|
draw();
|
|
3381
3505
|
return true;
|
|
3382
3506
|
}
|
|
3507
|
+
if (activeDrawingTool === "vertical-line") {
|
|
3508
|
+
const defaults = getDrawingToolDefaults("vertical-line");
|
|
3509
|
+
drawings.push(
|
|
3510
|
+
normalizeDrawingState({
|
|
3511
|
+
type: "vertical-line",
|
|
3512
|
+
points: [point],
|
|
3513
|
+
color: defaults.color ?? "#38bdf8",
|
|
3514
|
+
style: defaults.style ?? "solid",
|
|
3515
|
+
width: defaults.width ?? 1
|
|
3516
|
+
})
|
|
3517
|
+
);
|
|
3518
|
+
emitDrawingsChange();
|
|
3519
|
+
draw();
|
|
3520
|
+
return true;
|
|
3521
|
+
}
|
|
3383
3522
|
if (activeDrawingTool === "trendline") {
|
|
3384
3523
|
if (draftDrawing?.type === "trendline") {
|
|
3385
3524
|
const completed = normalizeDrawingState({
|
|
@@ -3404,6 +3543,30 @@ function createChart(element, options = {}) {
|
|
|
3404
3543
|
draw();
|
|
3405
3544
|
return true;
|
|
3406
3545
|
}
|
|
3546
|
+
if (activeDrawingTool === "ray") {
|
|
3547
|
+
if (draftDrawing?.type === "ray") {
|
|
3548
|
+
const completed = normalizeDrawingState({
|
|
3549
|
+
...serializeDrawing(draftDrawing),
|
|
3550
|
+
points: [draftDrawing.points[0], point]
|
|
3551
|
+
});
|
|
3552
|
+
drawings.push(completed);
|
|
3553
|
+
draftDrawing = null;
|
|
3554
|
+
activeDrawingTool = null;
|
|
3555
|
+
emitDrawingsChange();
|
|
3556
|
+
draw();
|
|
3557
|
+
return true;
|
|
3558
|
+
}
|
|
3559
|
+
const defaults = getDrawingToolDefaults("ray");
|
|
3560
|
+
draftDrawing = normalizeDrawingState({
|
|
3561
|
+
type: "ray",
|
|
3562
|
+
points: [point, point],
|
|
3563
|
+
color: defaults.color ?? "#2563eb",
|
|
3564
|
+
style: defaults.style ?? "solid",
|
|
3565
|
+
width: defaults.width ?? 2
|
|
3566
|
+
});
|
|
3567
|
+
draw();
|
|
3568
|
+
return true;
|
|
3569
|
+
}
|
|
3407
3570
|
if (activeDrawingTool === "fib-retracement") {
|
|
3408
3571
|
if (draftDrawing?.type === "fib-retracement") {
|
|
3409
3572
|
const completed = normalizeDrawingState({
|
|
@@ -3700,7 +3863,7 @@ function createChart(element, options = {}) {
|
|
|
3700
3863
|
setCrosshairPoint(null);
|
|
3701
3864
|
return;
|
|
3702
3865
|
}
|
|
3703
|
-
if (draftDrawing && (activeDrawingTool === "trendline" || activeDrawingTool === "fib-retracement")) {
|
|
3866
|
+
if (draftDrawing && (activeDrawingTool === "trendline" || activeDrawingTool === "ray" || activeDrawingTool === "fib-retracement")) {
|
|
3704
3867
|
const nextPoint = drawingPointFromCanvas(point.x, point.y);
|
|
3705
3868
|
if (nextPoint) {
|
|
3706
3869
|
draftDrawing = {
|
package/docs/API.md
CHANGED
|
@@ -57,6 +57,7 @@ Top-level options:
|
|
|
57
57
|
- `candleColorEpsilon` (default `-1` = auto from `priceDecimals`; set `0` to disable tolerance)
|
|
58
58
|
- `autoScaleSmoothing` (default `0.16`)
|
|
59
59
|
- `autoScaleIgnoreLatestCandle` (default `true`)
|
|
60
|
+
- `pinOutOfRangeLines` (default `false`; when `true`, horizontal price/order/reference lines outside the visible price range are pinned to the top/bottom chart edge)
|
|
60
61
|
- `doubleClickEnabled` (default `true`)
|
|
61
62
|
- `doubleClickAction` (`"reset"` | `"placeLimitOrder"`, default `"reset"`)
|
|
62
63
|
- `crosshair?: CrosshairOptions`
|
|
@@ -226,6 +227,7 @@ createChart(root, {
|
|
|
226
227
|
- `labelTextColor` (default `#0f172a`)
|
|
227
228
|
- `labelBorderRadius` (default `3`)
|
|
228
229
|
- `showLabel` (default `true`)
|
|
230
|
+
- `pinOutOfRange?: boolean` (default `false`; overrides `ChartOptions.pinOutOfRangeLines` for this line)
|
|
229
231
|
|
|
230
232
|
### `OrderActionButton`
|
|
231
233
|
|
|
@@ -269,6 +271,7 @@ Common optional fields:
|
|
|
269
271
|
- `widgetPosition?: "left" | "center" | "right"` (default `"left"`)
|
|
270
272
|
- `widgetPaddingRight?: number` (default `10`, extra right margin when `widgetPosition` is `"right"`)
|
|
271
273
|
- `draggable?: boolean` (default `false`)
|
|
274
|
+
- `pinOutOfRange?: boolean` (default `false`; overrides `ChartOptions.pinOutOfRangeLines` for this order/position line)
|
|
272
275
|
|
|
273
276
|
Legacy single action button:
|
|
274
277
|
|
|
@@ -411,7 +414,11 @@ Volume style inputs:
|
|
|
411
414
|
Drawings are user-created chart tools, separate from indicators. They are interactive chart objects like horizontal lines and trendlines.
|
|
412
415
|
|
|
413
416
|
- `id?: string`
|
|
414
|
-
- `type: "horizontal-line" | "trendline"`
|
|
417
|
+
- `type: "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`
|
|
418
|
+
- `horizontal-line` / `vertical-line`: single-point, full-width/full-height line (one click to place)
|
|
419
|
+
- `trendline`: two-point segment (click start, click end)
|
|
420
|
+
- `ray`: two-point line that extends infinitely past the second point
|
|
421
|
+
- `fib-retracement`: two-point retracement with levels/bands
|
|
415
422
|
- `points: DrawingPoint[]`
|
|
416
423
|
- `visible?: boolean`
|
|
417
424
|
- `color?: string`
|
|
@@ -433,7 +440,10 @@ Tool workflow:
|
|
|
433
440
|
|
|
434
441
|
```ts
|
|
435
442
|
chart.setActiveDrawingTool("horizontal-line"); // next plot click creates a line
|
|
443
|
+
chart.setActiveDrawingTool("vertical-line"); // next plot click creates a vertical line
|
|
436
444
|
chart.setActiveDrawingTool("trendline"); // first click starts, second click commits
|
|
445
|
+
chart.setActiveDrawingTool("ray"); // first click starts, second click commits (extends past p2)
|
|
446
|
+
chart.setActiveDrawingTool("fib-retracement"); // first click starts, second click commits
|
|
437
447
|
chart.setActiveDrawingTool(null); // back to normal cursor/pan
|
|
438
448
|
```
|
|
439
449
|
|
|
@@ -463,8 +473,8 @@ Use `getDrawings()` / `setDrawings()` for persistence.
|
|
|
463
473
|
- `panY(priceDelta: number): void` (positive = move viewport up)
|
|
464
474
|
- `fitContent(): void` (x-only fit, keeps y zoom)
|
|
465
475
|
- `resetViewport(): void` (fit x + reset y auto-scale)
|
|
466
|
-
- `setActiveDrawingTool(tool: "horizontal-line" | "trendline" |
|
|
467
|
-
- `getActiveDrawingTool():
|
|
476
|
+
- `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`)
|
|
477
|
+
- `getActiveDrawingTool(): DrawingToolType | null`
|
|
468
478
|
- `setDrawings(drawings: DrawingObjectOptions[]): void`
|
|
469
479
|
- `getDrawings(): DrawingObjectOptions[]`
|
|
470
480
|
- `addDrawing(drawing: DrawingObjectOptions): string`
|
package/docs/RECIPES.md
CHANGED
|
@@ -85,16 +85,35 @@ chart.addPriceLine({
|
|
|
85
85
|
});
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
## Pin out-of-range lines to the chart edge
|
|
89
|
+
|
|
90
|
+
By default, horizontal price/order/drawing lines outside the visible price range are hidden instead of being pinned to the top or bottom edge. Opt in globally or per line when you want marker-style behavior for important levels.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const chart = createChart(rootEl, {
|
|
94
|
+
pinOutOfRangeLines: true
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
chart.addPriceLine({
|
|
98
|
+
price: 6400,
|
|
99
|
+
label: "Liquidation",
|
|
100
|
+
pinOutOfRange: true
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
88
104
|
## Add chart drawing tools
|
|
89
105
|
|
|
90
106
|
Drawing tools are separate from indicators. Indicators compute/render data series; drawings are user-created objects that can be persisted.
|
|
91
107
|
|
|
92
108
|
```ts
|
|
93
|
-
//
|
|
109
|
+
// Single-click tools: the next plot click creates the drawing.
|
|
94
110
|
chart.setActiveDrawingTool("horizontal-line");
|
|
111
|
+
chart.setActiveDrawingTool("vertical-line");
|
|
95
112
|
|
|
96
|
-
//
|
|
113
|
+
// Two-click tools: first click starts, second click commits.
|
|
97
114
|
chart.setActiveDrawingTool("trendline");
|
|
115
|
+
chart.setActiveDrawingTool("ray"); // extends infinitely past the second point
|
|
116
|
+
chart.setActiveDrawingTool("fib-retracement");
|
|
98
117
|
|
|
99
118
|
// Back to normal cursor/pan mode.
|
|
100
119
|
chart.setActiveDrawingTool(null);
|