hyperprop-charting-library 0.1.72 → 0.1.74
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 +96 -71
- package/dist/hyperprop-charting-library.d.ts +4 -1
- package/dist/hyperprop-charting-library.js +95 -71
- package/dist/index.cjs +96 -71
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +95 -71
- package/docs/API.md +2 -1
- package/package.json +1 -1
|
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
|
|
24
|
+
POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
|
|
24
25
|
createChart: () => createChart
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
|
|
27
29
|
var FIB_DEFAULT_PALETTE = [
|
|
28
30
|
"#787b86",
|
|
29
31
|
"#f23645",
|
|
@@ -982,6 +984,7 @@ function createChart(element, options = {}) {
|
|
|
982
984
|
let drawingSelectHandler = null;
|
|
983
985
|
let drawingHoverHandler = null;
|
|
984
986
|
let lastHoveredDrawingId = null;
|
|
987
|
+
let selectedDrawingId = null;
|
|
985
988
|
const drawingToolDefaults = /* @__PURE__ */ new Map();
|
|
986
989
|
const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
|
|
987
990
|
const emitDrawingsChange = () => {
|
|
@@ -2160,6 +2163,12 @@ function createChart(element, options = {}) {
|
|
|
2160
2163
|
if (!drawing.visible) {
|
|
2161
2164
|
return;
|
|
2162
2165
|
}
|
|
2166
|
+
const isSelected = draft || drawing.id === selectedDrawingId;
|
|
2167
|
+
const handleAt = (hx, hy, _color) => {
|
|
2168
|
+
if (isSelected) {
|
|
2169
|
+
drawDrawingHandle(hx, hy, drawing.color);
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2163
2172
|
ctx.save();
|
|
2164
2173
|
ctx.strokeStyle = drawing.color;
|
|
2165
2174
|
ctx.lineWidth = drawing.width;
|
|
@@ -2178,7 +2187,7 @@ function createChart(element, options = {}) {
|
|
|
2178
2187
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2179
2188
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2180
2189
|
ctx.stroke();
|
|
2181
|
-
|
|
2190
|
+
handleAt(handleX, y, drawing.color);
|
|
2182
2191
|
if (drawing.label) {
|
|
2183
2192
|
const midX = (chartLeft + chartRight) / 2;
|
|
2184
2193
|
drawDrawingLabel(drawing.label, midX, y, drawing.color);
|
|
@@ -2193,7 +2202,7 @@ function createChart(element, options = {}) {
|
|
|
2193
2202
|
ctx.lineTo(crisp(x), crisp(chartBottom));
|
|
2194
2203
|
ctx.stroke();
|
|
2195
2204
|
const handleY = (chartTop + chartBottom) / 2;
|
|
2196
|
-
|
|
2205
|
+
handleAt(x, handleY, drawing.color);
|
|
2197
2206
|
if (drawing.label) {
|
|
2198
2207
|
drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
|
|
2199
2208
|
}
|
|
@@ -2210,8 +2219,8 @@ function createChart(element, options = {}) {
|
|
|
2210
2219
|
ctx.moveTo(firstX, firstY);
|
|
2211
2220
|
ctx.lineTo(secondX, secondY);
|
|
2212
2221
|
ctx.stroke();
|
|
2213
|
-
|
|
2214
|
-
|
|
2222
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2223
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2215
2224
|
if (drawing.label) {
|
|
2216
2225
|
const midX = (firstX + secondX) / 2;
|
|
2217
2226
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2240,8 +2249,8 @@ function createChart(element, options = {}) {
|
|
|
2240
2249
|
ctx.moveTo(firstX, firstY);
|
|
2241
2250
|
ctx.lineTo(endX, endY);
|
|
2242
2251
|
ctx.stroke();
|
|
2243
|
-
|
|
2244
|
-
|
|
2252
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2253
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2245
2254
|
if (drawing.label) {
|
|
2246
2255
|
const midX = (firstX + secondX) / 2;
|
|
2247
2256
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2295,8 +2304,8 @@ function createChart(element, options = {}) {
|
|
|
2295
2304
|
ctx.lineTo(secondX, secondY);
|
|
2296
2305
|
ctx.stroke();
|
|
2297
2306
|
ctx.restore();
|
|
2298
|
-
|
|
2299
|
-
|
|
2307
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2308
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2300
2309
|
const prevFont = ctx.font;
|
|
2301
2310
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2302
2311
|
levelLines.forEach((level, index) => {
|
|
@@ -2335,12 +2344,12 @@ function createChart(element, options = {}) {
|
|
|
2335
2344
|
}
|
|
2336
2345
|
ctx.stroke();
|
|
2337
2346
|
ctx.restore();
|
|
2338
|
-
|
|
2339
|
-
|
|
2347
|
+
handleAt(x0, y0, drawing.color);
|
|
2348
|
+
handleAt(x1, y1, drawing.color);
|
|
2340
2349
|
if (p2) {
|
|
2341
2350
|
const x2 = xFromDrawingPoint(p2);
|
|
2342
2351
|
const y2 = yFromPrice(p2.price);
|
|
2343
|
-
|
|
2352
|
+
handleAt(x2, y2, drawing.color);
|
|
2344
2353
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
2345
2354
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
2346
2355
|
const move = p1.price - p0.price;
|
|
@@ -2405,10 +2414,14 @@ function createChart(element, options = {}) {
|
|
|
2405
2414
|
const entryY = yFromPrice(entry.price);
|
|
2406
2415
|
const targetY = yFromPrice(target.price);
|
|
2407
2416
|
const stopY = yFromPrice(stop.price);
|
|
2408
|
-
const
|
|
2409
|
-
const
|
|
2410
|
-
const
|
|
2411
|
-
const
|
|
2417
|
+
const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
|
|
2418
|
+
const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
|
|
2419
|
+
const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
|
|
2420
|
+
const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
|
|
2421
|
+
const profitFill = hexToRgba(profitColor, 0.16);
|
|
2422
|
+
const lossFill = hexToRgba(lossColor, 0.16);
|
|
2423
|
+
const profitLine = profitColor;
|
|
2424
|
+
const lossLine = lossColor;
|
|
2412
2425
|
ctx.save();
|
|
2413
2426
|
ctx.globalAlpha = draft ? 0.6 : 1;
|
|
2414
2427
|
ctx.fillStyle = profitFill;
|
|
@@ -2416,61 +2429,63 @@ function createChart(element, options = {}) {
|
|
|
2416
2429
|
ctx.fillStyle = lossFill;
|
|
2417
2430
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2418
2431
|
ctx.restore();
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2432
|
+
if (isSelected) {
|
|
2433
|
+
ctx.save();
|
|
2434
|
+
ctx.setLineDash([]);
|
|
2435
|
+
ctx.lineWidth = Math.max(1, drawing.width);
|
|
2436
|
+
ctx.strokeStyle = profitLine;
|
|
2437
|
+
ctx.beginPath();
|
|
2438
|
+
ctx.moveTo(crisp(boxX0), crisp(targetY));
|
|
2439
|
+
ctx.lineTo(crisp(boxX1), crisp(targetY));
|
|
2440
|
+
ctx.stroke();
|
|
2441
|
+
ctx.strokeStyle = lossLine;
|
|
2442
|
+
ctx.beginPath();
|
|
2443
|
+
ctx.moveTo(crisp(boxX0), crisp(stopY));
|
|
2444
|
+
ctx.lineTo(crisp(boxX1), crisp(stopY));
|
|
2445
|
+
ctx.stroke();
|
|
2446
|
+
ctx.strokeStyle = drawing.color;
|
|
2447
|
+
ctx.beginPath();
|
|
2448
|
+
ctx.moveTo(crisp(boxX0), crisp(entryY));
|
|
2449
|
+
ctx.lineTo(crisp(boxX1), crisp(entryY));
|
|
2450
|
+
ctx.stroke();
|
|
2451
|
+
ctx.restore();
|
|
2452
|
+
handleAt(leftX, targetY, drawing.color);
|
|
2453
|
+
handleAt(leftX, entryY, drawing.color);
|
|
2454
|
+
handleAt(leftX, stopY, drawing.color);
|
|
2455
|
+
handleAt(rightX, entryY, drawing.color);
|
|
2456
|
+
const tick = getConfiguredTickSize();
|
|
2457
|
+
const pctOf = (price) => {
|
|
2458
|
+
if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
|
|
2459
|
+
return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
|
|
2460
|
+
};
|
|
2461
|
+
const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
|
|
2462
|
+
const targetDist = Math.abs(target.price - entry.price);
|
|
2463
|
+
const stopDist = Math.abs(entry.price - stop.price);
|
|
2464
|
+
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2465
|
+
const cx = (boxX0 + boxX1) / 2;
|
|
2466
|
+
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2467
|
+
const prevFont = ctx.font;
|
|
2468
|
+
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2469
|
+
const padding = 6;
|
|
2470
|
+
const textW = ctx.measureText(text).width;
|
|
2471
|
+
const pillW = textW + padding * 2;
|
|
2472
|
+
const pillH = 18;
|
|
2473
|
+
const pillX = centerX - pillW / 2;
|
|
2474
|
+
const pillY = centerY - pillH / 2;
|
|
2475
|
+
ctx.fillStyle = bg;
|
|
2476
|
+
fillRoundedRect(pillX, pillY, pillW, pillH, 4);
|
|
2477
|
+
ctx.fillStyle = labelTextColor;
|
|
2478
|
+
ctx.textAlign = "center";
|
|
2479
|
+
ctx.textBaseline = "middle";
|
|
2480
|
+
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2481
|
+
ctx.font = prevFont;
|
|
2482
|
+
};
|
|
2483
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2484
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2485
|
+
drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
|
|
2486
|
+
if (drawing.label) {
|
|
2487
|
+
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2488
|
+
}
|
|
2474
2489
|
}
|
|
2475
2490
|
}
|
|
2476
2491
|
}
|
|
@@ -3909,7 +3924,8 @@ function createChart(element, options = {}) {
|
|
|
3909
3924
|
normalizeDrawingPoint(point.index, stopPrice),
|
|
3910
3925
|
normalizeDrawingPoint(point.index + width2, entryPrice)
|
|
3911
3926
|
],
|
|
3912
|
-
color: defaults.color ?? "#
|
|
3927
|
+
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3928
|
+
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3913
3929
|
style: defaults.style ?? "solid",
|
|
3914
3930
|
width: defaults.width ?? 1
|
|
3915
3931
|
})
|
|
@@ -3927,6 +3943,13 @@ function createChart(element, options = {}) {
|
|
|
3927
3943
|
}
|
|
3928
3944
|
drawingToolDefaults.set(tool, { ...defaults });
|
|
3929
3945
|
};
|
|
3946
|
+
const setSelectedDrawing = (id) => {
|
|
3947
|
+
if (selectedDrawingId === id) {
|
|
3948
|
+
return;
|
|
3949
|
+
}
|
|
3950
|
+
selectedDrawingId = id;
|
|
3951
|
+
draw();
|
|
3952
|
+
};
|
|
3930
3953
|
const updateDrawingDrag = (x, y) => {
|
|
3931
3954
|
if (!drawingDragState) {
|
|
3932
3955
|
return false;
|
|
@@ -4839,6 +4862,7 @@ function createChart(element, options = {}) {
|
|
|
4839
4862
|
clearDrawings,
|
|
4840
4863
|
onDrawingsChange,
|
|
4841
4864
|
onDrawingSelect,
|
|
4865
|
+
setSelectedDrawing,
|
|
4842
4866
|
onDrawingHover,
|
|
4843
4867
|
setDrawingDefaults,
|
|
4844
4868
|
setDoubleClickEnabled,
|
|
@@ -4858,5 +4882,6 @@ function createChart(element, options = {}) {
|
|
|
4858
4882
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4859
4883
|
0 && (module.exports = {
|
|
4860
4884
|
FIB_DEFAULT_PALETTE,
|
|
4885
|
+
POSITION_DEFAULT_COLORS,
|
|
4861
4886
|
createChart
|
|
4862
4887
|
});
|
|
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
|
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
69
|
}
|
|
70
|
+
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
|
+
declare const POSITION_DEFAULT_COLORS: string[];
|
|
70
72
|
/** Default multi-color palette for fib-retracement levels. */
|
|
71
73
|
declare const FIB_DEFAULT_PALETTE: string[];
|
|
72
74
|
interface DrawingSelectEvent {
|
|
@@ -420,6 +422,7 @@ interface ChartInstance {
|
|
|
420
422
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
421
423
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
422
424
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
|
+
setSelectedDrawing: (id: string | null) => void;
|
|
423
426
|
setDoubleClickEnabled: (enabled: boolean) => void;
|
|
424
427
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
425
428
|
registerIndicator: (plugin: IndicatorPlugin<any>) => void;
|
|
@@ -455,4 +458,4 @@ interface ViewportState {
|
|
|
455
458
|
}
|
|
456
459
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
457
460
|
|
|
458
|
-
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
|
461
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
|
|
2
3
|
var FIB_DEFAULT_PALETTE = [
|
|
3
4
|
"#787b86",
|
|
4
5
|
"#f23645",
|
|
@@ -957,6 +958,7 @@ function createChart(element, options = {}) {
|
|
|
957
958
|
let drawingSelectHandler = null;
|
|
958
959
|
let drawingHoverHandler = null;
|
|
959
960
|
let lastHoveredDrawingId = null;
|
|
961
|
+
let selectedDrawingId = null;
|
|
960
962
|
const drawingToolDefaults = /* @__PURE__ */ new Map();
|
|
961
963
|
const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
|
|
962
964
|
const emitDrawingsChange = () => {
|
|
@@ -2135,6 +2137,12 @@ function createChart(element, options = {}) {
|
|
|
2135
2137
|
if (!drawing.visible) {
|
|
2136
2138
|
return;
|
|
2137
2139
|
}
|
|
2140
|
+
const isSelected = draft || drawing.id === selectedDrawingId;
|
|
2141
|
+
const handleAt = (hx, hy, _color) => {
|
|
2142
|
+
if (isSelected) {
|
|
2143
|
+
drawDrawingHandle(hx, hy, drawing.color);
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2138
2146
|
ctx.save();
|
|
2139
2147
|
ctx.strokeStyle = drawing.color;
|
|
2140
2148
|
ctx.lineWidth = drawing.width;
|
|
@@ -2153,7 +2161,7 @@ function createChart(element, options = {}) {
|
|
|
2153
2161
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2154
2162
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2155
2163
|
ctx.stroke();
|
|
2156
|
-
|
|
2164
|
+
handleAt(handleX, y, drawing.color);
|
|
2157
2165
|
if (drawing.label) {
|
|
2158
2166
|
const midX = (chartLeft + chartRight) / 2;
|
|
2159
2167
|
drawDrawingLabel(drawing.label, midX, y, drawing.color);
|
|
@@ -2168,7 +2176,7 @@ function createChart(element, options = {}) {
|
|
|
2168
2176
|
ctx.lineTo(crisp(x), crisp(chartBottom));
|
|
2169
2177
|
ctx.stroke();
|
|
2170
2178
|
const handleY = (chartTop + chartBottom) / 2;
|
|
2171
|
-
|
|
2179
|
+
handleAt(x, handleY, drawing.color);
|
|
2172
2180
|
if (drawing.label) {
|
|
2173
2181
|
drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
|
|
2174
2182
|
}
|
|
@@ -2185,8 +2193,8 @@ function createChart(element, options = {}) {
|
|
|
2185
2193
|
ctx.moveTo(firstX, firstY);
|
|
2186
2194
|
ctx.lineTo(secondX, secondY);
|
|
2187
2195
|
ctx.stroke();
|
|
2188
|
-
|
|
2189
|
-
|
|
2196
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2197
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2190
2198
|
if (drawing.label) {
|
|
2191
2199
|
const midX = (firstX + secondX) / 2;
|
|
2192
2200
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2215,8 +2223,8 @@ function createChart(element, options = {}) {
|
|
|
2215
2223
|
ctx.moveTo(firstX, firstY);
|
|
2216
2224
|
ctx.lineTo(endX, endY);
|
|
2217
2225
|
ctx.stroke();
|
|
2218
|
-
|
|
2219
|
-
|
|
2226
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2227
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2220
2228
|
if (drawing.label) {
|
|
2221
2229
|
const midX = (firstX + secondX) / 2;
|
|
2222
2230
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2270,8 +2278,8 @@ function createChart(element, options = {}) {
|
|
|
2270
2278
|
ctx.lineTo(secondX, secondY);
|
|
2271
2279
|
ctx.stroke();
|
|
2272
2280
|
ctx.restore();
|
|
2273
|
-
|
|
2274
|
-
|
|
2281
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2282
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2275
2283
|
const prevFont = ctx.font;
|
|
2276
2284
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2277
2285
|
levelLines.forEach((level, index) => {
|
|
@@ -2310,12 +2318,12 @@ function createChart(element, options = {}) {
|
|
|
2310
2318
|
}
|
|
2311
2319
|
ctx.stroke();
|
|
2312
2320
|
ctx.restore();
|
|
2313
|
-
|
|
2314
|
-
|
|
2321
|
+
handleAt(x0, y0, drawing.color);
|
|
2322
|
+
handleAt(x1, y1, drawing.color);
|
|
2315
2323
|
if (p2) {
|
|
2316
2324
|
const x2 = xFromDrawingPoint(p2);
|
|
2317
2325
|
const y2 = yFromPrice(p2.price);
|
|
2318
|
-
|
|
2326
|
+
handleAt(x2, y2, drawing.color);
|
|
2319
2327
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
2320
2328
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
2321
2329
|
const move = p1.price - p0.price;
|
|
@@ -2380,10 +2388,14 @@ function createChart(element, options = {}) {
|
|
|
2380
2388
|
const entryY = yFromPrice(entry.price);
|
|
2381
2389
|
const targetY = yFromPrice(target.price);
|
|
2382
2390
|
const stopY = yFromPrice(stop.price);
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2391
|
+
const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
|
|
2392
|
+
const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
|
|
2393
|
+
const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
|
|
2394
|
+
const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
|
|
2395
|
+
const profitFill = hexToRgba(profitColor, 0.16);
|
|
2396
|
+
const lossFill = hexToRgba(lossColor, 0.16);
|
|
2397
|
+
const profitLine = profitColor;
|
|
2398
|
+
const lossLine = lossColor;
|
|
2387
2399
|
ctx.save();
|
|
2388
2400
|
ctx.globalAlpha = draft ? 0.6 : 1;
|
|
2389
2401
|
ctx.fillStyle = profitFill;
|
|
@@ -2391,61 +2403,63 @@ function createChart(element, options = {}) {
|
|
|
2391
2403
|
ctx.fillStyle = lossFill;
|
|
2392
2404
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2393
2405
|
ctx.restore();
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
const
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2406
|
+
if (isSelected) {
|
|
2407
|
+
ctx.save();
|
|
2408
|
+
ctx.setLineDash([]);
|
|
2409
|
+
ctx.lineWidth = Math.max(1, drawing.width);
|
|
2410
|
+
ctx.strokeStyle = profitLine;
|
|
2411
|
+
ctx.beginPath();
|
|
2412
|
+
ctx.moveTo(crisp(boxX0), crisp(targetY));
|
|
2413
|
+
ctx.lineTo(crisp(boxX1), crisp(targetY));
|
|
2414
|
+
ctx.stroke();
|
|
2415
|
+
ctx.strokeStyle = lossLine;
|
|
2416
|
+
ctx.beginPath();
|
|
2417
|
+
ctx.moveTo(crisp(boxX0), crisp(stopY));
|
|
2418
|
+
ctx.lineTo(crisp(boxX1), crisp(stopY));
|
|
2419
|
+
ctx.stroke();
|
|
2420
|
+
ctx.strokeStyle = drawing.color;
|
|
2421
|
+
ctx.beginPath();
|
|
2422
|
+
ctx.moveTo(crisp(boxX0), crisp(entryY));
|
|
2423
|
+
ctx.lineTo(crisp(boxX1), crisp(entryY));
|
|
2424
|
+
ctx.stroke();
|
|
2425
|
+
ctx.restore();
|
|
2426
|
+
handleAt(leftX, targetY, drawing.color);
|
|
2427
|
+
handleAt(leftX, entryY, drawing.color);
|
|
2428
|
+
handleAt(leftX, stopY, drawing.color);
|
|
2429
|
+
handleAt(rightX, entryY, drawing.color);
|
|
2430
|
+
const tick = getConfiguredTickSize();
|
|
2431
|
+
const pctOf = (price) => {
|
|
2432
|
+
if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
|
|
2433
|
+
return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
|
|
2434
|
+
};
|
|
2435
|
+
const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
|
|
2436
|
+
const targetDist = Math.abs(target.price - entry.price);
|
|
2437
|
+
const stopDist = Math.abs(entry.price - stop.price);
|
|
2438
|
+
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2439
|
+
const cx = (boxX0 + boxX1) / 2;
|
|
2440
|
+
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2441
|
+
const prevFont = ctx.font;
|
|
2442
|
+
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2443
|
+
const padding = 6;
|
|
2444
|
+
const textW = ctx.measureText(text).width;
|
|
2445
|
+
const pillW = textW + padding * 2;
|
|
2446
|
+
const pillH = 18;
|
|
2447
|
+
const pillX = centerX - pillW / 2;
|
|
2448
|
+
const pillY = centerY - pillH / 2;
|
|
2449
|
+
ctx.fillStyle = bg;
|
|
2450
|
+
fillRoundedRect(pillX, pillY, pillW, pillH, 4);
|
|
2451
|
+
ctx.fillStyle = labelTextColor;
|
|
2452
|
+
ctx.textAlign = "center";
|
|
2453
|
+
ctx.textBaseline = "middle";
|
|
2454
|
+
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2455
|
+
ctx.font = prevFont;
|
|
2456
|
+
};
|
|
2457
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2458
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2459
|
+
drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
|
|
2460
|
+
if (drawing.label) {
|
|
2461
|
+
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2462
|
+
}
|
|
2449
2463
|
}
|
|
2450
2464
|
}
|
|
2451
2465
|
}
|
|
@@ -3884,7 +3898,8 @@ function createChart(element, options = {}) {
|
|
|
3884
3898
|
normalizeDrawingPoint(point.index, stopPrice),
|
|
3885
3899
|
normalizeDrawingPoint(point.index + width2, entryPrice)
|
|
3886
3900
|
],
|
|
3887
|
-
color: defaults.color ?? "#
|
|
3901
|
+
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3902
|
+
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3888
3903
|
style: defaults.style ?? "solid",
|
|
3889
3904
|
width: defaults.width ?? 1
|
|
3890
3905
|
})
|
|
@@ -3902,6 +3917,13 @@ function createChart(element, options = {}) {
|
|
|
3902
3917
|
}
|
|
3903
3918
|
drawingToolDefaults.set(tool, { ...defaults });
|
|
3904
3919
|
};
|
|
3920
|
+
const setSelectedDrawing = (id) => {
|
|
3921
|
+
if (selectedDrawingId === id) {
|
|
3922
|
+
return;
|
|
3923
|
+
}
|
|
3924
|
+
selectedDrawingId = id;
|
|
3925
|
+
draw();
|
|
3926
|
+
};
|
|
3905
3927
|
const updateDrawingDrag = (x, y) => {
|
|
3906
3928
|
if (!drawingDragState) {
|
|
3907
3929
|
return false;
|
|
@@ -4814,6 +4836,7 @@ function createChart(element, options = {}) {
|
|
|
4814
4836
|
clearDrawings,
|
|
4815
4837
|
onDrawingsChange,
|
|
4816
4838
|
onDrawingSelect,
|
|
4839
|
+
setSelectedDrawing,
|
|
4817
4840
|
onDrawingHover,
|
|
4818
4841
|
setDrawingDefaults,
|
|
4819
4842
|
setDoubleClickEnabled,
|
|
@@ -4832,5 +4855,6 @@ function createChart(element, options = {}) {
|
|
|
4832
4855
|
}
|
|
4833
4856
|
export {
|
|
4834
4857
|
FIB_DEFAULT_PALETTE,
|
|
4858
|
+
POSITION_DEFAULT_COLORS,
|
|
4835
4859
|
createChart
|
|
4836
4860
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
|
|
24
|
+
POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
|
|
24
25
|
createChart: () => createChart
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
|
|
27
29
|
var FIB_DEFAULT_PALETTE = [
|
|
28
30
|
"#787b86",
|
|
29
31
|
"#f23645",
|
|
@@ -982,6 +984,7 @@ function createChart(element, options = {}) {
|
|
|
982
984
|
let drawingSelectHandler = null;
|
|
983
985
|
let drawingHoverHandler = null;
|
|
984
986
|
let lastHoveredDrawingId = null;
|
|
987
|
+
let selectedDrawingId = null;
|
|
985
988
|
const drawingToolDefaults = /* @__PURE__ */ new Map();
|
|
986
989
|
const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
|
|
987
990
|
const emitDrawingsChange = () => {
|
|
@@ -2160,6 +2163,12 @@ function createChart(element, options = {}) {
|
|
|
2160
2163
|
if (!drawing.visible) {
|
|
2161
2164
|
return;
|
|
2162
2165
|
}
|
|
2166
|
+
const isSelected = draft || drawing.id === selectedDrawingId;
|
|
2167
|
+
const handleAt = (hx, hy, _color) => {
|
|
2168
|
+
if (isSelected) {
|
|
2169
|
+
drawDrawingHandle(hx, hy, drawing.color);
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2163
2172
|
ctx.save();
|
|
2164
2173
|
ctx.strokeStyle = drawing.color;
|
|
2165
2174
|
ctx.lineWidth = drawing.width;
|
|
@@ -2178,7 +2187,7 @@ function createChart(element, options = {}) {
|
|
|
2178
2187
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2179
2188
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2180
2189
|
ctx.stroke();
|
|
2181
|
-
|
|
2190
|
+
handleAt(handleX, y, drawing.color);
|
|
2182
2191
|
if (drawing.label) {
|
|
2183
2192
|
const midX = (chartLeft + chartRight) / 2;
|
|
2184
2193
|
drawDrawingLabel(drawing.label, midX, y, drawing.color);
|
|
@@ -2193,7 +2202,7 @@ function createChart(element, options = {}) {
|
|
|
2193
2202
|
ctx.lineTo(crisp(x), crisp(chartBottom));
|
|
2194
2203
|
ctx.stroke();
|
|
2195
2204
|
const handleY = (chartTop + chartBottom) / 2;
|
|
2196
|
-
|
|
2205
|
+
handleAt(x, handleY, drawing.color);
|
|
2197
2206
|
if (drawing.label) {
|
|
2198
2207
|
drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
|
|
2199
2208
|
}
|
|
@@ -2210,8 +2219,8 @@ function createChart(element, options = {}) {
|
|
|
2210
2219
|
ctx.moveTo(firstX, firstY);
|
|
2211
2220
|
ctx.lineTo(secondX, secondY);
|
|
2212
2221
|
ctx.stroke();
|
|
2213
|
-
|
|
2214
|
-
|
|
2222
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2223
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2215
2224
|
if (drawing.label) {
|
|
2216
2225
|
const midX = (firstX + secondX) / 2;
|
|
2217
2226
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2240,8 +2249,8 @@ function createChart(element, options = {}) {
|
|
|
2240
2249
|
ctx.moveTo(firstX, firstY);
|
|
2241
2250
|
ctx.lineTo(endX, endY);
|
|
2242
2251
|
ctx.stroke();
|
|
2243
|
-
|
|
2244
|
-
|
|
2252
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2253
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2245
2254
|
if (drawing.label) {
|
|
2246
2255
|
const midX = (firstX + secondX) / 2;
|
|
2247
2256
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2295,8 +2304,8 @@ function createChart(element, options = {}) {
|
|
|
2295
2304
|
ctx.lineTo(secondX, secondY);
|
|
2296
2305
|
ctx.stroke();
|
|
2297
2306
|
ctx.restore();
|
|
2298
|
-
|
|
2299
|
-
|
|
2307
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2308
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2300
2309
|
const prevFont = ctx.font;
|
|
2301
2310
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2302
2311
|
levelLines.forEach((level, index) => {
|
|
@@ -2335,12 +2344,12 @@ function createChart(element, options = {}) {
|
|
|
2335
2344
|
}
|
|
2336
2345
|
ctx.stroke();
|
|
2337
2346
|
ctx.restore();
|
|
2338
|
-
|
|
2339
|
-
|
|
2347
|
+
handleAt(x0, y0, drawing.color);
|
|
2348
|
+
handleAt(x1, y1, drawing.color);
|
|
2340
2349
|
if (p2) {
|
|
2341
2350
|
const x2 = xFromDrawingPoint(p2);
|
|
2342
2351
|
const y2 = yFromPrice(p2.price);
|
|
2343
|
-
|
|
2352
|
+
handleAt(x2, y2, drawing.color);
|
|
2344
2353
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
2345
2354
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
2346
2355
|
const move = p1.price - p0.price;
|
|
@@ -2405,10 +2414,14 @@ function createChart(element, options = {}) {
|
|
|
2405
2414
|
const entryY = yFromPrice(entry.price);
|
|
2406
2415
|
const targetY = yFromPrice(target.price);
|
|
2407
2416
|
const stopY = yFromPrice(stop.price);
|
|
2408
|
-
const
|
|
2409
|
-
const
|
|
2410
|
-
const
|
|
2411
|
-
const
|
|
2417
|
+
const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
|
|
2418
|
+
const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
|
|
2419
|
+
const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
|
|
2420
|
+
const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
|
|
2421
|
+
const profitFill = hexToRgba(profitColor, 0.16);
|
|
2422
|
+
const lossFill = hexToRgba(lossColor, 0.16);
|
|
2423
|
+
const profitLine = profitColor;
|
|
2424
|
+
const lossLine = lossColor;
|
|
2412
2425
|
ctx.save();
|
|
2413
2426
|
ctx.globalAlpha = draft ? 0.6 : 1;
|
|
2414
2427
|
ctx.fillStyle = profitFill;
|
|
@@ -2416,61 +2429,63 @@ function createChart(element, options = {}) {
|
|
|
2416
2429
|
ctx.fillStyle = lossFill;
|
|
2417
2430
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2418
2431
|
ctx.restore();
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2432
|
+
if (isSelected) {
|
|
2433
|
+
ctx.save();
|
|
2434
|
+
ctx.setLineDash([]);
|
|
2435
|
+
ctx.lineWidth = Math.max(1, drawing.width);
|
|
2436
|
+
ctx.strokeStyle = profitLine;
|
|
2437
|
+
ctx.beginPath();
|
|
2438
|
+
ctx.moveTo(crisp(boxX0), crisp(targetY));
|
|
2439
|
+
ctx.lineTo(crisp(boxX1), crisp(targetY));
|
|
2440
|
+
ctx.stroke();
|
|
2441
|
+
ctx.strokeStyle = lossLine;
|
|
2442
|
+
ctx.beginPath();
|
|
2443
|
+
ctx.moveTo(crisp(boxX0), crisp(stopY));
|
|
2444
|
+
ctx.lineTo(crisp(boxX1), crisp(stopY));
|
|
2445
|
+
ctx.stroke();
|
|
2446
|
+
ctx.strokeStyle = drawing.color;
|
|
2447
|
+
ctx.beginPath();
|
|
2448
|
+
ctx.moveTo(crisp(boxX0), crisp(entryY));
|
|
2449
|
+
ctx.lineTo(crisp(boxX1), crisp(entryY));
|
|
2450
|
+
ctx.stroke();
|
|
2451
|
+
ctx.restore();
|
|
2452
|
+
handleAt(leftX, targetY, drawing.color);
|
|
2453
|
+
handleAt(leftX, entryY, drawing.color);
|
|
2454
|
+
handleAt(leftX, stopY, drawing.color);
|
|
2455
|
+
handleAt(rightX, entryY, drawing.color);
|
|
2456
|
+
const tick = getConfiguredTickSize();
|
|
2457
|
+
const pctOf = (price) => {
|
|
2458
|
+
if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
|
|
2459
|
+
return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
|
|
2460
|
+
};
|
|
2461
|
+
const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
|
|
2462
|
+
const targetDist = Math.abs(target.price - entry.price);
|
|
2463
|
+
const stopDist = Math.abs(entry.price - stop.price);
|
|
2464
|
+
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2465
|
+
const cx = (boxX0 + boxX1) / 2;
|
|
2466
|
+
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2467
|
+
const prevFont = ctx.font;
|
|
2468
|
+
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2469
|
+
const padding = 6;
|
|
2470
|
+
const textW = ctx.measureText(text).width;
|
|
2471
|
+
const pillW = textW + padding * 2;
|
|
2472
|
+
const pillH = 18;
|
|
2473
|
+
const pillX = centerX - pillW / 2;
|
|
2474
|
+
const pillY = centerY - pillH / 2;
|
|
2475
|
+
ctx.fillStyle = bg;
|
|
2476
|
+
fillRoundedRect(pillX, pillY, pillW, pillH, 4);
|
|
2477
|
+
ctx.fillStyle = labelTextColor;
|
|
2478
|
+
ctx.textAlign = "center";
|
|
2479
|
+
ctx.textBaseline = "middle";
|
|
2480
|
+
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2481
|
+
ctx.font = prevFont;
|
|
2482
|
+
};
|
|
2483
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2484
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2485
|
+
drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
|
|
2486
|
+
if (drawing.label) {
|
|
2487
|
+
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2488
|
+
}
|
|
2474
2489
|
}
|
|
2475
2490
|
}
|
|
2476
2491
|
}
|
|
@@ -3909,7 +3924,8 @@ function createChart(element, options = {}) {
|
|
|
3909
3924
|
normalizeDrawingPoint(point.index, stopPrice),
|
|
3910
3925
|
normalizeDrawingPoint(point.index + width2, entryPrice)
|
|
3911
3926
|
],
|
|
3912
|
-
color: defaults.color ?? "#
|
|
3927
|
+
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3928
|
+
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3913
3929
|
style: defaults.style ?? "solid",
|
|
3914
3930
|
width: defaults.width ?? 1
|
|
3915
3931
|
})
|
|
@@ -3927,6 +3943,13 @@ function createChart(element, options = {}) {
|
|
|
3927
3943
|
}
|
|
3928
3944
|
drawingToolDefaults.set(tool, { ...defaults });
|
|
3929
3945
|
};
|
|
3946
|
+
const setSelectedDrawing = (id) => {
|
|
3947
|
+
if (selectedDrawingId === id) {
|
|
3948
|
+
return;
|
|
3949
|
+
}
|
|
3950
|
+
selectedDrawingId = id;
|
|
3951
|
+
draw();
|
|
3952
|
+
};
|
|
3930
3953
|
const updateDrawingDrag = (x, y) => {
|
|
3931
3954
|
if (!drawingDragState) {
|
|
3932
3955
|
return false;
|
|
@@ -4839,6 +4862,7 @@ function createChart(element, options = {}) {
|
|
|
4839
4862
|
clearDrawings,
|
|
4840
4863
|
onDrawingsChange,
|
|
4841
4864
|
onDrawingSelect,
|
|
4865
|
+
setSelectedDrawing,
|
|
4842
4866
|
onDrawingHover,
|
|
4843
4867
|
setDrawingDefaults,
|
|
4844
4868
|
setDoubleClickEnabled,
|
|
@@ -4858,5 +4882,6 @@ function createChart(element, options = {}) {
|
|
|
4858
4882
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4859
4883
|
0 && (module.exports = {
|
|
4860
4884
|
FIB_DEFAULT_PALETTE,
|
|
4885
|
+
POSITION_DEFAULT_COLORS,
|
|
4861
4886
|
createChart
|
|
4862
4887
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
|
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
69
|
}
|
|
70
|
+
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
|
+
declare const POSITION_DEFAULT_COLORS: string[];
|
|
70
72
|
/** Default multi-color palette for fib-retracement levels. */
|
|
71
73
|
declare const FIB_DEFAULT_PALETTE: string[];
|
|
72
74
|
interface DrawingSelectEvent {
|
|
@@ -420,6 +422,7 @@ interface ChartInstance {
|
|
|
420
422
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
421
423
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
422
424
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
|
+
setSelectedDrawing: (id: string | null) => void;
|
|
423
426
|
setDoubleClickEnabled: (enabled: boolean) => void;
|
|
424
427
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
425
428
|
registerIndicator: (plugin: IndicatorPlugin<any>) => void;
|
|
@@ -455,4 +458,4 @@ interface ViewportState {
|
|
|
455
458
|
}
|
|
456
459
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
457
460
|
|
|
458
|
-
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
|
461
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
|
|
|
67
67
|
label?: string;
|
|
68
68
|
locked?: boolean;
|
|
69
69
|
}
|
|
70
|
+
/** Default colors for position tools: [profit, loss, label text]. */
|
|
71
|
+
declare const POSITION_DEFAULT_COLORS: string[];
|
|
70
72
|
/** Default multi-color palette for fib-retracement levels. */
|
|
71
73
|
declare const FIB_DEFAULT_PALETTE: string[];
|
|
72
74
|
interface DrawingSelectEvent {
|
|
@@ -420,6 +422,7 @@ interface ChartInstance {
|
|
|
420
422
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
421
423
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
422
424
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
425
|
+
setSelectedDrawing: (id: string | null) => void;
|
|
423
426
|
setDoubleClickEnabled: (enabled: boolean) => void;
|
|
424
427
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
425
428
|
registerIndicator: (plugin: IndicatorPlugin<any>) => void;
|
|
@@ -455,4 +458,4 @@ interface ViewportState {
|
|
|
455
458
|
}
|
|
456
459
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
457
460
|
|
|
458
|
-
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
|
461
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
|
|
2
3
|
var FIB_DEFAULT_PALETTE = [
|
|
3
4
|
"#787b86",
|
|
4
5
|
"#f23645",
|
|
@@ -957,6 +958,7 @@ function createChart(element, options = {}) {
|
|
|
957
958
|
let drawingSelectHandler = null;
|
|
958
959
|
let drawingHoverHandler = null;
|
|
959
960
|
let lastHoveredDrawingId = null;
|
|
961
|
+
let selectedDrawingId = null;
|
|
960
962
|
const drawingToolDefaults = /* @__PURE__ */ new Map();
|
|
961
963
|
const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
|
|
962
964
|
const emitDrawingsChange = () => {
|
|
@@ -2135,6 +2137,12 @@ function createChart(element, options = {}) {
|
|
|
2135
2137
|
if (!drawing.visible) {
|
|
2136
2138
|
return;
|
|
2137
2139
|
}
|
|
2140
|
+
const isSelected = draft || drawing.id === selectedDrawingId;
|
|
2141
|
+
const handleAt = (hx, hy, _color) => {
|
|
2142
|
+
if (isSelected) {
|
|
2143
|
+
drawDrawingHandle(hx, hy, drawing.color);
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2138
2146
|
ctx.save();
|
|
2139
2147
|
ctx.strokeStyle = drawing.color;
|
|
2140
2148
|
ctx.lineWidth = drawing.width;
|
|
@@ -2153,7 +2161,7 @@ function createChart(element, options = {}) {
|
|
|
2153
2161
|
ctx.moveTo(crisp(chartLeft), crisp(y));
|
|
2154
2162
|
ctx.lineTo(crisp(chartRight), crisp(y));
|
|
2155
2163
|
ctx.stroke();
|
|
2156
|
-
|
|
2164
|
+
handleAt(handleX, y, drawing.color);
|
|
2157
2165
|
if (drawing.label) {
|
|
2158
2166
|
const midX = (chartLeft + chartRight) / 2;
|
|
2159
2167
|
drawDrawingLabel(drawing.label, midX, y, drawing.color);
|
|
@@ -2168,7 +2176,7 @@ function createChart(element, options = {}) {
|
|
|
2168
2176
|
ctx.lineTo(crisp(x), crisp(chartBottom));
|
|
2169
2177
|
ctx.stroke();
|
|
2170
2178
|
const handleY = (chartTop + chartBottom) / 2;
|
|
2171
|
-
|
|
2179
|
+
handleAt(x, handleY, drawing.color);
|
|
2172
2180
|
if (drawing.label) {
|
|
2173
2181
|
drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
|
|
2174
2182
|
}
|
|
@@ -2185,8 +2193,8 @@ function createChart(element, options = {}) {
|
|
|
2185
2193
|
ctx.moveTo(firstX, firstY);
|
|
2186
2194
|
ctx.lineTo(secondX, secondY);
|
|
2187
2195
|
ctx.stroke();
|
|
2188
|
-
|
|
2189
|
-
|
|
2196
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2197
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2190
2198
|
if (drawing.label) {
|
|
2191
2199
|
const midX = (firstX + secondX) / 2;
|
|
2192
2200
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2215,8 +2223,8 @@ function createChart(element, options = {}) {
|
|
|
2215
2223
|
ctx.moveTo(firstX, firstY);
|
|
2216
2224
|
ctx.lineTo(endX, endY);
|
|
2217
2225
|
ctx.stroke();
|
|
2218
|
-
|
|
2219
|
-
|
|
2226
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2227
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2220
2228
|
if (drawing.label) {
|
|
2221
2229
|
const midX = (firstX + secondX) / 2;
|
|
2222
2230
|
const midY = (firstY + secondY) / 2;
|
|
@@ -2270,8 +2278,8 @@ function createChart(element, options = {}) {
|
|
|
2270
2278
|
ctx.lineTo(secondX, secondY);
|
|
2271
2279
|
ctx.stroke();
|
|
2272
2280
|
ctx.restore();
|
|
2273
|
-
|
|
2274
|
-
|
|
2281
|
+
handleAt(firstX, firstY, drawing.color);
|
|
2282
|
+
handleAt(secondX, secondY, drawing.color);
|
|
2275
2283
|
const prevFont = ctx.font;
|
|
2276
2284
|
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2277
2285
|
levelLines.forEach((level, index) => {
|
|
@@ -2310,12 +2318,12 @@ function createChart(element, options = {}) {
|
|
|
2310
2318
|
}
|
|
2311
2319
|
ctx.stroke();
|
|
2312
2320
|
ctx.restore();
|
|
2313
|
-
|
|
2314
|
-
|
|
2321
|
+
handleAt(x0, y0, drawing.color);
|
|
2322
|
+
handleAt(x1, y1, drawing.color);
|
|
2315
2323
|
if (p2) {
|
|
2316
2324
|
const x2 = xFromDrawingPoint(p2);
|
|
2317
2325
|
const y2 = yFromPrice(p2.price);
|
|
2318
|
-
|
|
2326
|
+
handleAt(x2, y2, drawing.color);
|
|
2319
2327
|
const palette = drawing.colors.length > 0 ? drawing.colors : null;
|
|
2320
2328
|
const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
|
|
2321
2329
|
const move = p1.price - p0.price;
|
|
@@ -2380,10 +2388,14 @@ function createChart(element, options = {}) {
|
|
|
2380
2388
|
const entryY = yFromPrice(entry.price);
|
|
2381
2389
|
const targetY = yFromPrice(target.price);
|
|
2382
2390
|
const stopY = yFromPrice(stop.price);
|
|
2383
|
-
const
|
|
2384
|
-
const
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2391
|
+
const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
|
|
2392
|
+
const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
|
|
2393
|
+
const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
|
|
2394
|
+
const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
|
|
2395
|
+
const profitFill = hexToRgba(profitColor, 0.16);
|
|
2396
|
+
const lossFill = hexToRgba(lossColor, 0.16);
|
|
2397
|
+
const profitLine = profitColor;
|
|
2398
|
+
const lossLine = lossColor;
|
|
2387
2399
|
ctx.save();
|
|
2388
2400
|
ctx.globalAlpha = draft ? 0.6 : 1;
|
|
2389
2401
|
ctx.fillStyle = profitFill;
|
|
@@ -2391,61 +2403,63 @@ function createChart(element, options = {}) {
|
|
|
2391
2403
|
ctx.fillStyle = lossFill;
|
|
2392
2404
|
ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
|
|
2393
2405
|
ctx.restore();
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
const
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2406
|
+
if (isSelected) {
|
|
2407
|
+
ctx.save();
|
|
2408
|
+
ctx.setLineDash([]);
|
|
2409
|
+
ctx.lineWidth = Math.max(1, drawing.width);
|
|
2410
|
+
ctx.strokeStyle = profitLine;
|
|
2411
|
+
ctx.beginPath();
|
|
2412
|
+
ctx.moveTo(crisp(boxX0), crisp(targetY));
|
|
2413
|
+
ctx.lineTo(crisp(boxX1), crisp(targetY));
|
|
2414
|
+
ctx.stroke();
|
|
2415
|
+
ctx.strokeStyle = lossLine;
|
|
2416
|
+
ctx.beginPath();
|
|
2417
|
+
ctx.moveTo(crisp(boxX0), crisp(stopY));
|
|
2418
|
+
ctx.lineTo(crisp(boxX1), crisp(stopY));
|
|
2419
|
+
ctx.stroke();
|
|
2420
|
+
ctx.strokeStyle = drawing.color;
|
|
2421
|
+
ctx.beginPath();
|
|
2422
|
+
ctx.moveTo(crisp(boxX0), crisp(entryY));
|
|
2423
|
+
ctx.lineTo(crisp(boxX1), crisp(entryY));
|
|
2424
|
+
ctx.stroke();
|
|
2425
|
+
ctx.restore();
|
|
2426
|
+
handleAt(leftX, targetY, drawing.color);
|
|
2427
|
+
handleAt(leftX, entryY, drawing.color);
|
|
2428
|
+
handleAt(leftX, stopY, drawing.color);
|
|
2429
|
+
handleAt(rightX, entryY, drawing.color);
|
|
2430
|
+
const tick = getConfiguredTickSize();
|
|
2431
|
+
const pctOf = (price) => {
|
|
2432
|
+
if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
|
|
2433
|
+
return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
|
|
2434
|
+
};
|
|
2435
|
+
const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
|
|
2436
|
+
const targetDist = Math.abs(target.price - entry.price);
|
|
2437
|
+
const stopDist = Math.abs(entry.price - stop.price);
|
|
2438
|
+
const rr = stopDist > 0 ? targetDist / stopDist : 0;
|
|
2439
|
+
const cx = (boxX0 + boxX1) / 2;
|
|
2440
|
+
const drawPositionPill = (text, centerX, centerY, bg) => {
|
|
2441
|
+
const prevFont = ctx.font;
|
|
2442
|
+
ctx.font = `500 11px ${mergedOptions.fontFamily}`;
|
|
2443
|
+
const padding = 6;
|
|
2444
|
+
const textW = ctx.measureText(text).width;
|
|
2445
|
+
const pillW = textW + padding * 2;
|
|
2446
|
+
const pillH = 18;
|
|
2447
|
+
const pillX = centerX - pillW / 2;
|
|
2448
|
+
const pillY = centerY - pillH / 2;
|
|
2449
|
+
ctx.fillStyle = bg;
|
|
2450
|
+
fillRoundedRect(pillX, pillY, pillW, pillH, 4);
|
|
2451
|
+
ctx.fillStyle = labelTextColor;
|
|
2452
|
+
ctx.textAlign = "center";
|
|
2453
|
+
ctx.textBaseline = "middle";
|
|
2454
|
+
ctx.fillText(text, centerX, pillY + pillH / 2);
|
|
2455
|
+
ctx.font = prevFont;
|
|
2456
|
+
};
|
|
2457
|
+
drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
|
|
2458
|
+
drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
|
|
2459
|
+
drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
|
|
2460
|
+
if (drawing.label) {
|
|
2461
|
+
drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
|
|
2462
|
+
}
|
|
2449
2463
|
}
|
|
2450
2464
|
}
|
|
2451
2465
|
}
|
|
@@ -3884,7 +3898,8 @@ function createChart(element, options = {}) {
|
|
|
3884
3898
|
normalizeDrawingPoint(point.index, stopPrice),
|
|
3885
3899
|
normalizeDrawingPoint(point.index + width2, entryPrice)
|
|
3886
3900
|
],
|
|
3887
|
-
color: defaults.color ?? "#
|
|
3901
|
+
color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
|
|
3902
|
+
colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
|
|
3888
3903
|
style: defaults.style ?? "solid",
|
|
3889
3904
|
width: defaults.width ?? 1
|
|
3890
3905
|
})
|
|
@@ -3902,6 +3917,13 @@ function createChart(element, options = {}) {
|
|
|
3902
3917
|
}
|
|
3903
3918
|
drawingToolDefaults.set(tool, { ...defaults });
|
|
3904
3919
|
};
|
|
3920
|
+
const setSelectedDrawing = (id) => {
|
|
3921
|
+
if (selectedDrawingId === id) {
|
|
3922
|
+
return;
|
|
3923
|
+
}
|
|
3924
|
+
selectedDrawingId = id;
|
|
3925
|
+
draw();
|
|
3926
|
+
};
|
|
3905
3927
|
const updateDrawingDrag = (x, y) => {
|
|
3906
3928
|
if (!drawingDragState) {
|
|
3907
3929
|
return false;
|
|
@@ -4814,6 +4836,7 @@ function createChart(element, options = {}) {
|
|
|
4814
4836
|
clearDrawings,
|
|
4815
4837
|
onDrawingsChange,
|
|
4816
4838
|
onDrawingSelect,
|
|
4839
|
+
setSelectedDrawing,
|
|
4817
4840
|
onDrawingHover,
|
|
4818
4841
|
setDrawingDefaults,
|
|
4819
4842
|
setDoubleClickEnabled,
|
|
@@ -4832,5 +4855,6 @@ function createChart(element, options = {}) {
|
|
|
4832
4855
|
}
|
|
4833
4856
|
export {
|
|
4834
4857
|
FIB_DEFAULT_PALETTE,
|
|
4858
|
+
POSITION_DEFAULT_COLORS,
|
|
4835
4859
|
createChart
|
|
4836
4860
|
};
|
package/docs/API.md
CHANGED
|
@@ -422,7 +422,7 @@ Drawings are user-created chart tools, separate from indicators. They are intera
|
|
|
422
422
|
- `ray`: two-point line that extends infinitely past the second point
|
|
423
423
|
- `fib-retracement`: two-point retracement with levels/bands
|
|
424
424
|
- `fib-extension`: trend-based three-point extension (click trend start, trend end, then the projection origin); levels project from the third point by the first→second move
|
|
425
|
-
- `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio.
|
|
425
|
+
- `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio. `color` sets the entry line; `colors` is `[profitColor, lossColor, labelTextColor]` (defaults `POSITION_DEFAULT_COLORS`).
|
|
426
426
|
- `points: DrawingPoint[]`
|
|
427
427
|
- `visible?: boolean`
|
|
428
428
|
- `color?: string`
|
|
@@ -481,6 +481,7 @@ Use `getDrawings()` / `setDrawings()` for persistence.
|
|
|
481
481
|
- `panY(priceDelta: number): void` (positive = move viewport up)
|
|
482
482
|
- `fitContent(): void` (x-only fit, keeps y zoom)
|
|
483
483
|
- `resetViewport(): void` (fit x + reset y auto-scale)
|
|
484
|
+
- `setSelectedDrawing(id: string | null): void` (marks a drawing selected; only the selected/drafted drawing renders its handles, and position tools render their lines/labels only while selected)
|
|
484
485
|
- `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`)
|
|
485
486
|
- `getActiveDrawingTool(): DrawingToolType | null`
|
|
486
487
|
- `setDrawings(drawings: DrawingObjectOptions[]): void`
|