hyperprop-charting-library 0.1.85 → 0.1.87
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 +93 -2
- package/dist/hyperprop-charting-library.d.ts +4 -2
- package/dist/hyperprop-charting-library.js +93 -2
- package/dist/index.cjs +93 -2
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +93 -2
- package/docs/API.md +1 -0
- package/package.json +1 -1
|
@@ -968,6 +968,7 @@ function createChart(element, options = {}) {
|
|
|
968
968
|
leverage: Number(drawing.leverage) || 1,
|
|
969
969
|
pointValue: Number(drawing.pointValue) || 1,
|
|
970
970
|
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
971
|
+
fontSize: Math.max(6, Number(drawing.fontSize) || 14),
|
|
971
972
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
972
973
|
});
|
|
973
974
|
const serializeDrawing = (drawing) => ({
|
|
@@ -987,6 +988,7 @@ function createChart(element, options = {}) {
|
|
|
987
988
|
leverage: drawing.leverage,
|
|
988
989
|
pointValue: drawing.pointValue,
|
|
989
990
|
qtyPrecision: drawing.qtyPrecision,
|
|
991
|
+
fontSize: drawing.fontSize,
|
|
990
992
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
991
993
|
});
|
|
992
994
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -997,6 +999,7 @@ function createChart(element, options = {}) {
|
|
|
997
999
|
let drawingsChangeHandler = null;
|
|
998
1000
|
let drawingSelectHandler = null;
|
|
999
1001
|
let drawingDoubleClickHandler = null;
|
|
1002
|
+
let drawingEditTextHandler = null;
|
|
1000
1003
|
let drawingHoverHandler = null;
|
|
1001
1004
|
let lastHoveredDrawingId = null;
|
|
1002
1005
|
let selectedDrawingId = null;
|
|
@@ -2635,6 +2638,46 @@ function createChart(element, options = {}) {
|
|
|
2635
2638
|
drawDrawingLabel(drawing.label, midX, topY - 4, drawing.color);
|
|
2636
2639
|
}
|
|
2637
2640
|
}
|
|
2641
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
2642
|
+
const anchor = drawing.points[0];
|
|
2643
|
+
if (anchor) {
|
|
2644
|
+
const ax = xFromDrawingPoint(anchor);
|
|
2645
|
+
const ay = yFromPrice(anchor.price);
|
|
2646
|
+
const isNote = drawing.type === "note";
|
|
2647
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
2648
|
+
const prevFont = ctx.font;
|
|
2649
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
2650
|
+
ctx.textAlign = "left";
|
|
2651
|
+
ctx.textBaseline = "top";
|
|
2652
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
2653
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
2654
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
2655
|
+
const padX = isNote ? 8 : 2;
|
|
2656
|
+
const padY = isNote ? 6 : 1;
|
|
2657
|
+
const blockW = textW + padX * 2;
|
|
2658
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
2659
|
+
ctx.save();
|
|
2660
|
+
ctx.globalAlpha = draft ? 0.7 : 1;
|
|
2661
|
+
if (isNote) {
|
|
2662
|
+
ctx.fillStyle = hexToRgba(drawing.color, 0.14);
|
|
2663
|
+
fillRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2664
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.5);
|
|
2665
|
+
ctx.lineWidth = 1;
|
|
2666
|
+
strokeRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2667
|
+
}
|
|
2668
|
+
ctx.fillStyle = drawing.color;
|
|
2669
|
+
lines.forEach((line, lineIndex) => ctx.fillText(line, ax + padX, ay + padY + lineIndex * lineH));
|
|
2670
|
+
ctx.restore();
|
|
2671
|
+
ctx.font = prevFont;
|
|
2672
|
+
if (isSelected) {
|
|
2673
|
+
ctx.save();
|
|
2674
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.9);
|
|
2675
|
+
ctx.lineWidth = 1;
|
|
2676
|
+
ctx.setLineDash([]);
|
|
2677
|
+
strokeRoundedRect(ax - 2, ay - 2, blockW + 4, blockH + 4, 3);
|
|
2678
|
+
ctx.restore();
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2638
2681
|
}
|
|
2639
2682
|
ctx.restore();
|
|
2640
2683
|
};
|
|
@@ -3883,6 +3926,27 @@ function createChart(element, options = {}) {
|
|
|
3883
3926
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
3884
3927
|
return { drawing, target: "line" };
|
|
3885
3928
|
}
|
|
3929
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
3930
|
+
const anchor = drawing.points[0];
|
|
3931
|
+
if (!anchor) continue;
|
|
3932
|
+
const ax = canvasXFromDrawingPoint(anchor);
|
|
3933
|
+
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
3934
|
+
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
3935
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
3936
|
+
const prevFont = ctx.font;
|
|
3937
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
3938
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
3939
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
3940
|
+
ctx.font = prevFont;
|
|
3941
|
+
const isNote = drawing.type === "note";
|
|
3942
|
+
const padX = isNote ? 8 : 2;
|
|
3943
|
+
const padY = isNote ? 6 : 1;
|
|
3944
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
3945
|
+
const blockW = textW + padX * 2;
|
|
3946
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
3947
|
+
if (x >= ax && x <= ax + blockW && y >= ay && y <= ay + blockH) {
|
|
3948
|
+
return { drawing, target: "line" };
|
|
3949
|
+
}
|
|
3886
3950
|
}
|
|
3887
3951
|
}
|
|
3888
3952
|
return null;
|
|
@@ -4083,6 +4147,24 @@ function createChart(element, options = {}) {
|
|
|
4083
4147
|
draw();
|
|
4084
4148
|
return true;
|
|
4085
4149
|
}
|
|
4150
|
+
if (activeDrawingTool === "text" || activeDrawingTool === "note") {
|
|
4151
|
+
const defaults = getDrawingToolDefaults(activeDrawingTool);
|
|
4152
|
+
const created = normalizeDrawingState({
|
|
4153
|
+
type: activeDrawingTool,
|
|
4154
|
+
points: [point],
|
|
4155
|
+
color: defaults.color ?? "#e2e8f0",
|
|
4156
|
+
style: defaults.style ?? "solid",
|
|
4157
|
+
width: defaults.width ?? 1,
|
|
4158
|
+
...defaults.fontSize === void 0 ? {} : { fontSize: defaults.fontSize },
|
|
4159
|
+
label: ""
|
|
4160
|
+
});
|
|
4161
|
+
drawings.push(created);
|
|
4162
|
+
selectedDrawingId = created.id;
|
|
4163
|
+
emitDrawingsChange();
|
|
4164
|
+
draw();
|
|
4165
|
+
drawingEditTextHandler?.({ drawing: serializeDrawing(created), target: "line", x, y });
|
|
4166
|
+
return true;
|
|
4167
|
+
}
|
|
4086
4168
|
if (activeDrawingTool === "price-range") {
|
|
4087
4169
|
const tick = getConfiguredTickSize();
|
|
4088
4170
|
const visibleRange = drawState.yMax - drawState.yMin;
|
|
@@ -4705,13 +4787,18 @@ function createChart(element, options = {}) {
|
|
|
4705
4787
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4706
4788
|
if (drawingHit) {
|
|
4707
4789
|
selectedDrawingId = drawingHit.drawing.id;
|
|
4708
|
-
|
|
4790
|
+
const payload = {
|
|
4709
4791
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
4710
4792
|
target: drawingHit.target,
|
|
4711
4793
|
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4712
4794
|
x: point.x,
|
|
4713
4795
|
y: point.y
|
|
4714
|
-
}
|
|
4796
|
+
};
|
|
4797
|
+
if (drawingHit.drawing.type === "text" || drawingHit.drawing.type === "note") {
|
|
4798
|
+
drawingEditTextHandler?.(payload);
|
|
4799
|
+
} else {
|
|
4800
|
+
drawingDoubleClickHandler?.(payload);
|
|
4801
|
+
}
|
|
4715
4802
|
return;
|
|
4716
4803
|
}
|
|
4717
4804
|
}
|
|
@@ -5028,6 +5115,9 @@ function createChart(element, options = {}) {
|
|
|
5028
5115
|
const onDrawingDoubleClick = (handler) => {
|
|
5029
5116
|
drawingDoubleClickHandler = handler;
|
|
5030
5117
|
};
|
|
5118
|
+
const onDrawingEditText = (handler) => {
|
|
5119
|
+
drawingEditTextHandler = handler;
|
|
5120
|
+
};
|
|
5031
5121
|
const onDrawingHover = (handler) => {
|
|
5032
5122
|
drawingHoverHandler = handler;
|
|
5033
5123
|
};
|
|
@@ -5086,6 +5176,7 @@ function createChart(element, options = {}) {
|
|
|
5086
5176
|
onDrawingsChange,
|
|
5087
5177
|
onDrawingSelect,
|
|
5088
5178
|
onDrawingDoubleClick,
|
|
5179
|
+
onDrawingEditText,
|
|
5089
5180
|
setSelectedDrawing,
|
|
5090
5181
|
onDrawingHover,
|
|
5091
5182
|
setDrawingDefaults,
|
|
@@ -44,7 +44,7 @@ interface ChartOptions {
|
|
|
44
44
|
drawings?: DrawingObjectOptions[];
|
|
45
45
|
}
|
|
46
46
|
type IndicatorPane = "overlay" | "separate";
|
|
47
|
-
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range";
|
|
47
|
+
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "text" | "note";
|
|
48
48
|
interface DrawingPoint {
|
|
49
49
|
index: number;
|
|
50
50
|
price: number;
|
|
@@ -73,6 +73,7 @@ interface DrawingObjectOptions {
|
|
|
73
73
|
leverage?: number;
|
|
74
74
|
pointValue?: number;
|
|
75
75
|
qtyPrecision?: number;
|
|
76
|
+
fontSize?: number;
|
|
76
77
|
}
|
|
77
78
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
78
79
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -91,7 +92,7 @@ interface DrawingHoverEvent {
|
|
|
91
92
|
x: number;
|
|
92
93
|
y: number;
|
|
93
94
|
}
|
|
94
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
95
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision" | "fontSize">>;
|
|
95
96
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
96
97
|
id?: string;
|
|
97
98
|
type: string;
|
|
@@ -428,6 +429,7 @@ interface ChartInstance {
|
|
|
428
429
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
429
430
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
431
|
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
432
|
+
onDrawingEditText: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
431
433
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
432
434
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
433
435
|
setSelectedDrawing: (id: string | null) => void;
|
|
@@ -942,6 +942,7 @@ function createChart(element, options = {}) {
|
|
|
942
942
|
leverage: Number(drawing.leverage) || 1,
|
|
943
943
|
pointValue: Number(drawing.pointValue) || 1,
|
|
944
944
|
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
945
|
+
fontSize: Math.max(6, Number(drawing.fontSize) || 14),
|
|
945
946
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
946
947
|
});
|
|
947
948
|
const serializeDrawing = (drawing) => ({
|
|
@@ -961,6 +962,7 @@ function createChart(element, options = {}) {
|
|
|
961
962
|
leverage: drawing.leverage,
|
|
962
963
|
pointValue: drawing.pointValue,
|
|
963
964
|
qtyPrecision: drawing.qtyPrecision,
|
|
965
|
+
fontSize: drawing.fontSize,
|
|
964
966
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
965
967
|
});
|
|
966
968
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -971,6 +973,7 @@ function createChart(element, options = {}) {
|
|
|
971
973
|
let drawingsChangeHandler = null;
|
|
972
974
|
let drawingSelectHandler = null;
|
|
973
975
|
let drawingDoubleClickHandler = null;
|
|
976
|
+
let drawingEditTextHandler = null;
|
|
974
977
|
let drawingHoverHandler = null;
|
|
975
978
|
let lastHoveredDrawingId = null;
|
|
976
979
|
let selectedDrawingId = null;
|
|
@@ -2609,6 +2612,46 @@ function createChart(element, options = {}) {
|
|
|
2609
2612
|
drawDrawingLabel(drawing.label, midX, topY - 4, drawing.color);
|
|
2610
2613
|
}
|
|
2611
2614
|
}
|
|
2615
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
2616
|
+
const anchor = drawing.points[0];
|
|
2617
|
+
if (anchor) {
|
|
2618
|
+
const ax = xFromDrawingPoint(anchor);
|
|
2619
|
+
const ay = yFromPrice(anchor.price);
|
|
2620
|
+
const isNote = drawing.type === "note";
|
|
2621
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
2622
|
+
const prevFont = ctx.font;
|
|
2623
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
2624
|
+
ctx.textAlign = "left";
|
|
2625
|
+
ctx.textBaseline = "top";
|
|
2626
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
2627
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
2628
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
2629
|
+
const padX = isNote ? 8 : 2;
|
|
2630
|
+
const padY = isNote ? 6 : 1;
|
|
2631
|
+
const blockW = textW + padX * 2;
|
|
2632
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
2633
|
+
ctx.save();
|
|
2634
|
+
ctx.globalAlpha = draft ? 0.7 : 1;
|
|
2635
|
+
if (isNote) {
|
|
2636
|
+
ctx.fillStyle = hexToRgba(drawing.color, 0.14);
|
|
2637
|
+
fillRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2638
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.5);
|
|
2639
|
+
ctx.lineWidth = 1;
|
|
2640
|
+
strokeRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2641
|
+
}
|
|
2642
|
+
ctx.fillStyle = drawing.color;
|
|
2643
|
+
lines.forEach((line, lineIndex) => ctx.fillText(line, ax + padX, ay + padY + lineIndex * lineH));
|
|
2644
|
+
ctx.restore();
|
|
2645
|
+
ctx.font = prevFont;
|
|
2646
|
+
if (isSelected) {
|
|
2647
|
+
ctx.save();
|
|
2648
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.9);
|
|
2649
|
+
ctx.lineWidth = 1;
|
|
2650
|
+
ctx.setLineDash([]);
|
|
2651
|
+
strokeRoundedRect(ax - 2, ay - 2, blockW + 4, blockH + 4, 3);
|
|
2652
|
+
ctx.restore();
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2612
2655
|
}
|
|
2613
2656
|
ctx.restore();
|
|
2614
2657
|
};
|
|
@@ -3857,6 +3900,27 @@ function createChart(element, options = {}) {
|
|
|
3857
3900
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
3858
3901
|
return { drawing, target: "line" };
|
|
3859
3902
|
}
|
|
3903
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
3904
|
+
const anchor = drawing.points[0];
|
|
3905
|
+
if (!anchor) continue;
|
|
3906
|
+
const ax = canvasXFromDrawingPoint(anchor);
|
|
3907
|
+
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
3908
|
+
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
3909
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
3910
|
+
const prevFont = ctx.font;
|
|
3911
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
3912
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
3913
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
3914
|
+
ctx.font = prevFont;
|
|
3915
|
+
const isNote = drawing.type === "note";
|
|
3916
|
+
const padX = isNote ? 8 : 2;
|
|
3917
|
+
const padY = isNote ? 6 : 1;
|
|
3918
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
3919
|
+
const blockW = textW + padX * 2;
|
|
3920
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
3921
|
+
if (x >= ax && x <= ax + blockW && y >= ay && y <= ay + blockH) {
|
|
3922
|
+
return { drawing, target: "line" };
|
|
3923
|
+
}
|
|
3860
3924
|
}
|
|
3861
3925
|
}
|
|
3862
3926
|
return null;
|
|
@@ -4057,6 +4121,24 @@ function createChart(element, options = {}) {
|
|
|
4057
4121
|
draw();
|
|
4058
4122
|
return true;
|
|
4059
4123
|
}
|
|
4124
|
+
if (activeDrawingTool === "text" || activeDrawingTool === "note") {
|
|
4125
|
+
const defaults = getDrawingToolDefaults(activeDrawingTool);
|
|
4126
|
+
const created = normalizeDrawingState({
|
|
4127
|
+
type: activeDrawingTool,
|
|
4128
|
+
points: [point],
|
|
4129
|
+
color: defaults.color ?? "#e2e8f0",
|
|
4130
|
+
style: defaults.style ?? "solid",
|
|
4131
|
+
width: defaults.width ?? 1,
|
|
4132
|
+
...defaults.fontSize === void 0 ? {} : { fontSize: defaults.fontSize },
|
|
4133
|
+
label: ""
|
|
4134
|
+
});
|
|
4135
|
+
drawings.push(created);
|
|
4136
|
+
selectedDrawingId = created.id;
|
|
4137
|
+
emitDrawingsChange();
|
|
4138
|
+
draw();
|
|
4139
|
+
drawingEditTextHandler?.({ drawing: serializeDrawing(created), target: "line", x, y });
|
|
4140
|
+
return true;
|
|
4141
|
+
}
|
|
4060
4142
|
if (activeDrawingTool === "price-range") {
|
|
4061
4143
|
const tick = getConfiguredTickSize();
|
|
4062
4144
|
const visibleRange = drawState.yMax - drawState.yMin;
|
|
@@ -4679,13 +4761,18 @@ function createChart(element, options = {}) {
|
|
|
4679
4761
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4680
4762
|
if (drawingHit) {
|
|
4681
4763
|
selectedDrawingId = drawingHit.drawing.id;
|
|
4682
|
-
|
|
4764
|
+
const payload = {
|
|
4683
4765
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
4684
4766
|
target: drawingHit.target,
|
|
4685
4767
|
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4686
4768
|
x: point.x,
|
|
4687
4769
|
y: point.y
|
|
4688
|
-
}
|
|
4770
|
+
};
|
|
4771
|
+
if (drawingHit.drawing.type === "text" || drawingHit.drawing.type === "note") {
|
|
4772
|
+
drawingEditTextHandler?.(payload);
|
|
4773
|
+
} else {
|
|
4774
|
+
drawingDoubleClickHandler?.(payload);
|
|
4775
|
+
}
|
|
4689
4776
|
return;
|
|
4690
4777
|
}
|
|
4691
4778
|
}
|
|
@@ -5002,6 +5089,9 @@ function createChart(element, options = {}) {
|
|
|
5002
5089
|
const onDrawingDoubleClick = (handler) => {
|
|
5003
5090
|
drawingDoubleClickHandler = handler;
|
|
5004
5091
|
};
|
|
5092
|
+
const onDrawingEditText = (handler) => {
|
|
5093
|
+
drawingEditTextHandler = handler;
|
|
5094
|
+
};
|
|
5005
5095
|
const onDrawingHover = (handler) => {
|
|
5006
5096
|
drawingHoverHandler = handler;
|
|
5007
5097
|
};
|
|
@@ -5060,6 +5150,7 @@ function createChart(element, options = {}) {
|
|
|
5060
5150
|
onDrawingsChange,
|
|
5061
5151
|
onDrawingSelect,
|
|
5062
5152
|
onDrawingDoubleClick,
|
|
5153
|
+
onDrawingEditText,
|
|
5063
5154
|
setSelectedDrawing,
|
|
5064
5155
|
onDrawingHover,
|
|
5065
5156
|
setDrawingDefaults,
|
package/dist/index.cjs
CHANGED
|
@@ -968,6 +968,7 @@ function createChart(element, options = {}) {
|
|
|
968
968
|
leverage: Number(drawing.leverage) || 1,
|
|
969
969
|
pointValue: Number(drawing.pointValue) || 1,
|
|
970
970
|
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
971
|
+
fontSize: Math.max(6, Number(drawing.fontSize) || 14),
|
|
971
972
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
972
973
|
});
|
|
973
974
|
const serializeDrawing = (drawing) => ({
|
|
@@ -987,6 +988,7 @@ function createChart(element, options = {}) {
|
|
|
987
988
|
leverage: drawing.leverage,
|
|
988
989
|
pointValue: drawing.pointValue,
|
|
989
990
|
qtyPrecision: drawing.qtyPrecision,
|
|
991
|
+
fontSize: drawing.fontSize,
|
|
990
992
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
991
993
|
});
|
|
992
994
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -997,6 +999,7 @@ function createChart(element, options = {}) {
|
|
|
997
999
|
let drawingsChangeHandler = null;
|
|
998
1000
|
let drawingSelectHandler = null;
|
|
999
1001
|
let drawingDoubleClickHandler = null;
|
|
1002
|
+
let drawingEditTextHandler = null;
|
|
1000
1003
|
let drawingHoverHandler = null;
|
|
1001
1004
|
let lastHoveredDrawingId = null;
|
|
1002
1005
|
let selectedDrawingId = null;
|
|
@@ -2635,6 +2638,46 @@ function createChart(element, options = {}) {
|
|
|
2635
2638
|
drawDrawingLabel(drawing.label, midX, topY - 4, drawing.color);
|
|
2636
2639
|
}
|
|
2637
2640
|
}
|
|
2641
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
2642
|
+
const anchor = drawing.points[0];
|
|
2643
|
+
if (anchor) {
|
|
2644
|
+
const ax = xFromDrawingPoint(anchor);
|
|
2645
|
+
const ay = yFromPrice(anchor.price);
|
|
2646
|
+
const isNote = drawing.type === "note";
|
|
2647
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
2648
|
+
const prevFont = ctx.font;
|
|
2649
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
2650
|
+
ctx.textAlign = "left";
|
|
2651
|
+
ctx.textBaseline = "top";
|
|
2652
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
2653
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
2654
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
2655
|
+
const padX = isNote ? 8 : 2;
|
|
2656
|
+
const padY = isNote ? 6 : 1;
|
|
2657
|
+
const blockW = textW + padX * 2;
|
|
2658
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
2659
|
+
ctx.save();
|
|
2660
|
+
ctx.globalAlpha = draft ? 0.7 : 1;
|
|
2661
|
+
if (isNote) {
|
|
2662
|
+
ctx.fillStyle = hexToRgba(drawing.color, 0.14);
|
|
2663
|
+
fillRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2664
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.5);
|
|
2665
|
+
ctx.lineWidth = 1;
|
|
2666
|
+
strokeRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2667
|
+
}
|
|
2668
|
+
ctx.fillStyle = drawing.color;
|
|
2669
|
+
lines.forEach((line, lineIndex) => ctx.fillText(line, ax + padX, ay + padY + lineIndex * lineH));
|
|
2670
|
+
ctx.restore();
|
|
2671
|
+
ctx.font = prevFont;
|
|
2672
|
+
if (isSelected) {
|
|
2673
|
+
ctx.save();
|
|
2674
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.9);
|
|
2675
|
+
ctx.lineWidth = 1;
|
|
2676
|
+
ctx.setLineDash([]);
|
|
2677
|
+
strokeRoundedRect(ax - 2, ay - 2, blockW + 4, blockH + 4, 3);
|
|
2678
|
+
ctx.restore();
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2638
2681
|
}
|
|
2639
2682
|
ctx.restore();
|
|
2640
2683
|
};
|
|
@@ -3883,6 +3926,27 @@ function createChart(element, options = {}) {
|
|
|
3883
3926
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
3884
3927
|
return { drawing, target: "line" };
|
|
3885
3928
|
}
|
|
3929
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
3930
|
+
const anchor = drawing.points[0];
|
|
3931
|
+
if (!anchor) continue;
|
|
3932
|
+
const ax = canvasXFromDrawingPoint(anchor);
|
|
3933
|
+
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
3934
|
+
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
3935
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
3936
|
+
const prevFont = ctx.font;
|
|
3937
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
3938
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
3939
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
3940
|
+
ctx.font = prevFont;
|
|
3941
|
+
const isNote = drawing.type === "note";
|
|
3942
|
+
const padX = isNote ? 8 : 2;
|
|
3943
|
+
const padY = isNote ? 6 : 1;
|
|
3944
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
3945
|
+
const blockW = textW + padX * 2;
|
|
3946
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
3947
|
+
if (x >= ax && x <= ax + blockW && y >= ay && y <= ay + blockH) {
|
|
3948
|
+
return { drawing, target: "line" };
|
|
3949
|
+
}
|
|
3886
3950
|
}
|
|
3887
3951
|
}
|
|
3888
3952
|
return null;
|
|
@@ -4083,6 +4147,24 @@ function createChart(element, options = {}) {
|
|
|
4083
4147
|
draw();
|
|
4084
4148
|
return true;
|
|
4085
4149
|
}
|
|
4150
|
+
if (activeDrawingTool === "text" || activeDrawingTool === "note") {
|
|
4151
|
+
const defaults = getDrawingToolDefaults(activeDrawingTool);
|
|
4152
|
+
const created = normalizeDrawingState({
|
|
4153
|
+
type: activeDrawingTool,
|
|
4154
|
+
points: [point],
|
|
4155
|
+
color: defaults.color ?? "#e2e8f0",
|
|
4156
|
+
style: defaults.style ?? "solid",
|
|
4157
|
+
width: defaults.width ?? 1,
|
|
4158
|
+
...defaults.fontSize === void 0 ? {} : { fontSize: defaults.fontSize },
|
|
4159
|
+
label: ""
|
|
4160
|
+
});
|
|
4161
|
+
drawings.push(created);
|
|
4162
|
+
selectedDrawingId = created.id;
|
|
4163
|
+
emitDrawingsChange();
|
|
4164
|
+
draw();
|
|
4165
|
+
drawingEditTextHandler?.({ drawing: serializeDrawing(created), target: "line", x, y });
|
|
4166
|
+
return true;
|
|
4167
|
+
}
|
|
4086
4168
|
if (activeDrawingTool === "price-range") {
|
|
4087
4169
|
const tick = getConfiguredTickSize();
|
|
4088
4170
|
const visibleRange = drawState.yMax - drawState.yMin;
|
|
@@ -4705,13 +4787,18 @@ function createChart(element, options = {}) {
|
|
|
4705
4787
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4706
4788
|
if (drawingHit) {
|
|
4707
4789
|
selectedDrawingId = drawingHit.drawing.id;
|
|
4708
|
-
|
|
4790
|
+
const payload = {
|
|
4709
4791
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
4710
4792
|
target: drawingHit.target,
|
|
4711
4793
|
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4712
4794
|
x: point.x,
|
|
4713
4795
|
y: point.y
|
|
4714
|
-
}
|
|
4796
|
+
};
|
|
4797
|
+
if (drawingHit.drawing.type === "text" || drawingHit.drawing.type === "note") {
|
|
4798
|
+
drawingEditTextHandler?.(payload);
|
|
4799
|
+
} else {
|
|
4800
|
+
drawingDoubleClickHandler?.(payload);
|
|
4801
|
+
}
|
|
4715
4802
|
return;
|
|
4716
4803
|
}
|
|
4717
4804
|
}
|
|
@@ -5028,6 +5115,9 @@ function createChart(element, options = {}) {
|
|
|
5028
5115
|
const onDrawingDoubleClick = (handler) => {
|
|
5029
5116
|
drawingDoubleClickHandler = handler;
|
|
5030
5117
|
};
|
|
5118
|
+
const onDrawingEditText = (handler) => {
|
|
5119
|
+
drawingEditTextHandler = handler;
|
|
5120
|
+
};
|
|
5031
5121
|
const onDrawingHover = (handler) => {
|
|
5032
5122
|
drawingHoverHandler = handler;
|
|
5033
5123
|
};
|
|
@@ -5086,6 +5176,7 @@ function createChart(element, options = {}) {
|
|
|
5086
5176
|
onDrawingsChange,
|
|
5087
5177
|
onDrawingSelect,
|
|
5088
5178
|
onDrawingDoubleClick,
|
|
5179
|
+
onDrawingEditText,
|
|
5089
5180
|
setSelectedDrawing,
|
|
5090
5181
|
onDrawingHover,
|
|
5091
5182
|
setDrawingDefaults,
|
package/dist/index.d.cts
CHANGED
|
@@ -44,7 +44,7 @@ interface ChartOptions {
|
|
|
44
44
|
drawings?: DrawingObjectOptions[];
|
|
45
45
|
}
|
|
46
46
|
type IndicatorPane = "overlay" | "separate";
|
|
47
|
-
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range";
|
|
47
|
+
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "text" | "note";
|
|
48
48
|
interface DrawingPoint {
|
|
49
49
|
index: number;
|
|
50
50
|
price: number;
|
|
@@ -73,6 +73,7 @@ interface DrawingObjectOptions {
|
|
|
73
73
|
leverage?: number;
|
|
74
74
|
pointValue?: number;
|
|
75
75
|
qtyPrecision?: number;
|
|
76
|
+
fontSize?: number;
|
|
76
77
|
}
|
|
77
78
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
78
79
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -91,7 +92,7 @@ interface DrawingHoverEvent {
|
|
|
91
92
|
x: number;
|
|
92
93
|
y: number;
|
|
93
94
|
}
|
|
94
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
95
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision" | "fontSize">>;
|
|
95
96
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
96
97
|
id?: string;
|
|
97
98
|
type: string;
|
|
@@ -428,6 +429,7 @@ interface ChartInstance {
|
|
|
428
429
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
429
430
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
431
|
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
432
|
+
onDrawingEditText: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
431
433
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
432
434
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
433
435
|
setSelectedDrawing: (id: string | null) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ interface ChartOptions {
|
|
|
44
44
|
drawings?: DrawingObjectOptions[];
|
|
45
45
|
}
|
|
46
46
|
type IndicatorPane = "overlay" | "separate";
|
|
47
|
-
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range";
|
|
47
|
+
type DrawingToolType = "horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "text" | "note";
|
|
48
48
|
interface DrawingPoint {
|
|
49
49
|
index: number;
|
|
50
50
|
price: number;
|
|
@@ -73,6 +73,7 @@ interface DrawingObjectOptions {
|
|
|
73
73
|
leverage?: number;
|
|
74
74
|
pointValue?: number;
|
|
75
75
|
qtyPrecision?: number;
|
|
76
|
+
fontSize?: number;
|
|
76
77
|
}
|
|
77
78
|
/** Default colors for position tools: [profit, loss, label text]. */
|
|
78
79
|
declare const POSITION_DEFAULT_COLORS: string[];
|
|
@@ -91,7 +92,7 @@ interface DrawingHoverEvent {
|
|
|
91
92
|
x: number;
|
|
92
93
|
y: number;
|
|
93
94
|
}
|
|
94
|
-
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision">>;
|
|
95
|
+
type DrawingDefaults = Partial<Pick<DrawingObjectOptions, "color" | "colors" | "style" | "width" | "accountSize" | "lotSize" | "risk" | "riskMode" | "leverage" | "pointValue" | "qtyPrecision" | "fontSize">>;
|
|
95
96
|
interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
|
|
96
97
|
id?: string;
|
|
97
98
|
type: string;
|
|
@@ -428,6 +429,7 @@ interface ChartInstance {
|
|
|
428
429
|
onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
|
|
429
430
|
onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
430
431
|
onDrawingDoubleClick: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
432
|
+
onDrawingEditText: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
|
|
431
433
|
onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
|
|
432
434
|
setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
|
|
433
435
|
setSelectedDrawing: (id: string | null) => void;
|
package/dist/index.js
CHANGED
|
@@ -942,6 +942,7 @@ function createChart(element, options = {}) {
|
|
|
942
942
|
leverage: Number(drawing.leverage) || 1,
|
|
943
943
|
pointValue: Number(drawing.pointValue) || 1,
|
|
944
944
|
qtyPrecision: Number.isFinite(drawing.qtyPrecision) ? Math.max(0, Math.floor(Number(drawing.qtyPrecision))) : 0,
|
|
945
|
+
fontSize: Math.max(6, Number(drawing.fontSize) || 14),
|
|
945
946
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
946
947
|
});
|
|
947
948
|
const serializeDrawing = (drawing) => ({
|
|
@@ -961,6 +962,7 @@ function createChart(element, options = {}) {
|
|
|
961
962
|
leverage: drawing.leverage,
|
|
962
963
|
pointValue: drawing.pointValue,
|
|
963
964
|
qtyPrecision: drawing.qtyPrecision,
|
|
965
|
+
fontSize: drawing.fontSize,
|
|
964
966
|
...drawing.label === void 0 ? {} : { label: drawing.label }
|
|
965
967
|
});
|
|
966
968
|
let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
|
|
@@ -971,6 +973,7 @@ function createChart(element, options = {}) {
|
|
|
971
973
|
let drawingsChangeHandler = null;
|
|
972
974
|
let drawingSelectHandler = null;
|
|
973
975
|
let drawingDoubleClickHandler = null;
|
|
976
|
+
let drawingEditTextHandler = null;
|
|
974
977
|
let drawingHoverHandler = null;
|
|
975
978
|
let lastHoveredDrawingId = null;
|
|
976
979
|
let selectedDrawingId = null;
|
|
@@ -2609,6 +2612,46 @@ function createChart(element, options = {}) {
|
|
|
2609
2612
|
drawDrawingLabel(drawing.label, midX, topY - 4, drawing.color);
|
|
2610
2613
|
}
|
|
2611
2614
|
}
|
|
2615
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
2616
|
+
const anchor = drawing.points[0];
|
|
2617
|
+
if (anchor) {
|
|
2618
|
+
const ax = xFromDrawingPoint(anchor);
|
|
2619
|
+
const ay = yFromPrice(anchor.price);
|
|
2620
|
+
const isNote = drawing.type === "note";
|
|
2621
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
2622
|
+
const prevFont = ctx.font;
|
|
2623
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
2624
|
+
ctx.textAlign = "left";
|
|
2625
|
+
ctx.textBaseline = "top";
|
|
2626
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
2627
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
2628
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
2629
|
+
const padX = isNote ? 8 : 2;
|
|
2630
|
+
const padY = isNote ? 6 : 1;
|
|
2631
|
+
const blockW = textW + padX * 2;
|
|
2632
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
2633
|
+
ctx.save();
|
|
2634
|
+
ctx.globalAlpha = draft ? 0.7 : 1;
|
|
2635
|
+
if (isNote) {
|
|
2636
|
+
ctx.fillStyle = hexToRgba(drawing.color, 0.14);
|
|
2637
|
+
fillRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2638
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.5);
|
|
2639
|
+
ctx.lineWidth = 1;
|
|
2640
|
+
strokeRoundedRect(ax, ay, blockW, blockH, 4);
|
|
2641
|
+
}
|
|
2642
|
+
ctx.fillStyle = drawing.color;
|
|
2643
|
+
lines.forEach((line, lineIndex) => ctx.fillText(line, ax + padX, ay + padY + lineIndex * lineH));
|
|
2644
|
+
ctx.restore();
|
|
2645
|
+
ctx.font = prevFont;
|
|
2646
|
+
if (isSelected) {
|
|
2647
|
+
ctx.save();
|
|
2648
|
+
ctx.strokeStyle = hexToRgba(drawing.color, 0.9);
|
|
2649
|
+
ctx.lineWidth = 1;
|
|
2650
|
+
ctx.setLineDash([]);
|
|
2651
|
+
strokeRoundedRect(ax - 2, ay - 2, blockW + 4, blockH + 4, 3);
|
|
2652
|
+
ctx.restore();
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2612
2655
|
}
|
|
2613
2656
|
ctx.restore();
|
|
2614
2657
|
};
|
|
@@ -3857,6 +3900,27 @@ function createChart(element, options = {}) {
|
|
|
3857
3900
|
if (x >= Math.min(px0, px1) && x <= Math.max(px0, px1) && y >= Math.min(y0, y1) && y <= Math.max(y0, y1)) {
|
|
3858
3901
|
return { drawing, target: "line" };
|
|
3859
3902
|
}
|
|
3903
|
+
} else if (drawing.type === "text" || drawing.type === "note") {
|
|
3904
|
+
const anchor = drawing.points[0];
|
|
3905
|
+
if (!anchor) continue;
|
|
3906
|
+
const ax = canvasXFromDrawingPoint(anchor);
|
|
3907
|
+
const ay = canvasYFromDrawingPrice(anchor.price);
|
|
3908
|
+
if (Math.hypot(x - ax, y - ay) <= 9) return { drawing, target: "handle", pointIndex: 0 };
|
|
3909
|
+
const fontSize = Math.max(6, drawing.fontSize);
|
|
3910
|
+
const prevFont = ctx.font;
|
|
3911
|
+
ctx.font = `500 ${fontSize}px ${mergedOptions.fontFamily}`;
|
|
3912
|
+
const lines = (drawing.label ?? "").split("\n");
|
|
3913
|
+
const textW = Math.max(1, ...lines.map((line) => ctx.measureText(line).width));
|
|
3914
|
+
ctx.font = prevFont;
|
|
3915
|
+
const isNote = drawing.type === "note";
|
|
3916
|
+
const padX = isNote ? 8 : 2;
|
|
3917
|
+
const padY = isNote ? 6 : 1;
|
|
3918
|
+
const lineH = Math.round(fontSize * 1.35);
|
|
3919
|
+
const blockW = textW + padX * 2;
|
|
3920
|
+
const blockH = lines.length * lineH + padY * 2;
|
|
3921
|
+
if (x >= ax && x <= ax + blockW && y >= ay && y <= ay + blockH) {
|
|
3922
|
+
return { drawing, target: "line" };
|
|
3923
|
+
}
|
|
3860
3924
|
}
|
|
3861
3925
|
}
|
|
3862
3926
|
return null;
|
|
@@ -4057,6 +4121,24 @@ function createChart(element, options = {}) {
|
|
|
4057
4121
|
draw();
|
|
4058
4122
|
return true;
|
|
4059
4123
|
}
|
|
4124
|
+
if (activeDrawingTool === "text" || activeDrawingTool === "note") {
|
|
4125
|
+
const defaults = getDrawingToolDefaults(activeDrawingTool);
|
|
4126
|
+
const created = normalizeDrawingState({
|
|
4127
|
+
type: activeDrawingTool,
|
|
4128
|
+
points: [point],
|
|
4129
|
+
color: defaults.color ?? "#e2e8f0",
|
|
4130
|
+
style: defaults.style ?? "solid",
|
|
4131
|
+
width: defaults.width ?? 1,
|
|
4132
|
+
...defaults.fontSize === void 0 ? {} : { fontSize: defaults.fontSize },
|
|
4133
|
+
label: ""
|
|
4134
|
+
});
|
|
4135
|
+
drawings.push(created);
|
|
4136
|
+
selectedDrawingId = created.id;
|
|
4137
|
+
emitDrawingsChange();
|
|
4138
|
+
draw();
|
|
4139
|
+
drawingEditTextHandler?.({ drawing: serializeDrawing(created), target: "line", x, y });
|
|
4140
|
+
return true;
|
|
4141
|
+
}
|
|
4060
4142
|
if (activeDrawingTool === "price-range") {
|
|
4061
4143
|
const tick = getConfiguredTickSize();
|
|
4062
4144
|
const visibleRange = drawState.yMax - drawState.yMin;
|
|
@@ -4679,13 +4761,18 @@ function createChart(element, options = {}) {
|
|
|
4679
4761
|
const drawingHit = getDrawingHit(point.x, point.y);
|
|
4680
4762
|
if (drawingHit) {
|
|
4681
4763
|
selectedDrawingId = drawingHit.drawing.id;
|
|
4682
|
-
|
|
4764
|
+
const payload = {
|
|
4683
4765
|
drawing: serializeDrawing(drawingHit.drawing),
|
|
4684
4766
|
target: drawingHit.target,
|
|
4685
4767
|
...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
|
|
4686
4768
|
x: point.x,
|
|
4687
4769
|
y: point.y
|
|
4688
|
-
}
|
|
4770
|
+
};
|
|
4771
|
+
if (drawingHit.drawing.type === "text" || drawingHit.drawing.type === "note") {
|
|
4772
|
+
drawingEditTextHandler?.(payload);
|
|
4773
|
+
} else {
|
|
4774
|
+
drawingDoubleClickHandler?.(payload);
|
|
4775
|
+
}
|
|
4689
4776
|
return;
|
|
4690
4777
|
}
|
|
4691
4778
|
}
|
|
@@ -5002,6 +5089,9 @@ function createChart(element, options = {}) {
|
|
|
5002
5089
|
const onDrawingDoubleClick = (handler) => {
|
|
5003
5090
|
drawingDoubleClickHandler = handler;
|
|
5004
5091
|
};
|
|
5092
|
+
const onDrawingEditText = (handler) => {
|
|
5093
|
+
drawingEditTextHandler = handler;
|
|
5094
|
+
};
|
|
5005
5095
|
const onDrawingHover = (handler) => {
|
|
5006
5096
|
drawingHoverHandler = handler;
|
|
5007
5097
|
};
|
|
@@ -5060,6 +5150,7 @@ function createChart(element, options = {}) {
|
|
|
5060
5150
|
onDrawingsChange,
|
|
5061
5151
|
onDrawingSelect,
|
|
5062
5152
|
onDrawingDoubleClick,
|
|
5153
|
+
onDrawingEditText,
|
|
5063
5154
|
setSelectedDrawing,
|
|
5064
5155
|
onDrawingHover,
|
|
5065
5156
|
setDrawingDefaults,
|
package/docs/API.md
CHANGED
|
@@ -483,6 +483,7 @@ Use `getDrawings()` / `setDrawings()` for persistence.
|
|
|
483
483
|
- `resetViewport(): void` (fit x + reset y auto-scale)
|
|
484
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)
|
|
485
485
|
- `onDrawingDoubleClick(handler): void` (fires when a drawing is double-clicked; use it to open a settings dialog, e.g. for position tools)
|
|
486
|
+
- `onDrawingEditText(handler): void` (fires when a `text`/`note` tool is placed or double-clicked; use it to show an inline text editor at `{x, y}` and write the result back via `updateDrawing(id, { label })`). `text`/`note` drawings store their content in `label` and size in `fontSize`.
|
|
486
487
|
- `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`)
|
|
487
488
|
- `getActiveDrawingTool(): DrawingToolType | null`
|
|
488
489
|
- `setDrawings(drawings: DrawingObjectOptions[]): void`
|