@pradeepjadhav/trading-reload-chart 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -21
- package/dist/canvas/layers/ShapesLayer/FibRetracementShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/LineShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/PathShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/RectangleShape.d.ts +1 -1
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.constants.d.ts +10 -0
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.d.ts +11 -0
- package/dist/canvas/layers/ShapesLayer/ShapesLayer.types.d.ts +7 -28
- package/dist/canvas/layers/ShapesLayer/ShortLongPosition.d.ts +2 -3
- package/dist/chart/ChartController.types.d.ts +12 -0
- package/dist/trading-reload-chart.js +899 -874
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { forwardRef as
|
|
2
|
-
import { jsx as
|
|
1
|
+
import { forwardRef as Rt, useEffect as st, useImperativeHandle as Dt, useRef as N } from "react";
|
|
2
|
+
import { jsx as At } from "react/jsx-runtime";
|
|
3
3
|
var h = {
|
|
4
4
|
primary: "#7959F7",
|
|
5
5
|
blue: "#2962FF",
|
|
@@ -18,61 +18,43 @@ var h = {
|
|
|
18
18
|
axisYTick: "rgba(255, 255, 255, 0.40)",
|
|
19
19
|
divider: "rgba(255,255,255,0.12)",
|
|
20
20
|
crosshairLabelBackground: "#494949"
|
|
21
|
-
},
|
|
21
|
+
}, y = {
|
|
22
22
|
...h,
|
|
23
23
|
gray: "#808080",
|
|
24
24
|
orange: "#ff9500",
|
|
25
|
-
purple: "#af52de"
|
|
26
|
-
|
|
27
|
-
handleFill: h.background
|
|
28
|
-
}, et = {
|
|
25
|
+
purple: "#af52de"
|
|
26
|
+
}, rt = {
|
|
29
27
|
defaultWidthCandles: 10,
|
|
30
28
|
defaultStopLossPercent: 0.1,
|
|
31
29
|
defaultRiskRewardRatio: 1.5,
|
|
32
|
-
profitFillColor:
|
|
30
|
+
profitFillColor: y.green,
|
|
33
31
|
profitFillOpacity: 0.18,
|
|
34
|
-
lossFillColor:
|
|
32
|
+
lossFillColor: y.red,
|
|
35
33
|
lossFillOpacity: 0.18,
|
|
36
|
-
borderColor:
|
|
34
|
+
borderColor: y.gray,
|
|
37
35
|
borderOpacity: 0,
|
|
38
36
|
borderWidth: 1,
|
|
39
37
|
borderStyle: "solid",
|
|
40
|
-
midLineColor:
|
|
38
|
+
midLineColor: y.gray,
|
|
41
39
|
midLineOpacity: 0.9,
|
|
42
40
|
midLineWidth: 0.5,
|
|
43
|
-
midLineStyle: "solid"
|
|
44
|
-
|
|
45
|
-
handleBorderColor: f.handleBorder,
|
|
46
|
-
handleBorderThickness: 1.5,
|
|
47
|
-
handleRadius: 5,
|
|
48
|
-
hoverLineWidth: 2,
|
|
49
|
-
selectedLineWidth: 2
|
|
50
|
-
}, Dt = {
|
|
41
|
+
midLineStyle: "solid"
|
|
42
|
+
}, Xt = {
|
|
51
43
|
trendline: {
|
|
52
44
|
lineWidth: 1,
|
|
53
|
-
lineColor:
|
|
45
|
+
lineColor: y.blue,
|
|
54
46
|
lineOpacity: 1,
|
|
55
47
|
lineStyle: "solid",
|
|
56
|
-
fillColor:
|
|
57
|
-
fillOpacity: 0
|
|
58
|
-
handleColor: f.handleFill,
|
|
59
|
-
handleBorderColor: f.handleBorder,
|
|
60
|
-
handleRadius: 5,
|
|
61
|
-
hoverLineWidth: 1,
|
|
62
|
-
selectedLineWidth: 1.1
|
|
48
|
+
fillColor: y.blue,
|
|
49
|
+
fillOpacity: 0
|
|
63
50
|
},
|
|
64
51
|
rectangle: {
|
|
65
52
|
lineWidth: 1,
|
|
66
|
-
lineColor:
|
|
53
|
+
lineColor: y.purple,
|
|
67
54
|
lineOpacity: 0.6,
|
|
68
55
|
lineStyle: "solid",
|
|
69
|
-
fillColor:
|
|
56
|
+
fillColor: y.purple,
|
|
70
57
|
fillOpacity: 0.06,
|
|
71
|
-
handleColor: f.handleFill,
|
|
72
|
-
handleBorderColor: f.handleBorder,
|
|
73
|
-
handleRadius: 5,
|
|
74
|
-
hoverLineWidth: 1,
|
|
75
|
-
selectedLineWidth: 1.1,
|
|
76
58
|
textColor: h.white,
|
|
77
59
|
textOpacity: 1,
|
|
78
60
|
textFontFamily: "Arial",
|
|
@@ -80,23 +62,18 @@ var h = {
|
|
|
80
62
|
},
|
|
81
63
|
path: {
|
|
82
64
|
lineWidth: 1,
|
|
83
|
-
lineColor:
|
|
65
|
+
lineColor: y.yellow,
|
|
84
66
|
lineOpacity: 0.8,
|
|
85
67
|
lineStyle: "solid",
|
|
86
|
-
fillColor:
|
|
87
|
-
fillOpacity: 0
|
|
88
|
-
handleColor: f.handleFill,
|
|
89
|
-
handleBorderColor: f.handleBorder,
|
|
90
|
-
handleRadius: 5,
|
|
91
|
-
hoverLineWidth: 1,
|
|
92
|
-
selectedLineWidth: 1.1
|
|
68
|
+
fillColor: y.yellow,
|
|
69
|
+
fillOpacity: 0
|
|
93
70
|
},
|
|
94
71
|
fibRetracement: {
|
|
95
72
|
levels: [
|
|
96
73
|
{
|
|
97
74
|
level: 1,
|
|
98
75
|
label: "1",
|
|
99
|
-
color:
|
|
76
|
+
color: y.gray,
|
|
100
77
|
opacity: 0.5,
|
|
101
78
|
lineWidth: 1,
|
|
102
79
|
lineStyle: "dashed"
|
|
@@ -104,7 +81,7 @@ var h = {
|
|
|
104
81
|
{
|
|
105
82
|
level: 0.72,
|
|
106
83
|
label: "0.720",
|
|
107
|
-
color:
|
|
84
|
+
color: y.red,
|
|
108
85
|
opacity: 0.5,
|
|
109
86
|
lineWidth: 1,
|
|
110
87
|
lineStyle: "dashed"
|
|
@@ -112,7 +89,7 @@ var h = {
|
|
|
112
89
|
{
|
|
113
90
|
level: 0.618,
|
|
114
91
|
label: "0.618",
|
|
115
|
-
color:
|
|
92
|
+
color: y.orange,
|
|
116
93
|
opacity: 0.5,
|
|
117
94
|
lineWidth: 1,
|
|
118
95
|
lineStyle: "dashed"
|
|
@@ -120,7 +97,7 @@ var h = {
|
|
|
120
97
|
{
|
|
121
98
|
level: 0.5,
|
|
122
99
|
label: "0.5",
|
|
123
|
-
color:
|
|
100
|
+
color: y.purple,
|
|
124
101
|
opacity: 0.5,
|
|
125
102
|
lineWidth: 1,
|
|
126
103
|
lineStyle: "dashed"
|
|
@@ -128,22 +105,17 @@ var h = {
|
|
|
128
105
|
{
|
|
129
106
|
level: 0,
|
|
130
107
|
label: "0",
|
|
131
|
-
color:
|
|
108
|
+
color: y.gray,
|
|
132
109
|
opacity: 0.5,
|
|
133
110
|
lineWidth: 1,
|
|
134
111
|
lineStyle: "dashed"
|
|
135
112
|
}
|
|
136
113
|
],
|
|
137
|
-
fillColor:
|
|
138
|
-
fillOpacity: 0
|
|
139
|
-
handleColor: f.handleFill,
|
|
140
|
-
handleBorderColor: f.handleBorder,
|
|
141
|
-
handleRadius: 5,
|
|
142
|
-
hoverLineWidth: 1,
|
|
143
|
-
selectedLineWidth: 1
|
|
114
|
+
fillColor: y.gray,
|
|
115
|
+
fillOpacity: 0
|
|
144
116
|
},
|
|
145
|
-
longPosition: { ...
|
|
146
|
-
shortPosition: { ...
|
|
117
|
+
longPosition: { ...rt },
|
|
118
|
+
shortPosition: { ...rt },
|
|
147
119
|
previousDayHighLow: {
|
|
148
120
|
line: {
|
|
149
121
|
color: h.red,
|
|
@@ -157,12 +129,12 @@ var h = {
|
|
|
157
129
|
paddingX: 6
|
|
158
130
|
}
|
|
159
131
|
}
|
|
160
|
-
},
|
|
132
|
+
}, X = { default: "12px Arial" }, nt = {
|
|
161
133
|
width: 1,
|
|
162
134
|
opacity: 0.9,
|
|
163
135
|
style: "dashed",
|
|
164
136
|
dash: [4, 4]
|
|
165
|
-
},
|
|
137
|
+
}, _ = {
|
|
166
138
|
width: 1,
|
|
167
139
|
opacity: 0.9,
|
|
168
140
|
style: "dotted",
|
|
@@ -187,7 +159,7 @@ var h = {
|
|
|
187
159
|
showVolumeSection: !0,
|
|
188
160
|
showPnlSection: !0,
|
|
189
161
|
showCloseSection: !0
|
|
190
|
-
},
|
|
162
|
+
}, ot = {
|
|
191
163
|
width: 32,
|
|
192
164
|
height: 22,
|
|
193
165
|
gapFromStartPriceHandle: 6,
|
|
@@ -200,8 +172,8 @@ var h = {
|
|
|
200
172
|
backgroundOpacity: 0.1,
|
|
201
173
|
textColor: h.white,
|
|
202
174
|
textOpacity: 0.6,
|
|
203
|
-
font:
|
|
204
|
-
},
|
|
175
|
+
font: X.default
|
|
176
|
+
}, at = {
|
|
205
177
|
height: 22,
|
|
206
178
|
widthPNL: 80,
|
|
207
179
|
position: {
|
|
@@ -216,7 +188,7 @@ var h = {
|
|
|
216
188
|
paddingX: 10,
|
|
217
189
|
textColor: h.white,
|
|
218
190
|
textOpacity: 0.85,
|
|
219
|
-
font:
|
|
191
|
+
font: X.default
|
|
220
192
|
}, c = {
|
|
221
193
|
zoom: {
|
|
222
194
|
x: {
|
|
@@ -275,7 +247,7 @@ var h = {
|
|
|
275
247
|
borderColor: h.axisBorder,
|
|
276
248
|
borderWidth: 1,
|
|
277
249
|
textColor: h.axisText,
|
|
278
|
-
font:
|
|
250
|
+
font: X.default,
|
|
279
251
|
textAlign: "center",
|
|
280
252
|
tickColor: h.axisTick,
|
|
281
253
|
tickWidth: 1,
|
|
@@ -287,7 +259,7 @@ var h = {
|
|
|
287
259
|
borderColor: h.crosshairLabelBackground,
|
|
288
260
|
borderWidth: 1,
|
|
289
261
|
textColor: h.white,
|
|
290
|
-
font:
|
|
262
|
+
font: X.default,
|
|
291
263
|
paddingX: 8,
|
|
292
264
|
height: 26
|
|
293
265
|
}
|
|
@@ -298,7 +270,7 @@ var h = {
|
|
|
298
270
|
borderColor: h.axisBorder,
|
|
299
271
|
borderWidth: 1,
|
|
300
272
|
textColor: h.axisText,
|
|
301
|
-
font:
|
|
273
|
+
font: X.default,
|
|
302
274
|
textAlign: "left",
|
|
303
275
|
tickCount: 12,
|
|
304
276
|
tickColor: h.axisYTick,
|
|
@@ -311,14 +283,14 @@ var h = {
|
|
|
311
283
|
borderColor: h.crosshairLabelBackground,
|
|
312
284
|
borderWidth: 1,
|
|
313
285
|
textColor: h.white,
|
|
314
|
-
font:
|
|
286
|
+
font: X.default,
|
|
315
287
|
paddingX: 8,
|
|
316
288
|
height: 20
|
|
317
289
|
}
|
|
318
290
|
}
|
|
319
291
|
},
|
|
320
292
|
tradeHandles: {
|
|
321
|
-
font:
|
|
293
|
+
font: X.default,
|
|
322
294
|
textColor: h.white,
|
|
323
295
|
textOpacity: 0.8,
|
|
324
296
|
pnlTextColors: {
|
|
@@ -335,7 +307,7 @@ var h = {
|
|
|
335
307
|
showVolumeSection: !1
|
|
336
308
|
},
|
|
337
309
|
handleLine: {
|
|
338
|
-
...
|
|
310
|
+
...nt,
|
|
339
311
|
color: h.red
|
|
340
312
|
}
|
|
341
313
|
},
|
|
@@ -349,7 +321,7 @@ var h = {
|
|
|
349
321
|
showVolumeSection: !1
|
|
350
322
|
},
|
|
351
323
|
handleLine: {
|
|
352
|
-
...
|
|
324
|
+
...nt,
|
|
353
325
|
color: h.green
|
|
354
326
|
}
|
|
355
327
|
},
|
|
@@ -366,35 +338,35 @@ var h = {
|
|
|
366
338
|
visible: !0,
|
|
367
339
|
dragActivationThresholdPx: 2,
|
|
368
340
|
slHandle: {
|
|
369
|
-
...
|
|
341
|
+
...ot,
|
|
370
342
|
borderColor: h.red,
|
|
371
343
|
backgroundColor: h.slBackground,
|
|
372
344
|
textColor: h.red
|
|
373
345
|
},
|
|
374
346
|
tpHandle: {
|
|
375
|
-
...
|
|
347
|
+
...ot,
|
|
376
348
|
borderColor: h.green,
|
|
377
349
|
backgroundColor: h.tpBackground,
|
|
378
350
|
textColor: h.green
|
|
379
351
|
},
|
|
380
352
|
temporarySlHandle: {
|
|
381
|
-
...
|
|
353
|
+
...at,
|
|
382
354
|
borderColor: h.red,
|
|
383
355
|
backgroundColor: h.slBackground,
|
|
384
356
|
textColor: h.red
|
|
385
357
|
},
|
|
386
358
|
temporaryTpHandle: {
|
|
387
|
-
...
|
|
359
|
+
...at,
|
|
388
360
|
borderColor: h.green,
|
|
389
361
|
backgroundColor: h.tpBackground,
|
|
390
362
|
textColor: h.green
|
|
391
363
|
},
|
|
392
364
|
temporarySlLine: {
|
|
393
|
-
...
|
|
365
|
+
..._,
|
|
394
366
|
color: h.red
|
|
395
367
|
},
|
|
396
368
|
temporaryTpLine: {
|
|
397
|
-
...
|
|
369
|
+
..._,
|
|
398
370
|
color: h.green
|
|
399
371
|
}
|
|
400
372
|
}
|
|
@@ -415,7 +387,7 @@ var h = {
|
|
|
415
387
|
opacity: 1
|
|
416
388
|
},
|
|
417
389
|
connectorLine: {
|
|
418
|
-
...
|
|
390
|
+
..._,
|
|
419
391
|
color: h.white,
|
|
420
392
|
opacity: 0.65
|
|
421
393
|
}
|
|
@@ -425,8 +397,8 @@ var h = {
|
|
|
425
397
|
bearish: h.red,
|
|
426
398
|
background: h.background
|
|
427
399
|
},
|
|
428
|
-
shapes:
|
|
429
|
-
},
|
|
400
|
+
shapes: Xt
|
|
401
|
+
}, lt = [
|
|
430
402
|
300 * 1e3,
|
|
431
403
|
900 * 1e3,
|
|
432
404
|
1800 * 1e3,
|
|
@@ -436,27 +408,27 @@ var h = {
|
|
|
436
408
|
360 * 60 * 1e3,
|
|
437
409
|
720 * 60 * 1e3,
|
|
438
410
|
1440 * 60 * 1e3
|
|
439
|
-
],
|
|
411
|
+
], It = (t) => {
|
|
440
412
|
if (t.length < 2) return 900 * 1e3;
|
|
441
413
|
const e = [];
|
|
442
414
|
for (let i = 1; i < Math.min(t.length, 10); i++) e.push(t[i].time - t[i - 1].time);
|
|
443
|
-
return e.sort((i,
|
|
444
|
-
},
|
|
445
|
-
if (t <= 0 || e <= 0) return
|
|
446
|
-
const
|
|
447
|
-
for (const a of
|
|
415
|
+
return e.sort((i, s) => i - s), e[Math.floor(e.length / 2)];
|
|
416
|
+
}, Bt = ({ candleSpacing: t, candleTimeframeMs: e, labelWidth: i, minLabelGap: s }) => {
|
|
417
|
+
if (t <= 0 || e <= 0) return lt[0];
|
|
418
|
+
const r = i + s;
|
|
419
|
+
for (const a of lt) if (a / e * t >= r) return a;
|
|
448
420
|
const n = 1440 * 60 * 1e3, o = n / e * t;
|
|
449
|
-
return n * Math.ceil(
|
|
450
|
-
},
|
|
451
|
-
const i = new Date(t),
|
|
452
|
-
return e >= 1440 * 60 * 1e3 ?
|
|
453
|
-
}, It = (t) => {
|
|
454
|
-
const e = new Date(t), i = e.getHours(), r = e.getMinutes();
|
|
455
|
-
return i === 0 && r === 0 ? String(e.getDate()) : `${String(i).padStart(2, "0")}:${String(r).padStart(2, "0")}`;
|
|
421
|
+
return n * Math.ceil(r / o);
|
|
422
|
+
}, Wt = (t, e) => {
|
|
423
|
+
const i = new Date(t), s = (i.getHours() * 60 + i.getMinutes()) * 60 * 1e3 + i.getSeconds() * 1e3 + i.getMilliseconds();
|
|
424
|
+
return e >= 1440 * 60 * 1e3 ? s === 0 : s % e === 0;
|
|
456
425
|
}, Ft = (t) => {
|
|
457
|
-
const e = new Date(t), i = e.
|
|
458
|
-
return
|
|
459
|
-
}, Yt =
|
|
426
|
+
const e = new Date(t), i = e.getHours(), s = e.getMinutes();
|
|
427
|
+
return i === 0 && s === 0 ? String(e.getDate()) : `${String(i).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
428
|
+
}, Yt = (t) => {
|
|
429
|
+
const e = new Date(t), i = e.toLocaleDateString("en-US", { weekday: "short" }), s = e.toLocaleDateString("en-US", { month: "short" });
|
|
430
|
+
return `${i} ${e.getDate()} ${s} ${e.getHours().toString().padStart(2, "0")}.${e.getMinutes().toString().padStart(2, "0")}`;
|
|
431
|
+
}, Ot = class {
|
|
460
432
|
#t;
|
|
461
433
|
#e;
|
|
462
434
|
candles;
|
|
@@ -489,10 +461,10 @@ var h = {
|
|
|
489
461
|
}
|
|
490
462
|
drawCrosshairTimeLabel() {
|
|
491
463
|
if (!this.crosshair.visible || !this.crosshair.candle) return;
|
|
492
|
-
const t = this.#e, e = this.#t.width, i = this.#t.height,
|
|
493
|
-
t.save(), t.font =
|
|
494
|
-
const n = t.measureText(
|
|
495
|
-
t.fillStyle =
|
|
464
|
+
const t = this.#e, e = this.#t.width, i = this.#t.height, s = c.axis.axisX.crosshairLabel, r = Yt(this.crosshair.candle.time);
|
|
465
|
+
t.save(), t.font = s.font;
|
|
466
|
+
const n = t.measureText(r).width + s.paddingX * 2, o = s.height, a = this.getCrosshairLabelX(n, e), l = Math.max(0, (i - o) / 2);
|
|
467
|
+
t.fillStyle = s.backgroundColor, t.fillRect(a, l, n, o), t.strokeStyle = s.borderColor, t.lineWidth = s.borderWidth, t.strokeRect(a, l, n, o), t.fillStyle = s.textColor, t.textAlign = "center", t.textBaseline = "middle", t.fillText(r, a + n / 2, l + o / 2), t.restore();
|
|
496
468
|
}
|
|
497
469
|
clearCanvas() {
|
|
498
470
|
this.#e.clearRect(0, 0, this.#t.width, this.#t.height);
|
|
@@ -507,18 +479,18 @@ var h = {
|
|
|
507
479
|
}
|
|
508
480
|
drawAxisLabels() {
|
|
509
481
|
if (!this.viewport) return;
|
|
510
|
-
const t = this.#e, e = c.axis.axisX, i = this.#t.width,
|
|
482
|
+
const t = this.#e, e = c.axis.axisX, i = this.#t.width, s = It(this.candles);
|
|
511
483
|
t.save(), t.font = e.font, t.fillStyle = e.textColor, t.textAlign = e.textAlign, t.textBaseline = "middle";
|
|
512
|
-
const
|
|
484
|
+
const r = t.measureText("00:00").width, n = Bt({
|
|
513
485
|
candleSpacing: this.viewport.candleSpacing,
|
|
514
|
-
candleTimeframeMs:
|
|
515
|
-
labelWidth:
|
|
486
|
+
candleTimeframeMs: s,
|
|
487
|
+
labelWidth: r,
|
|
516
488
|
minLabelGap: e.minLabelGap
|
|
517
489
|
}), { startIndex: o, endIndex: a } = this.getVisibleCandleIndexRange(i);
|
|
518
490
|
for (let l = o; l <= a; l += 1) {
|
|
519
|
-
const d = this.getSlotTime(l,
|
|
520
|
-
if (d === null || !
|
|
521
|
-
const u = this.getCandleCenterX(l), g =
|
|
491
|
+
const d = this.getSlotTime(l, s);
|
|
492
|
+
if (d === null || !Wt(d, n)) continue;
|
|
493
|
+
const u = this.getCandleCenterX(l), g = Ft(d), m = t.measureText(g).width;
|
|
522
494
|
this.isLabelOutsideCanvas(u, m, i) || (this.drawTick(u), this.drawLabel(g, u));
|
|
523
495
|
}
|
|
524
496
|
t.restore();
|
|
@@ -536,18 +508,18 @@ var h = {
|
|
|
536
508
|
}
|
|
537
509
|
getSlotTime(t, e) {
|
|
538
510
|
if (t < this.candles.length) {
|
|
539
|
-
const
|
|
540
|
-
return
|
|
511
|
+
const r = this.candles[t];
|
|
512
|
+
return r ? r.time : null;
|
|
541
513
|
}
|
|
542
514
|
const i = this.candles[this.candles.length - 1];
|
|
543
515
|
if (!i) return null;
|
|
544
|
-
const
|
|
545
|
-
return i.time +
|
|
516
|
+
const s = t - (this.candles.length - 1);
|
|
517
|
+
return i.time + s * e;
|
|
546
518
|
}
|
|
547
519
|
getCandleCenterX(t) {
|
|
548
520
|
if (!this.viewport) return 0;
|
|
549
|
-
const { candleSpacing: e, candleWidth: i, offsetX:
|
|
550
|
-
return t * e +
|
|
521
|
+
const { candleSpacing: e, candleWidth: i, offsetX: s } = this.viewport;
|
|
522
|
+
return t * e + s + i / 2;
|
|
551
523
|
}
|
|
552
524
|
isLabelOutsideCanvas(t, e, i) {
|
|
553
525
|
return t + e / 2 < 0 || t - e / 2 > i;
|
|
@@ -557,25 +529,25 @@ var h = {
|
|
|
557
529
|
e.strokeStyle = i.tickColor, e.lineWidth = i.tickWidth, e.beginPath(), e.moveTo(t, 0), e.lineTo(t, i.tickLength), e.stroke();
|
|
558
530
|
}
|
|
559
531
|
drawLabel(t, e) {
|
|
560
|
-
const i = this.#e,
|
|
561
|
-
i.fillStyle =
|
|
532
|
+
const i = this.#e, s = c.axis.axisX;
|
|
533
|
+
i.fillStyle = s.textColor, i.fillText(t, e, s.labelOffsetY);
|
|
562
534
|
}
|
|
563
535
|
getCrosshairLabelX(t, e) {
|
|
564
536
|
return Math.max(120, Math.min(e - t, this.crosshair.x - t / 2));
|
|
565
537
|
}
|
|
566
|
-
}, p = (t, e = 5) => Number(t.toFixed(e)),
|
|
567
|
-
const i = t / (e / c.axis.axisY.tickGap),
|
|
568
|
-
for (const
|
|
538
|
+
}, p = (t, e = 5) => Number(t.toFixed(e)), O = ({ price: t, minPrice: e, priceRange: i, chartHeight: s }) => s - (t - e) / i * s, mt = ({ y: t, minPrice: e, priceRange: i, chartHeight: s }) => e + (1 - t / s) * i, Et = ({ priceRange: t, canvasHeight: e }) => {
|
|
539
|
+
const i = t / (e / c.axis.axisY.tickGap), s = 10 ** Math.floor(Math.log10(i));
|
|
540
|
+
for (const r of [
|
|
569
541
|
1,
|
|
570
542
|
2,
|
|
571
543
|
5,
|
|
572
544
|
10
|
|
573
545
|
]) {
|
|
574
|
-
const n =
|
|
546
|
+
const n = r * s;
|
|
575
547
|
if (n >= i) return n;
|
|
576
548
|
}
|
|
577
|
-
return 10 *
|
|
578
|
-
},
|
|
549
|
+
return 10 * s;
|
|
550
|
+
}, zt = class {
|
|
579
551
|
#t;
|
|
580
552
|
#e;
|
|
581
553
|
viewport = null;
|
|
@@ -604,8 +576,8 @@ var h = {
|
|
|
604
576
|
}
|
|
605
577
|
drawCrosshairPriceLabel() {
|
|
606
578
|
if (!this.crosshair.visible) return;
|
|
607
|
-
const t = this.#e, e = this.#t.width, i = this.#t.height,
|
|
608
|
-
t.save(), t.fillStyle =
|
|
579
|
+
const t = this.#e, e = this.#t.width, i = this.#t.height, s = c.axis.axisY.crosshairLabel, r = p(this.crosshair.price).toFixed(5), n = s.height, o = this.getCrosshairLabelY(n, i);
|
|
580
|
+
t.save(), t.fillStyle = s.backgroundColor, t.fillRect(0, o, e, n), t.strokeStyle = s.borderColor, t.lineWidth = s.borderWidth, t.strokeRect(0, o, e, n), t.font = s.font, t.fillStyle = s.textColor, t.textAlign = "left", t.textBaseline = "middle", t.fillText(r, s.paddingX, o + n / 2), t.restore();
|
|
609
581
|
}
|
|
610
582
|
clearCanvas() {
|
|
611
583
|
this.#e.clearRect(0, 0, this.#t.width, this.#t.height);
|
|
@@ -620,13 +592,13 @@ var h = {
|
|
|
620
592
|
}
|
|
621
593
|
drawPriceLabels() {
|
|
622
594
|
if (!this.viewport) return;
|
|
623
|
-
const t = this.#e, e = this.#t.height, i = c.axis.axisY,
|
|
595
|
+
const t = this.#e, e = this.#t.height, i = c.axis.axisY, s = Et({
|
|
624
596
|
priceRange: this.viewport.priceRange,
|
|
625
597
|
canvasHeight: e
|
|
626
598
|
});
|
|
627
599
|
t.save(), t.font = i.font, t.fillStyle = i.textColor, t.textAlign = i.textAlign, t.textBaseline = "middle";
|
|
628
|
-
const { startPrice:
|
|
629
|
-
for (let o =
|
|
600
|
+
const { startPrice: r, endPrice: n } = this.getVisiblePriceRange(s);
|
|
601
|
+
for (let o = r; o <= n; o += s) {
|
|
630
602
|
const a = this.getPriceY(o, e);
|
|
631
603
|
this.isPriceOutsideCanvas(a, e) || (this.drawTick(a), this.drawPriceLabel(o, a));
|
|
632
604
|
}
|
|
@@ -642,7 +614,7 @@ var h = {
|
|
|
642
614
|
};
|
|
643
615
|
}
|
|
644
616
|
getPriceY(t, e) {
|
|
645
|
-
return this.viewport ?
|
|
617
|
+
return this.viewport ? O({
|
|
646
618
|
price: t,
|
|
647
619
|
minPrice: this.viewport.minPrice,
|
|
648
620
|
priceRange: this.viewport.priceRange,
|
|
@@ -657,13 +629,13 @@ var h = {
|
|
|
657
629
|
e.strokeStyle = i.tickColor, e.lineWidth = i.tickWidth, e.beginPath(), e.moveTo(0, t), e.lineTo(i.tickLength, t), e.stroke();
|
|
658
630
|
}
|
|
659
631
|
drawPriceLabel(t, e) {
|
|
660
|
-
const i = this.#e,
|
|
661
|
-
i.fillStyle =
|
|
632
|
+
const i = this.#e, s = c.axis.axisY;
|
|
633
|
+
i.fillStyle = s.textColor, i.fillText(p(t).toFixed(5), s.labelOffsetX, e);
|
|
662
634
|
}
|
|
663
635
|
getCrosshairLabelY(t, e) {
|
|
664
636
|
return Math.max(0, Math.min(e - t, this.crosshair.y - t / 2));
|
|
665
637
|
}
|
|
666
|
-
},
|
|
638
|
+
}, Vt = class {
|
|
667
639
|
#t;
|
|
668
640
|
#e;
|
|
669
641
|
mouseX = 0;
|
|
@@ -679,8 +651,8 @@ var h = {
|
|
|
679
651
|
this.#e = e, this.crosshairColor = t.crosshairColor ?? c.crosshair.color, this.crosshairThickness = t.crosshairThickness ?? c.crosshair.thickness, this.crosshairStyle = t.crosshairStyle ?? c.crosshair.style;
|
|
680
652
|
}
|
|
681
653
|
updateMousePosition(t, e, i = {}) {
|
|
682
|
-
const
|
|
683
|
-
this.mouseX = this.clampX(
|
|
654
|
+
const s = this.getLocalCanvasPoint(t, e), r = i.snapX ?? s.x;
|
|
655
|
+
this.mouseX = this.clampX(r), this.mouseY = this.clampY(s.y), this.visible = !0;
|
|
684
656
|
}
|
|
685
657
|
hide() {
|
|
686
658
|
this.visible = !1;
|
|
@@ -712,10 +684,10 @@ var h = {
|
|
|
712
684
|
t.clearRect(0, 0, e, i), this.visible && (t.save(), this.applyCrosshairStyle(), this.drawVerticalCrosshairLine(t, i), this.drawHorizontalCrosshairLine(t, e), t.restore());
|
|
713
685
|
}
|
|
714
686
|
getLocalCanvasPoint(t, e) {
|
|
715
|
-
const i = this.#t.getBoundingClientRect(),
|
|
687
|
+
const i = this.#t.getBoundingClientRect(), s = this.#t.width / i.width, r = this.#t.height / i.height;
|
|
716
688
|
return {
|
|
717
|
-
x: (t - i.left) *
|
|
718
|
-
y: (e - i.top) *
|
|
689
|
+
x: (t - i.left) * s,
|
|
690
|
+
y: (e - i.top) * r
|
|
719
691
|
};
|
|
720
692
|
}
|
|
721
693
|
clampX(t) {
|
|
@@ -737,10 +709,10 @@ var h = {
|
|
|
737
709
|
return [2, 6];
|
|
738
710
|
}
|
|
739
711
|
}
|
|
740
|
-
drawLine({ ctx: t, fromX: e, fromY: i, toX:
|
|
741
|
-
t.beginPath(), t.moveTo(e, i), t.lineTo(
|
|
712
|
+
drawLine({ ctx: t, fromX: e, fromY: i, toX: s, toY: r }) {
|
|
713
|
+
t.beginPath(), t.moveTo(e, i), t.lineTo(s, r), t.stroke();
|
|
742
714
|
}
|
|
743
|
-
}, F = 60 * 1e3,
|
|
715
|
+
}, F = 60 * 1e3, Ct = 60 * F, Nt = 24 * Ct, _t = class {
|
|
744
716
|
#t;
|
|
745
717
|
#e;
|
|
746
718
|
candles;
|
|
@@ -768,8 +740,8 @@ var h = {
|
|
|
768
740
|
this.setFallbackViewport();
|
|
769
741
|
return;
|
|
770
742
|
}
|
|
771
|
-
const t = this.getInitialVisibleCandles(), { minPrice: e, maxPrice: i } = this.getCandlesPriceBounds(t),
|
|
772
|
-
this.priceCenter = (e + i) / 2, this.priceRange =
|
|
743
|
+
const t = this.getInitialVisibleCandles(), { minPrice: e, maxPrice: i } = this.getCandlesPriceBounds(t), s = this.getInitialPriceRange(e, i);
|
|
744
|
+
this.priceCenter = (e + i) / 2, this.priceRange = s, this.initialPriceRange = s;
|
|
773
745
|
}
|
|
774
746
|
isWithinAutoFollowThreshold() {
|
|
775
747
|
return this.getRightGap() <= this.autoFollowThresholdCandles * this.candleSpacing + 5;
|
|
@@ -834,7 +806,7 @@ var h = {
|
|
|
834
806
|
return this.getCandleCenterX(e);
|
|
835
807
|
}
|
|
836
808
|
getPriceAtY(t) {
|
|
837
|
-
return p(
|
|
809
|
+
return p(mt({
|
|
838
810
|
y: t,
|
|
839
811
|
minPrice: this.minPrice,
|
|
840
812
|
priceRange: this.priceRange,
|
|
@@ -861,11 +833,11 @@ var h = {
|
|
|
861
833
|
render() {
|
|
862
834
|
const t = this.#e, e = this.#t.width, i = this.#t.height;
|
|
863
835
|
if (this.clearCanvas(t, e, i), this.candles.length === 0) return;
|
|
864
|
-
const { startIndex:
|
|
836
|
+
const { startIndex: s, endIndex: r } = this.getVisibleRange(e), n = this.candles.slice(s, r + 1);
|
|
865
837
|
this.drawCandles({
|
|
866
838
|
ctx: t,
|
|
867
839
|
candles: n,
|
|
868
|
-
startIndex:
|
|
840
|
+
startIndex: s,
|
|
869
841
|
chartHeight: i
|
|
870
842
|
});
|
|
871
843
|
const o = {
|
|
@@ -875,9 +847,9 @@ var h = {
|
|
|
875
847
|
};
|
|
876
848
|
this.drawAskPriceLine(o), this.drawBidPriceLine(o);
|
|
877
849
|
}
|
|
878
|
-
drawCandles({ ctx: t, candles: e, startIndex: i, chartHeight:
|
|
879
|
-
e.forEach((
|
|
880
|
-
const o = i + n, a = this.getCandleX(o), l = this.getCandleColor(
|
|
850
|
+
drawCandles({ ctx: t, candles: e, startIndex: i, chartHeight: s }) {
|
|
851
|
+
e.forEach((r, n) => {
|
|
852
|
+
const o = i + n, a = this.getCandleX(o), l = this.getCandleColor(r), d = this.getCandleYCoordinates(r, s);
|
|
881
853
|
this.drawSingleCandle({
|
|
882
854
|
ctx: t,
|
|
883
855
|
candleX: a,
|
|
@@ -886,38 +858,38 @@ var h = {
|
|
|
886
858
|
});
|
|
887
859
|
});
|
|
888
860
|
}
|
|
889
|
-
drawSingleCandle({ ctx: t, candleX: e, openY: i, closeY:
|
|
861
|
+
drawSingleCandle({ ctx: t, candleX: e, openY: i, closeY: s, highY: r, lowY: n, candleColor: o }) {
|
|
890
862
|
t.strokeStyle = o, t.fillStyle = o;
|
|
891
863
|
const a = e + this.candleWidth / 2;
|
|
892
|
-
t.beginPath(), t.moveTo(a,
|
|
893
|
-
const l = Math.min(i,
|
|
864
|
+
t.beginPath(), t.moveTo(a, r), t.lineTo(a, n), t.stroke();
|
|
865
|
+
const l = Math.min(i, s), d = Math.max(Math.abs(s - i), c.candles.minBodyHeight);
|
|
894
866
|
t.fillRect(e, l, this.candleWidth, d);
|
|
895
867
|
}
|
|
896
|
-
drawPriceLine({ ctx: t, chartWidth: e, chartHeight: i, price:
|
|
897
|
-
const l = this.getPriceY(p(
|
|
898
|
-
t.save(), t.globalAlpha = n, t.strokeStyle =
|
|
868
|
+
drawPriceLine({ ctx: t, chartWidth: e, chartHeight: i, price: s, color: r, opacity: n, lineWidth: o, dash: a }) {
|
|
869
|
+
const l = this.getPriceY(p(s), i);
|
|
870
|
+
t.save(), t.globalAlpha = n, t.strokeStyle = r, t.lineWidth = o, t.setLineDash(a), t.beginPath(), t.moveTo(0, l), t.lineTo(e, l), t.stroke(), t.restore();
|
|
899
871
|
}
|
|
900
872
|
drawBidPriceLine({ ctx: t, chartWidth: e, chartHeight: i }) {
|
|
901
|
-
const
|
|
902
|
-
!
|
|
873
|
+
const s = this.candles.at(-1);
|
|
874
|
+
!s || !c.candles.liveBidPriceLine.visible || this.drawPriceLine({
|
|
903
875
|
ctx: t,
|
|
904
876
|
chartWidth: e,
|
|
905
877
|
chartHeight: i,
|
|
906
|
-
price:
|
|
907
|
-
color: this.getBidPriceLineColor(
|
|
878
|
+
price: s.close,
|
|
879
|
+
color: this.getBidPriceLineColor(s),
|
|
908
880
|
opacity: c.candles.liveBidPriceLine.opacity,
|
|
909
881
|
lineWidth: c.candles.liveBidPriceLine.width,
|
|
910
882
|
dash: c.candles.liveBidPriceLine.dash
|
|
911
883
|
});
|
|
912
884
|
}
|
|
913
885
|
drawAskPriceLine({ ctx: t, chartWidth: e, chartHeight: i }) {
|
|
914
|
-
const
|
|
915
|
-
!
|
|
886
|
+
const s = this.candles.at(-1);
|
|
887
|
+
!s || !c.candles.liveAskPriceLine.visible || s.ask == null || this.drawPriceLine({
|
|
916
888
|
ctx: t,
|
|
917
889
|
chartWidth: e,
|
|
918
890
|
chartHeight: i,
|
|
919
|
-
price:
|
|
920
|
-
color: this.getAskPriceLineColor(
|
|
891
|
+
price: s.ask,
|
|
892
|
+
color: this.getAskPriceLineColor(s),
|
|
921
893
|
opacity: c.candles.liveAskPriceLine.opacity,
|
|
922
894
|
lineWidth: c.candles.liveAskPriceLine.width,
|
|
923
895
|
dash: c.candles.liveAskPriceLine.dash
|
|
@@ -945,20 +917,20 @@ var h = {
|
|
|
945
917
|
}
|
|
946
918
|
getCandlesPriceBounds(t) {
|
|
947
919
|
let e = Number.POSITIVE_INFINITY, i = Number.NEGATIVE_INFINITY;
|
|
948
|
-
for (const
|
|
949
|
-
|
|
920
|
+
for (const s of t)
|
|
921
|
+
s.low < e && (e = s.low), s.high > i && (i = s.high);
|
|
950
922
|
return {
|
|
951
923
|
minPrice: e,
|
|
952
924
|
maxPrice: i
|
|
953
925
|
};
|
|
954
926
|
}
|
|
955
927
|
getInitialPriceRange(t, e) {
|
|
956
|
-
const i = this.getInitialFallbackPercent(),
|
|
928
|
+
const i = this.getInitialFallbackPercent(), s = p(e - t), r = Math.max(Math.abs((t + e) / 2) * i, 1e-5), n = Math.max(s, r);
|
|
957
929
|
return n + n * 0.2;
|
|
958
930
|
}
|
|
959
931
|
getInitialFallbackPercent() {
|
|
960
932
|
const t = this.detectCandleTimeframeMs();
|
|
961
|
-
return t <= F ? 25e-4 : t <= 5 * F ? 35e-4 : t <= 15 * F ? 5e-3 : t <=
|
|
933
|
+
return t <= F ? 25e-4 : t <= 5 * F ? 35e-4 : t <= 15 * F ? 5e-3 : t <= Ct ? 75e-4 : (t < Nt, 0.01);
|
|
962
934
|
}
|
|
963
935
|
detectCandleTimeframeMs() {
|
|
964
936
|
if (this.candles.length < 2) return 15 * F;
|
|
@@ -985,11 +957,11 @@ var h = {
|
|
|
985
957
|
return (this.#t.width - this.offsetX) / this.candleSpacing;
|
|
986
958
|
}
|
|
987
959
|
getNextHorizontalZoom(t) {
|
|
988
|
-
const { speed: e, min: i, max:
|
|
989
|
-
return Math.max(i, Math.min(
|
|
960
|
+
const { speed: e, min: i, max: s } = c.zoom.x, r = this.zoomX + t * e;
|
|
961
|
+
return Math.max(i, Math.min(r, s));
|
|
990
962
|
}
|
|
991
963
|
getNextVerticalPriceRange(t) {
|
|
992
|
-
const { speed: e, min: i, max:
|
|
964
|
+
const { speed: e, min: i, max: s } = c.zoom.y, r = 1 - t * e, n = this.priceRange * r, o = this.initialPriceRange * (i / 100), a = this.initialPriceRange * (s / 100);
|
|
993
965
|
return Math.max(o, Math.min(n, a));
|
|
994
966
|
}
|
|
995
967
|
clearCanvas(t, e, i) {
|
|
@@ -1007,7 +979,7 @@ var h = {
|
|
|
1007
979
|
};
|
|
1008
980
|
}
|
|
1009
981
|
getPriceY(t, e) {
|
|
1010
|
-
return
|
|
982
|
+
return O({
|
|
1011
983
|
price: t,
|
|
1012
984
|
minPrice: this.minPrice,
|
|
1013
985
|
priceRange: this.priceRange,
|
|
@@ -1024,7 +996,7 @@ var h = {
|
|
|
1024
996
|
#t;
|
|
1025
997
|
#e;
|
|
1026
998
|
#r = null;
|
|
1027
|
-
#
|
|
999
|
+
#i = null;
|
|
1028
1000
|
constructor({ ctx: t, config: e }) {
|
|
1029
1001
|
this.#t = t, this.#e = e;
|
|
1030
1002
|
}
|
|
@@ -1035,113 +1007,118 @@ var h = {
|
|
|
1035
1007
|
this.#e = t;
|
|
1036
1008
|
}
|
|
1037
1009
|
setPreviousDay(t) {
|
|
1038
|
-
this.#
|
|
1010
|
+
this.#i = t ?? null;
|
|
1039
1011
|
}
|
|
1040
1012
|
render() {
|
|
1041
|
-
if (!this.#r || !this.#
|
|
1042
|
-
const { high: t, low: e } = this.#
|
|
1043
|
-
Number.isFinite(t) && t > 0 && this.#
|
|
1013
|
+
if (!this.#r || !this.#i) return;
|
|
1014
|
+
const { high: t, low: e } = this.#i;
|
|
1015
|
+
Number.isFinite(t) && t > 0 && this.#u(t, "PDH"), Number.isFinite(e) && e > 0 && this.#u(e, "PDL");
|
|
1044
1016
|
}
|
|
1045
|
-
#
|
|
1017
|
+
#u(t, e) {
|
|
1046
1018
|
if (!this.#r || !this.#e) return;
|
|
1047
|
-
const i = this.#t,
|
|
1019
|
+
const i = this.#t, s = i.canvas, r = O({
|
|
1048
1020
|
price: t,
|
|
1049
1021
|
minPrice: this.#r.minPrice,
|
|
1050
1022
|
priceRange: this.#r.priceRange,
|
|
1051
|
-
chartHeight:
|
|
1023
|
+
chartHeight: s.height
|
|
1052
1024
|
});
|
|
1053
|
-
if (
|
|
1054
|
-
const { line: n, text: o } = this.#e, a =
|
|
1025
|
+
if (r < 0 || r > s.height) return;
|
|
1026
|
+
const { line: n, text: o } = this.#e, a = s.width;
|
|
1055
1027
|
i.save(), i.font = o.font;
|
|
1056
1028
|
const l = i.measureText(e).width, d = a / 2, u = l / 2 + o.paddingX;
|
|
1057
|
-
i.globalAlpha = n.opacity, i.strokeStyle = n.color, i.lineWidth = n.width, i.setLineDash(n.dash), i.beginPath(), i.moveTo(0,
|
|
1029
|
+
i.globalAlpha = n.opacity, i.strokeStyle = n.color, i.lineWidth = n.width, i.setLineDash(n.dash), i.beginPath(), i.moveTo(0, r), i.lineTo(d - u, r), i.stroke(), i.beginPath(), i.moveTo(d + u, r), i.lineTo(a, r), i.stroke(), i.setLineDash([]), i.globalAlpha = 1, i.fillStyle = o.color, i.textAlign = "center", i.textBaseline = "middle", i.fillText(e, d, r), i.restore();
|
|
1058
1030
|
}
|
|
1059
|
-
},
|
|
1060
|
-
const i = t.getBoundingClientRect(),
|
|
1031
|
+
}, vt = (t, e) => {
|
|
1032
|
+
const i = t.getBoundingClientRect(), s = t.width / i.width, r = t.height / i.height;
|
|
1061
1033
|
return {
|
|
1062
|
-
x: (e.clientX - i.left) *
|
|
1063
|
-
y: (e.clientY - i.top) *
|
|
1034
|
+
x: (e.clientX - i.left) * s,
|
|
1035
|
+
y: (e.clientY - i.top) * r
|
|
1064
1036
|
};
|
|
1065
1037
|
};
|
|
1066
|
-
var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID() : `shape-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
1038
|
+
var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID() : `shape-${Date.now()}-${Math.random().toString(16).slice(2)}`, $ = (t, e) => vt(t, e), ht = (t, e) => ({
|
|
1067
1039
|
time: e.getNearestCandleTimeForX(t.x),
|
|
1068
1040
|
price: e.getPriceForY(t.y)
|
|
1069
|
-
}),
|
|
1041
|
+
}), C = (t, e) => ({
|
|
1070
1042
|
x: e.getXForTime(t.time),
|
|
1071
1043
|
y: e.getYForPrice(t.price)
|
|
1072
1044
|
}), Ut = (t, e) => {
|
|
1073
|
-
const i = Math.min(t.x, e.x),
|
|
1045
|
+
const i = Math.min(t.x, e.x), s = Math.max(t.x, e.x), r = Math.min(t.y, e.y), n = Math.max(t.y, e.y);
|
|
1074
1046
|
return {
|
|
1075
1047
|
left: i,
|
|
1076
|
-
top:
|
|
1077
|
-
right:
|
|
1048
|
+
top: r,
|
|
1049
|
+
right: s,
|
|
1078
1050
|
bottom: n,
|
|
1079
|
-
width:
|
|
1080
|
-
height: n -
|
|
1051
|
+
width: s - i,
|
|
1052
|
+
height: n - r
|
|
1081
1053
|
};
|
|
1082
|
-
},
|
|
1083
|
-
const i = t.x - e.x,
|
|
1084
|
-
return Math.sqrt(i * i +
|
|
1085
|
-
},
|
|
1086
|
-
const
|
|
1087
|
-
if (n === 0) return
|
|
1088
|
-
const o = Math.max(0, Math.min(1, ((t.x - e.x) *
|
|
1089
|
-
return
|
|
1090
|
-
x: e.x + o *
|
|
1091
|
-
y: e.y + o *
|
|
1054
|
+
}, J = (t, e, i) => Ut(C(t, i), C(e, i)), K = (t, e) => {
|
|
1055
|
+
const i = t.x - e.x, s = t.y - e.y;
|
|
1056
|
+
return Math.sqrt(i * i + s * s);
|
|
1057
|
+
}, yt = (t, e, i) => {
|
|
1058
|
+
const s = i.x - e.x, r = i.y - e.y, n = s * s + r * r;
|
|
1059
|
+
if (n === 0) return K(t, e);
|
|
1060
|
+
const o = Math.max(0, Math.min(1, ((t.x - e.x) * s + (t.y - e.y) * r) / n));
|
|
1061
|
+
return K(t, {
|
|
1062
|
+
x: e.x + o * s,
|
|
1063
|
+
y: e.y + o * r
|
|
1092
1064
|
});
|
|
1093
|
-
},
|
|
1094
|
-
if (!
|
|
1095
|
-
const
|
|
1096
|
-
return (
|
|
1097
|
-
},
|
|
1065
|
+
}, wt = (t, e, i = 0) => t.x >= e.left - i && t.x <= e.right + i && t.y >= e.top - i && t.y <= e.bottom + i, $t = (t, e, i = 8) => {
|
|
1066
|
+
if (!wt(t, e, i)) return !1;
|
|
1067
|
+
const s = Math.abs(t.x - e.left) <= i, r = Math.abs(t.x - e.right) <= i, n = Math.abs(t.y - e.top) <= i, o = Math.abs(t.y - e.bottom) <= i, a = t.x >= e.left - i && t.x <= e.right + i, l = t.y >= e.top - i && t.y <= e.bottom + i;
|
|
1068
|
+
return (s || r) && l || (n || o) && a;
|
|
1069
|
+
}, x = ({ shapeId: t, type: e, point: i, radius: s = 5, cursor: r, index: n }) => ({
|
|
1098
1070
|
shapeId: t,
|
|
1099
1071
|
type: e,
|
|
1100
1072
|
x: i.x,
|
|
1101
1073
|
y: i.y,
|
|
1102
|
-
radius:
|
|
1103
|
-
cursor:
|
|
1074
|
+
radius: s,
|
|
1075
|
+
cursor: r,
|
|
1104
1076
|
index: n
|
|
1105
|
-
}),
|
|
1106
|
-
t.strokeStyle =
|
|
1107
|
-
},
|
|
1077
|
+
}), j = (t, e) => K(t, e) <= e.radius + 2, V = (t, e = 1) => t === "dashed" ? [e * 6, e * 4] : t === "dotted" ? [e, e * 3] : [], Q = (t, e, i) => {
|
|
1078
|
+
t.strokeStyle = P(e.lineColor, e.lineOpacity), t.lineWidth = i ?? e.lineWidth, t.setLineDash(V(e.lineStyle, t.lineWidth));
|
|
1079
|
+
}, Pt = (t, e, i) => !e || i === void 0 || i <= 0 ? !1 : (t.fillStyle = P(e, i), !0), E = (t) => {
|
|
1108
1080
|
t.setLineDash([]);
|
|
1109
|
-
},
|
|
1081
|
+
}, Jt = (t, e, i = {
|
|
1110
1082
|
fillColor: "#ffffff",
|
|
1111
1083
|
borderColor: "#2962ff",
|
|
1112
1084
|
borderThickness: 3
|
|
1113
1085
|
}) => {
|
|
1114
1086
|
t.save(), t.beginPath(), t.arc(e.x, e.y, e.radius, 0, Math.PI * 2), t.fillStyle = i.fillColor, t.fill(), t.lineWidth = i.borderThickness, t.strokeStyle = i.borderColor, t.stroke(), t.restore();
|
|
1115
|
-
},
|
|
1116
|
-
e.forEach((
|
|
1117
|
-
|
|
1087
|
+
}, z = (t, e, i) => {
|
|
1088
|
+
e.forEach((s) => {
|
|
1089
|
+
Jt(t, s, i);
|
|
1118
1090
|
});
|
|
1119
|
-
},
|
|
1091
|
+
}, P = (t, e) => {
|
|
1120
1092
|
const i = jt(e, 0, 1);
|
|
1121
|
-
return t.startsWith("rgba(") ? t : t.startsWith("rgb(") ? t.replace("rgb(", "rgba(").replace(")", `, ${i})`) : t.startsWith("#") ?
|
|
1122
|
-
},
|
|
1123
|
-
const i = t.replace("#", ""),
|
|
1124
|
-
return `rgba(${parseInt(
|
|
1125
|
-
}, jt = (t, e, i) => Math.min(i, Math.max(e, t)),
|
|
1093
|
+
return t.startsWith("rgba(") ? t : t.startsWith("rgb(") ? t.replace("rgb(", "rgba(").replace(")", `, ${i})`) : t.startsWith("#") ? Kt(t, i) : t;
|
|
1094
|
+
}, Kt = (t, e) => {
|
|
1095
|
+
const i = t.replace("#", ""), s = i.length === 3 ? i.split("").map((r) => `${r}${r}`).join("") : i;
|
|
1096
|
+
return `rgba(${parseInt(s.slice(0, 2), 16)}, ${parseInt(s.slice(2, 4), 16)}, ${parseInt(s.slice(4, 6), 16)}, ${e})`;
|
|
1097
|
+
}, jt = (t, e, i) => Math.min(i, Math.max(e, t)), dt = (t, e, i) => e + (t - e) * i, Z = (t, e) => {
|
|
1126
1098
|
if (t.length === 0) return -1;
|
|
1127
|
-
let i = 0,
|
|
1128
|
-
for (let
|
|
1129
|
-
const n = Math.abs(t[
|
|
1130
|
-
n <
|
|
1099
|
+
let i = 0, s = Math.abs(t[0].time - e);
|
|
1100
|
+
for (let r = 1; r < t.length; r += 1) {
|
|
1101
|
+
const n = Math.abs(t[r].time - e);
|
|
1102
|
+
n < s && (s = n, i = r);
|
|
1131
1103
|
}
|
|
1132
1104
|
return i;
|
|
1133
|
-
},
|
|
1105
|
+
}, q = (t) => {
|
|
1134
1106
|
if (t.length < 2) return 900 * 1e3;
|
|
1135
1107
|
const e = [];
|
|
1136
1108
|
for (let i = 1; i < t.length; i += 1) {
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1140
|
-
return e.length === 0 ? 900 * 1e3 : e.reduce((i,
|
|
1141
|
-
},
|
|
1142
|
-
const
|
|
1143
|
-
return
|
|
1144
|
-
},
|
|
1109
|
+
const s = t[i].time - t[i - 1].time;
|
|
1110
|
+
s > 0 && e.push(s);
|
|
1111
|
+
}
|
|
1112
|
+
return e.length === 0 ? 900 * 1e3 : e.reduce((i, s) => i + s, 0) / e.length;
|
|
1113
|
+
}, Zt = (t, e, i) => {
|
|
1114
|
+
const s = Z(t, e), r = s + i;
|
|
1115
|
+
return s >= 0 && r >= 0 && r < t.length ? t[r].time : e + q(t) * i;
|
|
1116
|
+
}, ct = (t) => t instanceof MouseEvent && t.type === "contextmenu" ? !1 : "button" in t && t.type === "pointerdown" ? t.button === 0 : !0, f = {
|
|
1117
|
+
handleColor: h.background,
|
|
1118
|
+
handleBorderColor: h.blue,
|
|
1119
|
+
handleBorderThickness: 1.5,
|
|
1120
|
+
handleRadius: 5
|
|
1121
|
+
}, L = class I {
|
|
1145
1122
|
static defaultConfig = {
|
|
1146
1123
|
levels: [
|
|
1147
1124
|
{
|
|
@@ -1186,62 +1163,56 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1186
1163
|
}
|
|
1187
1164
|
],
|
|
1188
1165
|
fillColor: "#808080",
|
|
1189
|
-
fillOpacity: 0.04
|
|
1190
|
-
handleColor: "#ffffff",
|
|
1191
|
-
handleBorderColor: "#2962ff",
|
|
1192
|
-
handleBorderThickness: 1.5,
|
|
1193
|
-
handleRadius: 5,
|
|
1194
|
-
hoverLineWidth: 2,
|
|
1195
|
-
selectedLineWidth: 2
|
|
1166
|
+
fillOpacity: 0.04
|
|
1196
1167
|
};
|
|
1197
|
-
static draw({ ctx: e, shape: i, converter:
|
|
1198
|
-
const [a, l] = i.vertices, d =
|
|
1199
|
-
e.save(),
|
|
1200
|
-
for (const
|
|
1201
|
-
const
|
|
1202
|
-
e.beginPath(), e.strokeStyle =
|
|
1168
|
+
static draw({ ctx: e, shape: i, converter: s, config: r = I.defaultConfig, selected: n = !1, hovered: o = !1 }) {
|
|
1169
|
+
const [a, l] = i.vertices, d = C(a, s), u = C(l, s), g = J(a, l, s), m = Math.min(d.x, u.x), b = Math.max(d.x, u.x);
|
|
1170
|
+
e.save(), Pt(e, r.fillColor, r.fillOpacity) && e.fillRect(g.left, g.top, g.width, g.height);
|
|
1171
|
+
for (const v of r.levels) {
|
|
1172
|
+
const S = dt(a.price, l.price, v.level), T = s.getYForPrice(S), k = v.lineWidth;
|
|
1173
|
+
e.beginPath(), e.strokeStyle = P(v.color, v.opacity), e.lineWidth = k, e.setLineDash(V(v.lineStyle, k)), e.moveTo(m, T), e.lineTo(b, T), e.stroke(), v.label && (e.setLineDash([]), e.fillStyle = P(v.color, v.opacity), e.font = "11px sans-serif", e.textBaseline = "middle", e.fillText(Number(v.label).toFixed(2).toString(), b + 12, T));
|
|
1203
1174
|
}
|
|
1204
|
-
|
|
1205
|
-
fillColor:
|
|
1206
|
-
borderColor:
|
|
1207
|
-
borderThickness:
|
|
1175
|
+
E(e), (n || o) && z(e, I.getHandles(i, s), {
|
|
1176
|
+
fillColor: f.handleColor,
|
|
1177
|
+
borderColor: f.handleBorderColor,
|
|
1178
|
+
borderThickness: f.handleBorderThickness
|
|
1208
1179
|
}), e.restore();
|
|
1209
1180
|
}
|
|
1210
|
-
static drawDraft({ ctx: e, vertices: i, converter:
|
|
1211
|
-
|
|
1181
|
+
static drawDraft({ ctx: e, vertices: i, converter: s, config: r = I.defaultConfig }) {
|
|
1182
|
+
I.draw({
|
|
1212
1183
|
ctx: e,
|
|
1213
1184
|
shape: {
|
|
1214
1185
|
id: "__draft_fib_retracement__",
|
|
1215
1186
|
type: "fibRetracement",
|
|
1216
1187
|
vertices: i
|
|
1217
1188
|
},
|
|
1218
|
-
converter:
|
|
1219
|
-
config:
|
|
1189
|
+
converter: s,
|
|
1190
|
+
config: r,
|
|
1220
1191
|
selected: !0
|
|
1221
1192
|
});
|
|
1222
1193
|
}
|
|
1223
|
-
static getHandles(e, i
|
|
1224
|
-
const [s,
|
|
1225
|
-
return [
|
|
1194
|
+
static getHandles(e, i) {
|
|
1195
|
+
const [s, r] = e.vertices, n = C(s, i), o = C(r, i);
|
|
1196
|
+
return [x({
|
|
1226
1197
|
shapeId: e.id,
|
|
1227
1198
|
type: "start",
|
|
1228
|
-
point:
|
|
1229
|
-
radius:
|
|
1199
|
+
point: n,
|
|
1200
|
+
radius: f.handleRadius,
|
|
1230
1201
|
cursor: "grab"
|
|
1231
|
-
}),
|
|
1202
|
+
}), x({
|
|
1232
1203
|
shapeId: e.id,
|
|
1233
1204
|
type: "end",
|
|
1234
|
-
point:
|
|
1235
|
-
radius:
|
|
1205
|
+
point: o,
|
|
1206
|
+
radius: f.handleRadius,
|
|
1236
1207
|
cursor: "grab"
|
|
1237
1208
|
})];
|
|
1238
1209
|
}
|
|
1239
|
-
static hitTest({ point: e, shape: i, converter:
|
|
1240
|
-
const [o, a] = i.vertices, l =
|
|
1241
|
-
if (e.x < u -
|
|
1210
|
+
static hitTest({ point: e, shape: i, converter: s, tolerance: r = 8, config: n = I.defaultConfig }) {
|
|
1211
|
+
const [o, a] = i.vertices, l = C(o, s), d = C(a, s), u = Math.min(l.x, d.x), g = Math.max(l.x, d.x);
|
|
1212
|
+
if (e.x < u - r || e.x > g + r) return !1;
|
|
1242
1213
|
for (const m of n.levels) {
|
|
1243
|
-
const
|
|
1244
|
-
if (Math.abs(e.y -
|
|
1214
|
+
const b = dt(o.price, a.price, m.level), v = s.getYForPrice(b);
|
|
1215
|
+
if (Math.abs(e.y - v) <= r) return !0;
|
|
1245
1216
|
}
|
|
1246
1217
|
return !1;
|
|
1247
1218
|
}
|
|
@@ -1257,68 +1228,62 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1257
1228
|
}]
|
|
1258
1229
|
};
|
|
1259
1230
|
}
|
|
1260
|
-
static resize(e, i,
|
|
1231
|
+
static resize(e, i, s) {
|
|
1261
1232
|
return i === "start" ? {
|
|
1262
1233
|
...e,
|
|
1263
|
-
vertices: [
|
|
1234
|
+
vertices: [s, e.vertices[1]]
|
|
1264
1235
|
} : i === "end" ? {
|
|
1265
1236
|
...e,
|
|
1266
|
-
vertices: [e.vertices[0],
|
|
1237
|
+
vertices: [e.vertices[0], s]
|
|
1267
1238
|
} : e;
|
|
1268
1239
|
}
|
|
1269
|
-
},
|
|
1240
|
+
}, M = class Y {
|
|
1270
1241
|
static defaultConfig = {
|
|
1271
1242
|
lineWidth: 2,
|
|
1272
1243
|
lineColor: "#2962ff",
|
|
1273
1244
|
lineOpacity: 1,
|
|
1274
|
-
lineStyle: "solid"
|
|
1275
|
-
handleColor: "#ffffff",
|
|
1276
|
-
handleBorderColor: "#2962ff",
|
|
1277
|
-
handleBorderThickness: 1.5,
|
|
1278
|
-
handleRadius: 5,
|
|
1279
|
-
hoverLineWidth: 3,
|
|
1280
|
-
selectedLineWidth: 3
|
|
1245
|
+
lineStyle: "solid"
|
|
1281
1246
|
};
|
|
1282
|
-
static draw({ ctx: e, shape: i, converter:
|
|
1283
|
-
const [a, l] = i.vertices, d =
|
|
1284
|
-
e.save(),
|
|
1285
|
-
fillColor:
|
|
1286
|
-
borderColor:
|
|
1287
|
-
borderThickness:
|
|
1247
|
+
static draw({ ctx: e, shape: i, converter: s, config: r = Y.defaultConfig, selected: n = !1, hovered: o = !1 }) {
|
|
1248
|
+
const [a, l] = i.vertices, d = C(a, s), u = C(l, s);
|
|
1249
|
+
e.save(), Q(e, r), e.beginPath(), e.moveTo(d.x, d.y), e.lineTo(u.x, u.y), e.stroke(), E(e), (n || o) && z(e, Y.getHandles(i, s), {
|
|
1250
|
+
fillColor: f.handleColor,
|
|
1251
|
+
borderColor: f.handleBorderColor,
|
|
1252
|
+
borderThickness: f.handleBorderThickness
|
|
1288
1253
|
}), e.restore();
|
|
1289
1254
|
}
|
|
1290
|
-
static drawDraft({ ctx: e, vertices: i, converter:
|
|
1291
|
-
|
|
1255
|
+
static drawDraft({ ctx: e, vertices: i, converter: s, config: r = Y.defaultConfig }) {
|
|
1256
|
+
Y.draw({
|
|
1292
1257
|
ctx: e,
|
|
1293
1258
|
shape: {
|
|
1294
1259
|
id: "__draft_trendline__",
|
|
1295
1260
|
type: "trendline",
|
|
1296
1261
|
vertices: i
|
|
1297
1262
|
},
|
|
1298
|
-
converter:
|
|
1299
|
-
config:
|
|
1263
|
+
converter: s,
|
|
1264
|
+
config: r,
|
|
1300
1265
|
selected: !0
|
|
1301
1266
|
});
|
|
1302
1267
|
}
|
|
1303
|
-
static getHandles(e, i
|
|
1304
|
-
const [s,
|
|
1305
|
-
return [
|
|
1268
|
+
static getHandles(e, i) {
|
|
1269
|
+
const [s, r] = e.vertices, n = C(s, i), o = C(r, i);
|
|
1270
|
+
return [x({
|
|
1306
1271
|
shapeId: e.id,
|
|
1307
1272
|
type: "start",
|
|
1308
|
-
point:
|
|
1309
|
-
radius:
|
|
1273
|
+
point: n,
|
|
1274
|
+
radius: f.handleRadius,
|
|
1310
1275
|
cursor: "grab"
|
|
1311
|
-
}),
|
|
1276
|
+
}), x({
|
|
1312
1277
|
shapeId: e.id,
|
|
1313
1278
|
type: "end",
|
|
1314
|
-
point:
|
|
1315
|
-
radius:
|
|
1279
|
+
point: o,
|
|
1280
|
+
radius: f.handleRadius,
|
|
1316
1281
|
cursor: "grab"
|
|
1317
1282
|
})];
|
|
1318
1283
|
}
|
|
1319
|
-
static hitTest({ point: e, shape: i, converter:
|
|
1284
|
+
static hitTest({ point: e, shape: i, converter: s, tolerance: r = 8 }) {
|
|
1320
1285
|
const [n, o] = i.vertices;
|
|
1321
|
-
return
|
|
1286
|
+
return yt(e, C(n, s), C(o, s)) <= r;
|
|
1322
1287
|
}
|
|
1323
1288
|
static move(e, i) {
|
|
1324
1289
|
return {
|
|
@@ -1332,51 +1297,45 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1332
1297
|
}]
|
|
1333
1298
|
};
|
|
1334
1299
|
}
|
|
1335
|
-
static resize(e, i,
|
|
1300
|
+
static resize(e, i, s) {
|
|
1336
1301
|
return i === "start" ? {
|
|
1337
1302
|
...e,
|
|
1338
|
-
vertices: [
|
|
1303
|
+
vertices: [s, e.vertices[1]]
|
|
1339
1304
|
} : i === "end" ? {
|
|
1340
1305
|
...e,
|
|
1341
|
-
vertices: [e.vertices[0],
|
|
1306
|
+
vertices: [e.vertices[0], s]
|
|
1342
1307
|
} : e;
|
|
1343
1308
|
}
|
|
1344
|
-
},
|
|
1309
|
+
}, R = class B {
|
|
1345
1310
|
static defaultConfig = {
|
|
1346
1311
|
lineWidth: 2,
|
|
1347
1312
|
lineColor: "#2962ff",
|
|
1348
1313
|
lineOpacity: 1,
|
|
1349
1314
|
lineStyle: "solid",
|
|
1350
1315
|
fillColor: "#2962ff",
|
|
1351
|
-
fillOpacity: 0
|
|
1352
|
-
handleColor: "#ffffff",
|
|
1353
|
-
handleBorderColor: "#2962ff",
|
|
1354
|
-
handleBorderThickness: 1.5,
|
|
1355
|
-
handleRadius: 5,
|
|
1356
|
-
hoverLineWidth: 3,
|
|
1357
|
-
selectedLineWidth: 3
|
|
1316
|
+
fillOpacity: 0
|
|
1358
1317
|
};
|
|
1359
|
-
static draw({ ctx: e, shape: i, converter:
|
|
1360
|
-
const a = i.vertices.map((l) =>
|
|
1318
|
+
static draw({ ctx: e, shape: i, converter: s, config: r = B.defaultConfig, selected: n = !1, hovered: o = !1 }) {
|
|
1319
|
+
const a = i.vertices.map((l) => C(l, s));
|
|
1361
1320
|
if (a.length !== 0) {
|
|
1362
|
-
e.save(),
|
|
1321
|
+
e.save(), Q(e, r), e.beginPath(), e.moveTo(a[0].x, a[0].y);
|
|
1363
1322
|
for (let l = 1; l < a.length; l += 1) e.lineTo(a[l].x, a[l].y);
|
|
1364
|
-
e.stroke(),
|
|
1323
|
+
e.stroke(), E(e), a.length >= 2 && B.drawEndArrow({
|
|
1365
1324
|
ctx: e,
|
|
1366
1325
|
previousPoint: a[a.length - 2],
|
|
1367
1326
|
endPoint: a[a.length - 1],
|
|
1368
|
-
color:
|
|
1369
|
-
opacity:
|
|
1370
|
-
lineWidth:
|
|
1371
|
-
}), (n || o) &&
|
|
1372
|
-
fillColor:
|
|
1373
|
-
borderColor:
|
|
1374
|
-
borderThickness:
|
|
1327
|
+
color: r.lineColor,
|
|
1328
|
+
opacity: r.lineOpacity,
|
|
1329
|
+
lineWidth: r.lineWidth
|
|
1330
|
+
}), (n || o) && z(e, B.getHandles(i, s), {
|
|
1331
|
+
fillColor: f.handleColor,
|
|
1332
|
+
borderColor: f.handleBorderColor,
|
|
1333
|
+
borderThickness: f.handleBorderThickness
|
|
1375
1334
|
}), e.restore();
|
|
1376
1335
|
}
|
|
1377
1336
|
}
|
|
1378
|
-
static drawDraft({ ctx: e, vertices: i, previewVertex:
|
|
1379
|
-
const o =
|
|
1337
|
+
static drawDraft({ ctx: e, vertices: i, previewVertex: s, converter: r, config: n = B.defaultConfig }) {
|
|
1338
|
+
const o = s ? [...i, s] : i;
|
|
1380
1339
|
B.draw({
|
|
1381
1340
|
ctx: e,
|
|
1382
1341
|
shape: {
|
|
@@ -1384,50 +1343,50 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1384
1343
|
type: "path",
|
|
1385
1344
|
vertices: o
|
|
1386
1345
|
},
|
|
1387
|
-
converter:
|
|
1346
|
+
converter: r,
|
|
1388
1347
|
config: n,
|
|
1389
1348
|
selected: !0
|
|
1390
1349
|
});
|
|
1391
1350
|
}
|
|
1392
|
-
static getHandles(e, i
|
|
1393
|
-
return e.vertices.map((s,
|
|
1351
|
+
static getHandles(e, i) {
|
|
1352
|
+
return e.vertices.map((s, r) => x({
|
|
1394
1353
|
shapeId: e.id,
|
|
1395
|
-
type:
|
|
1396
|
-
point:
|
|
1397
|
-
radius:
|
|
1354
|
+
type: r === 0 ? "start" : r === e.vertices.length - 1 ? "end" : "move",
|
|
1355
|
+
point: C(s, i),
|
|
1356
|
+
radius: f.handleRadius,
|
|
1398
1357
|
cursor: "grab",
|
|
1399
|
-
index:
|
|
1358
|
+
index: r
|
|
1400
1359
|
}));
|
|
1401
1360
|
}
|
|
1402
|
-
static hitTest({ point: e, shape: i, converter:
|
|
1403
|
-
const n = i.vertices.map((o) =>
|
|
1361
|
+
static hitTest({ point: e, shape: i, converter: s, tolerance: r = 8 }) {
|
|
1362
|
+
const n = i.vertices.map((o) => C(o, s));
|
|
1404
1363
|
if (n.length === 1) {
|
|
1405
1364
|
const o = n[0], a = e.x - o.x, l = e.y - o.y;
|
|
1406
|
-
return Math.sqrt(a * a + l * l) <=
|
|
1365
|
+
return Math.sqrt(a * a + l * l) <= r;
|
|
1407
1366
|
}
|
|
1408
|
-
for (let o = 1; o < n.length; o += 1) if (
|
|
1367
|
+
for (let o = 1; o < n.length; o += 1) if (yt(e, n[o - 1], n[o]) <= r) return !0;
|
|
1409
1368
|
return !1;
|
|
1410
1369
|
}
|
|
1411
1370
|
static move(e, i) {
|
|
1412
1371
|
return {
|
|
1413
1372
|
...e,
|
|
1414
|
-
vertices: e.vertices.map((
|
|
1415
|
-
time:
|
|
1416
|
-
price:
|
|
1373
|
+
vertices: e.vertices.map((s) => ({
|
|
1374
|
+
time: s.time + i.time,
|
|
1375
|
+
price: s.price + i.price
|
|
1417
1376
|
}))
|
|
1418
1377
|
};
|
|
1419
1378
|
}
|
|
1420
|
-
static resize(e, i,
|
|
1379
|
+
static resize(e, i, s) {
|
|
1421
1380
|
return i < 0 || i >= e.vertices.length ? e : {
|
|
1422
1381
|
...e,
|
|
1423
|
-
vertices: e.vertices.map((
|
|
1382
|
+
vertices: e.vertices.map((r, n) => n === i ? s : r)
|
|
1424
1383
|
};
|
|
1425
1384
|
}
|
|
1426
|
-
static drawEndArrow({ ctx: e, previousPoint: i, endPoint:
|
|
1427
|
-
const a = Math.atan2(
|
|
1428
|
-
e.save(), e.beginPath(), e.strokeStyle =
|
|
1385
|
+
static drawEndArrow({ ctx: e, previousPoint: i, endPoint: s, color: r, opacity: n, lineWidth: o }) {
|
|
1386
|
+
const a = Math.atan2(s.y - i.y, s.x - i.x), l = 12, d = Math.PI / 7;
|
|
1387
|
+
e.save(), e.beginPath(), e.strokeStyle = P(r, n), e.fillStyle = P(r, n), e.lineWidth = o, e.setLineDash([]), e.moveTo(s.x, s.y), e.lineTo(s.x - l * Math.cos(a - d), s.y - l * Math.sin(a - d)), e.lineTo(s.x - l * Math.cos(a + d), s.y - l * Math.sin(a + d)), e.closePath(), e.fill(), e.stroke(), e.restore();
|
|
1429
1388
|
}
|
|
1430
|
-
},
|
|
1389
|
+
}, D = class W {
|
|
1431
1390
|
static defaultConfig = {
|
|
1432
1391
|
lineWidth: 2,
|
|
1433
1392
|
lineColor: "#2962ff",
|
|
@@ -1435,57 +1394,51 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1435
1394
|
lineStyle: "solid",
|
|
1436
1395
|
fillColor: "#2962ff",
|
|
1437
1396
|
fillOpacity: 0.12,
|
|
1438
|
-
handleColor: "#ffffff",
|
|
1439
|
-
handleBorderColor: "#2962ff",
|
|
1440
|
-
handleBorderThickness: 1.5,
|
|
1441
|
-
handleRadius: 5,
|
|
1442
|
-
hoverLineWidth: 3,
|
|
1443
|
-
selectedLineWidth: 3,
|
|
1444
1397
|
textColor: "#ffffff",
|
|
1445
1398
|
textOpacity: 1,
|
|
1446
1399
|
textFontFamily: "Arial",
|
|
1447
1400
|
textFontSize: 20
|
|
1448
1401
|
};
|
|
1449
|
-
static draw({ ctx: e, shape: i, converter:
|
|
1450
|
-
const [a, l] = i.vertices, d =
|
|
1451
|
-
e.save(),
|
|
1452
|
-
fillColor:
|
|
1453
|
-
borderColor:
|
|
1454
|
-
borderThickness:
|
|
1402
|
+
static draw({ ctx: e, shape: i, converter: s, config: r = W.defaultConfig, selected: n = !1, hovered: o = !1 }) {
|
|
1403
|
+
const [a, l] = i.vertices, d = J(a, l, s);
|
|
1404
|
+
e.save(), Pt(e, r.fillColor, r.fillOpacity) && e.fillRect(d.left, d.top, d.width, d.height), Q(e, r), e.strokeRect(d.left, d.top, d.width, d.height), E(e), W.drawText(e, d, i.text, r), (n || o) && z(e, W.getHandles(i, s), {
|
|
1405
|
+
fillColor: f.handleColor,
|
|
1406
|
+
borderColor: f.handleBorderColor,
|
|
1407
|
+
borderThickness: f.handleBorderThickness
|
|
1455
1408
|
}), e.restore();
|
|
1456
1409
|
}
|
|
1457
|
-
static drawDraft({ ctx: e, vertices: i, converter:
|
|
1458
|
-
|
|
1410
|
+
static drawDraft({ ctx: e, vertices: i, converter: s, config: r = W.defaultConfig }) {
|
|
1411
|
+
W.draw({
|
|
1459
1412
|
ctx: e,
|
|
1460
1413
|
shape: {
|
|
1461
1414
|
id: "__draft_rectangle__",
|
|
1462
1415
|
type: "rectangle",
|
|
1463
1416
|
vertices: i
|
|
1464
1417
|
},
|
|
1465
|
-
converter:
|
|
1466
|
-
config:
|
|
1418
|
+
converter: s,
|
|
1419
|
+
config: r,
|
|
1467
1420
|
selected: !0
|
|
1468
1421
|
});
|
|
1469
1422
|
}
|
|
1470
|
-
static getHandles(e, i
|
|
1471
|
-
const [s,
|
|
1472
|
-
return [
|
|
1423
|
+
static getHandles(e, i) {
|
|
1424
|
+
const [s, r] = e.vertices, n = C(s, i), o = C(r, i), a = n.x <= o.x, l = n.y <= o.y, d = a === l ? "nwse-resize" : "nesw-resize", u = a === l ? "nwse-resize" : "nesw-resize";
|
|
1425
|
+
return [x({
|
|
1473
1426
|
shapeId: e.id,
|
|
1474
1427
|
type: "start",
|
|
1475
|
-
point:
|
|
1476
|
-
radius:
|
|
1477
|
-
cursor:
|
|
1478
|
-
}),
|
|
1428
|
+
point: n,
|
|
1429
|
+
radius: f.handleRadius,
|
|
1430
|
+
cursor: d
|
|
1431
|
+
}), x({
|
|
1479
1432
|
shapeId: e.id,
|
|
1480
1433
|
type: "end",
|
|
1481
|
-
point:
|
|
1482
|
-
radius:
|
|
1483
|
-
cursor:
|
|
1434
|
+
point: o,
|
|
1435
|
+
radius: f.handleRadius,
|
|
1436
|
+
cursor: u
|
|
1484
1437
|
})];
|
|
1485
1438
|
}
|
|
1486
|
-
static hitTest({ point: e, shape: i, converter:
|
|
1439
|
+
static hitTest({ point: e, shape: i, converter: s, tolerance: r = 8 }) {
|
|
1487
1440
|
const [n, o] = i.vertices;
|
|
1488
|
-
return
|
|
1441
|
+
return $t(e, J(n, o, s), r);
|
|
1489
1442
|
}
|
|
1490
1443
|
static move(e, i) {
|
|
1491
1444
|
return {
|
|
@@ -1499,35 +1452,35 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1499
1452
|
}]
|
|
1500
1453
|
};
|
|
1501
1454
|
}
|
|
1502
|
-
static resize(e, i,
|
|
1455
|
+
static resize(e, i, s) {
|
|
1503
1456
|
return i === "start" ? {
|
|
1504
1457
|
...e,
|
|
1505
|
-
vertices: [
|
|
1458
|
+
vertices: [s, e.vertices[1]]
|
|
1506
1459
|
} : i === "end" ? {
|
|
1507
1460
|
...e,
|
|
1508
|
-
vertices: [e.vertices[0],
|
|
1461
|
+
vertices: [e.vertices[0], s]
|
|
1509
1462
|
} : e;
|
|
1510
1463
|
}
|
|
1511
|
-
static drawText(e, i,
|
|
1512
|
-
const n =
|
|
1513
|
-
n && (e.save(), e.beginPath(), e.rect(i.left, i.top, i.width, i.height), e.clip(), e.font = `${
|
|
1464
|
+
static drawText(e, i, s, r) {
|
|
1465
|
+
const n = s?.trim();
|
|
1466
|
+
n && (e.save(), e.beginPath(), e.rect(i.left, i.top, i.width, i.height), e.clip(), e.font = `${r.textFontSize}px ${r.textFontFamily}`, e.globalAlpha = r.textOpacity, e.fillStyle = r.textColor, e.textAlign = "center", e.textBaseline = "middle", e.fillText(n, i.left + i.width / 2, i.top + i.height / 2), e.restore());
|
|
1514
1467
|
}
|
|
1515
|
-
},
|
|
1468
|
+
}, bt = [
|
|
1516
1469
|
"USDJPY",
|
|
1517
1470
|
"GBPJPY",
|
|
1518
1471
|
"AUDJPY",
|
|
1519
1472
|
"EURJPY",
|
|
1520
1473
|
"NZDJPY",
|
|
1521
1474
|
"CADJPY"
|
|
1522
|
-
],
|
|
1475
|
+
], xt = ["BTCUSD", "ETHUSD"], St = [
|
|
1523
1476
|
"XAUUSD",
|
|
1524
1477
|
"USOIL",
|
|
1525
1478
|
"UKOIL",
|
|
1526
1479
|
"XAGUSD"
|
|
1527
|
-
], Tt = (t) =>
|
|
1528
|
-
const n =
|
|
1480
|
+
], Tt = (t) => bt.some((e) => t.includes(e.slice(3))) ? 0.01 : xt.includes(t) ? 1 : St.includes(t) ? 0.01 : 1e-4, qt = (t, e) => bt.includes(t) ? e * 6.33806 : xt.includes(t) ? e * 1 : (St.includes(t), e * 10), ut = (t, e, i, s, r) => {
|
|
1481
|
+
const n = r.split(".")[0], o = Tt(n), a = qt(n, s);
|
|
1529
1482
|
return (t === "buy" ? i - e : e - i) / o * a;
|
|
1530
|
-
},
|
|
1483
|
+
}, H = class w {
|
|
1531
1484
|
static defaultLongConfig = {
|
|
1532
1485
|
defaultWidthCandles: 10,
|
|
1533
1486
|
defaultStopLossPercent: 0.25,
|
|
@@ -1543,123 +1496,117 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1543
1496
|
midLineColor: "#808080",
|
|
1544
1497
|
midLineOpacity: 0.9,
|
|
1545
1498
|
midLineWidth: 1,
|
|
1546
|
-
midLineStyle: "dashed"
|
|
1547
|
-
handleColor: "#ffffff",
|
|
1548
|
-
handleBorderColor: "#2962ff",
|
|
1549
|
-
handleBorderThickness: 1.5,
|
|
1550
|
-
handleRadius: 5,
|
|
1551
|
-
hoverLineWidth: 2,
|
|
1552
|
-
selectedLineWidth: 2
|
|
1499
|
+
midLineStyle: "dashed"
|
|
1553
1500
|
};
|
|
1554
|
-
static defaultShortConfig = { ...
|
|
1555
|
-
static draw({ ctx: e, activeSymbol: i, shape:
|
|
1556
|
-
const l =
|
|
1557
|
-
e.save(), e.fillStyle =
|
|
1558
|
-
const d =
|
|
1559
|
-
e.strokeStyle =
|
|
1501
|
+
static defaultShortConfig = { ...w.defaultLongConfig };
|
|
1502
|
+
static draw({ ctx: e, activeSymbol: i, shape: s, converter: r, config: n = s.type === "longPosition" ? w.defaultLongConfig : w.defaultShortConfig, selected: o = !1, hovered: a = !1 }) {
|
|
1503
|
+
const l = w.getGeometry(s, r);
|
|
1504
|
+
e.save(), e.fillStyle = P(n.profitFillColor, n.profitFillOpacity), e.fillRect(l.profitBox.left, l.profitBox.top, l.profitBox.width, l.profitBox.height), e.fillStyle = P(n.lossFillColor, n.lossFillOpacity), e.fillRect(l.lossBox.left, l.lossBox.top, l.lossBox.width, l.lossBox.height);
|
|
1505
|
+
const d = n.borderWidth;
|
|
1506
|
+
e.strokeStyle = P(n.borderColor, n.borderOpacity), e.lineWidth = d, e.setLineDash(V(n.borderStyle, d)), e.strokeRect(l.box.left, l.box.top, l.box.width, l.box.height), e.beginPath(), e.strokeStyle = P(n.midLineColor, n.midLineOpacity), e.lineWidth = n.midLineWidth, e.setLineDash(V(n.midLineStyle, n.midLineWidth)), e.moveTo(l.box.left, l.entryY), e.lineTo(l.box.right, l.entryY), e.stroke(), E(e), w.drawLabels({
|
|
1560
1507
|
ctx: e,
|
|
1561
1508
|
activeSymbol: i,
|
|
1562
|
-
shape:
|
|
1509
|
+
shape: s,
|
|
1563
1510
|
geometry: l,
|
|
1564
1511
|
config: n
|
|
1565
|
-
}), (o || a) &&
|
|
1566
|
-
fillColor:
|
|
1567
|
-
borderColor:
|
|
1568
|
-
borderThickness:
|
|
1512
|
+
}), (o || a) && z(e, w.getHandles(s, r), {
|
|
1513
|
+
fillColor: f.handleColor,
|
|
1514
|
+
borderColor: f.handleBorderColor,
|
|
1515
|
+
borderThickness: f.handleBorderThickness
|
|
1569
1516
|
}), e.restore();
|
|
1570
1517
|
}
|
|
1571
|
-
static createFromVertex({ id: e, type: i, entry:
|
|
1572
|
-
const o =
|
|
1518
|
+
static createFromVertex({ id: e, type: i, entry: s, converter: r, config: n = i === "longPosition" ? w.defaultLongConfig : w.defaultShortConfig }) {
|
|
1519
|
+
const o = r.getTimeForX(r.getXForTime(s.time) + r.getCandleWidth() * n.defaultWidthCandles), a = n.defaultStopLossPercent;
|
|
1573
1520
|
return {
|
|
1574
1521
|
id: e,
|
|
1575
1522
|
type: i,
|
|
1576
|
-
entry:
|
|
1523
|
+
entry: s,
|
|
1577
1524
|
endTime: o,
|
|
1578
1525
|
stopLossPercent: a,
|
|
1579
1526
|
takeProfitPercent: a * n.defaultRiskRewardRatio
|
|
1580
1527
|
};
|
|
1581
1528
|
}
|
|
1582
1529
|
static getGeometry(e, i) {
|
|
1583
|
-
const
|
|
1530
|
+
const s = C(e.entry, i), r = i.getXForTime(e.endTime), n = Math.min(s.x, r), o = Math.max(s.x, r), a = e.type === "longPosition", l = a ? e.takeProfitPercent : e.stopLossPercent, d = a ? e.stopLossPercent : e.takeProfitPercent, u = e.entry.price * (1 + l / 100), g = e.entry.price * (1 - d / 100), m = i.getYForPrice(u), b = i.getYForPrice(g), v = Math.min(m, b, s.y), S = Math.max(m, b, s.y), T = {
|
|
1584
1531
|
left: n,
|
|
1585
|
-
top:
|
|
1532
|
+
top: v,
|
|
1586
1533
|
right: o,
|
|
1587
|
-
bottom:
|
|
1534
|
+
bottom: s.y,
|
|
1588
1535
|
width: o - n,
|
|
1589
|
-
height: Math.abs(
|
|
1590
|
-
},
|
|
1536
|
+
height: Math.abs(s.y - v)
|
|
1537
|
+
}, k = {
|
|
1591
1538
|
left: n,
|
|
1592
|
-
top:
|
|
1539
|
+
top: s.y,
|
|
1593
1540
|
right: o,
|
|
1594
|
-
bottom:
|
|
1541
|
+
bottom: S,
|
|
1595
1542
|
width: o - n,
|
|
1596
|
-
height: Math.abs(
|
|
1543
|
+
height: Math.abs(S - s.y)
|
|
1597
1544
|
};
|
|
1598
1545
|
return {
|
|
1599
|
-
entryPoint:
|
|
1600
|
-
endX:
|
|
1601
|
-
entryY:
|
|
1546
|
+
entryPoint: s,
|
|
1547
|
+
endX: r,
|
|
1548
|
+
entryY: s.y,
|
|
1602
1549
|
upperPrice: u,
|
|
1603
1550
|
lowerPrice: g,
|
|
1604
1551
|
box: {
|
|
1605
1552
|
left: n,
|
|
1606
|
-
top:
|
|
1553
|
+
top: v,
|
|
1607
1554
|
right: o,
|
|
1608
|
-
bottom:
|
|
1555
|
+
bottom: S,
|
|
1609
1556
|
width: o - n,
|
|
1610
|
-
height:
|
|
1557
|
+
height: S - v
|
|
1611
1558
|
},
|
|
1612
|
-
profitBox: a ? T :
|
|
1613
|
-
lossBox: a ?
|
|
1559
|
+
profitBox: a ? T : k,
|
|
1560
|
+
lossBox: a ? k : T
|
|
1614
1561
|
};
|
|
1615
1562
|
}
|
|
1616
|
-
static getHandles(e, i
|
|
1617
|
-
const s =
|
|
1563
|
+
static getHandles(e, i) {
|
|
1564
|
+
const s = w.getGeometry(e, i);
|
|
1618
1565
|
return [
|
|
1619
|
-
|
|
1566
|
+
x({
|
|
1620
1567
|
shapeId: e.id,
|
|
1621
1568
|
type: "upperHeight",
|
|
1622
1569
|
point: {
|
|
1623
|
-
x:
|
|
1624
|
-
y:
|
|
1570
|
+
x: s.box.left,
|
|
1571
|
+
y: s.box.top
|
|
1625
1572
|
},
|
|
1626
|
-
radius:
|
|
1573
|
+
radius: f.handleRadius,
|
|
1627
1574
|
cursor: "ns-resize"
|
|
1628
1575
|
}),
|
|
1629
|
-
|
|
1576
|
+
x({
|
|
1630
1577
|
shapeId: e.id,
|
|
1631
1578
|
type: "lowerHeight",
|
|
1632
1579
|
point: {
|
|
1633
|
-
x:
|
|
1634
|
-
y:
|
|
1580
|
+
x: s.box.left,
|
|
1581
|
+
y: s.box.bottom
|
|
1635
1582
|
},
|
|
1636
|
-
radius:
|
|
1583
|
+
radius: f.handleRadius,
|
|
1637
1584
|
cursor: "ns-resize"
|
|
1638
1585
|
}),
|
|
1639
|
-
|
|
1586
|
+
x({
|
|
1640
1587
|
shapeId: e.id,
|
|
1641
1588
|
type: "start",
|
|
1642
1589
|
point: {
|
|
1643
|
-
x:
|
|
1644
|
-
y:
|
|
1590
|
+
x: s.entryPoint.x,
|
|
1591
|
+
y: s.entryY
|
|
1645
1592
|
},
|
|
1646
|
-
radius:
|
|
1593
|
+
radius: f.handleRadius,
|
|
1647
1594
|
cursor: "ns-resize"
|
|
1648
1595
|
}),
|
|
1649
|
-
|
|
1596
|
+
x({
|
|
1650
1597
|
shapeId: e.id,
|
|
1651
1598
|
type: "end",
|
|
1652
1599
|
point: {
|
|
1653
|
-
x:
|
|
1654
|
-
y:
|
|
1600
|
+
x: s.endX,
|
|
1601
|
+
y: s.entryY
|
|
1655
1602
|
},
|
|
1656
|
-
radius:
|
|
1603
|
+
radius: f.handleRadius,
|
|
1657
1604
|
cursor: "ew-resize"
|
|
1658
1605
|
})
|
|
1659
1606
|
];
|
|
1660
1607
|
}
|
|
1661
|
-
static hitTest({ point: e, shape: i, converter:
|
|
1662
|
-
return
|
|
1608
|
+
static hitTest({ point: e, shape: i, converter: s }) {
|
|
1609
|
+
return w.getHandles(i, s).some((r) => j(e, r)) ? !0 : wt(e, w.getGeometry(i, s).box);
|
|
1663
1610
|
}
|
|
1664
1611
|
static move(e, i) {
|
|
1665
1612
|
return {
|
|
@@ -1671,51 +1618,51 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1671
1618
|
endTime: e.endTime + i.time
|
|
1672
1619
|
};
|
|
1673
1620
|
}
|
|
1674
|
-
static resize({ shape: e, handleType: i, vertex:
|
|
1621
|
+
static resize({ shape: e, handleType: i, vertex: s, converter: r }) {
|
|
1675
1622
|
return i === "start" ? {
|
|
1676
1623
|
...e,
|
|
1677
1624
|
entry: {
|
|
1678
1625
|
time: e.entry.time,
|
|
1679
|
-
price:
|
|
1626
|
+
price: s.price
|
|
1680
1627
|
}
|
|
1681
1628
|
} : i === "end" ? {
|
|
1682
1629
|
...e,
|
|
1683
|
-
endTime:
|
|
1684
|
-
} : i === "upperHeight" ?
|
|
1630
|
+
endTime: s.time
|
|
1631
|
+
} : i === "upperHeight" ? w.resizeUpperHeight(e, s.price) : i === "lowerHeight" ? w.resizeLowerHeight(e, s.price) : {
|
|
1685
1632
|
...e,
|
|
1686
|
-
endTime:
|
|
1633
|
+
endTime: r.getTimeForX(r.getXForTime(e.endTime))
|
|
1687
1634
|
};
|
|
1688
1635
|
}
|
|
1689
1636
|
static resizeUpperHeight(e, i) {
|
|
1690
|
-
const
|
|
1637
|
+
const s = Math.max(0, (i - e.entry.price) / e.entry.price * 100);
|
|
1691
1638
|
return e.type === "longPosition" ? {
|
|
1692
1639
|
...e,
|
|
1693
|
-
takeProfitPercent:
|
|
1640
|
+
takeProfitPercent: s
|
|
1694
1641
|
} : {
|
|
1695
1642
|
...e,
|
|
1696
|
-
stopLossPercent:
|
|
1643
|
+
stopLossPercent: s
|
|
1697
1644
|
};
|
|
1698
1645
|
}
|
|
1699
1646
|
static resizeLowerHeight(e, i) {
|
|
1700
|
-
const
|
|
1647
|
+
const s = Math.max(0, (e.entry.price - i) / e.entry.price * 100);
|
|
1701
1648
|
return e.type === "longPosition" ? {
|
|
1702
1649
|
...e,
|
|
1703
|
-
stopLossPercent:
|
|
1650
|
+
stopLossPercent: s
|
|
1704
1651
|
} : {
|
|
1705
1652
|
...e,
|
|
1706
|
-
takeProfitPercent:
|
|
1653
|
+
takeProfitPercent: s
|
|
1707
1654
|
};
|
|
1708
1655
|
}
|
|
1709
|
-
static drawLabels({ ctx: e, activeSymbol: i, shape:
|
|
1656
|
+
static drawLabels({ ctx: e, activeSymbol: i, shape: s, geometry: r, config: n }) {
|
|
1710
1657
|
e.save(), e.font = "11px sans-serif", e.textBaseline = "middle";
|
|
1711
|
-
const o =
|
|
1712
|
-
e.fillStyle =
|
|
1713
|
-
const m = o === "longPosition" ?
|
|
1714
|
-
e.fillText(`${l.toFixed(2)} (${g.toFixed(2)})`, u, m), e.fillStyle =
|
|
1715
|
-
const
|
|
1716
|
-
e.fillText(d.toFixed(1), u,
|
|
1717
|
-
}
|
|
1718
|
-
},
|
|
1658
|
+
const o = s.type, a = Tt(i), l = s.entry.price * (s.takeProfitPercent / 100) / a, d = s.entry.price * (s.stopLossPercent / 100) / a, u = r.box.left + 6, g = l / d;
|
|
1659
|
+
e.fillStyle = P(n.profitFillColor, 0.95);
|
|
1660
|
+
const m = o === "longPosition" ? r.profitBox.top + r.profitBox.height / 10 : r.profitBox.bottom - r.profitBox.height / 10;
|
|
1661
|
+
e.fillText(`${l.toFixed(2)} (${g.toFixed(2)})`, u, m), e.fillStyle = P(n.lossFillColor, 0.95);
|
|
1662
|
+
const b = o === "shortPosition" ? r.lossBox.top + r.lossBox.height / 10 : r.lossBox.bottom - r.lossBox.height / 10;
|
|
1663
|
+
e.fillText(d.toFixed(1), u, b);
|
|
1664
|
+
}
|
|
1665
|
+
}, Qt = class {
|
|
1719
1666
|
canvas;
|
|
1720
1667
|
ctx;
|
|
1721
1668
|
activeSymbol;
|
|
@@ -1729,15 +1676,18 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1729
1676
|
handleHitboxes = [];
|
|
1730
1677
|
draft = null;
|
|
1731
1678
|
dragState = null;
|
|
1679
|
+
lastTapTime = 0;
|
|
1680
|
+
lastTapShapeId = null;
|
|
1732
1681
|
onShapeAdded;
|
|
1733
1682
|
onShapeModified;
|
|
1734
1683
|
onShapeSelected;
|
|
1684
|
+
onShapeDoubleClicked;
|
|
1735
1685
|
onToolChange;
|
|
1736
1686
|
constructor(t) {
|
|
1737
1687
|
this.canvas = t.canvas;
|
|
1738
1688
|
const e = this.canvas.getContext("2d");
|
|
1739
1689
|
if (!e) throw new Error("Failed to get 2d context for ShapesLayer");
|
|
1740
|
-
this.ctx = e, this.activeSymbol = t.activeSymbol, this.candles = t.candles, this.shapes = t.shapes, this.activeTool = t.activeTool ?? null, this.config = this.mergeConfig(t.config), this.onShapeAdded = t.onShapeAdded, this.onShapeModified = t.onShapeModified, this.onShapeSelected = t.onShapeSelected, this.onToolChange = t.onToolChange;
|
|
1690
|
+
this.ctx = e, this.activeSymbol = t.activeSymbol, this.candles = t.candles, this.shapes = t.shapes, this.activeTool = t.activeTool ?? null, this.config = this.mergeConfig(t.config), this.onShapeAdded = t.onShapeAdded, this.onShapeModified = t.onShapeModified, this.onShapeSelected = t.onShapeSelected, this.onShapeDoubleClicked = t.onShapeDoubleClicked, this.onToolChange = t.onToolChange;
|
|
1741
1691
|
}
|
|
1742
1692
|
setCandles(t) {
|
|
1743
1693
|
this.candles = t;
|
|
@@ -1769,61 +1719,93 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1769
1719
|
this.drawDraft(t), this.rebuildHandleHitboxes();
|
|
1770
1720
|
}
|
|
1771
1721
|
handlePointerEvent(t) {
|
|
1772
|
-
return !this.viewport || this.candles.length === 0 ? !1 : t.type === "contextmenu" ? this.handleContextMenu() : t.type === "pointerdown" || t.type === "mousedown" ? this.handlePointerDown(t) : t.type === "pointermove" || t.type === "mousemove" ? this.handlePointerMove(t) : t.type === "pointerup" || t.type === "mouseup" ? this.handlePointerUp() : !1;
|
|
1722
|
+
return !this.viewport || this.candles.length === 0 ? !1 : t.type === "contextmenu" ? this.handleContextMenu() : t.type === "pointerdown" || t.type === "mousedown" ? this.handlePointerDown(t) : t.type === "pointermove" || t.type === "mousemove" ? this.handlePointerMove(t) : t.type === "pointerup" || t.type === "mouseup" ? this.handlePointerUp() : t.type === "dblclick" ? this.handleDoubleClick(t) : !1;
|
|
1773
1723
|
}
|
|
1774
1724
|
handleKeyboardEvent(t) {
|
|
1775
|
-
|
|
1725
|
+
if (t.key === "Escape" && this.draft?.type === "path")
|
|
1726
|
+
return this.completePathDraft(), !0;
|
|
1727
|
+
if (t.key === "Escape" && this.draft)
|
|
1728
|
+
return this.draft = null, this.setActiveToolAndEmit(null), !0;
|
|
1729
|
+
if (t.key === "Escape" && this.selectedShapeId)
|
|
1730
|
+
return this.setSelectedShapeId(null), !0;
|
|
1731
|
+
if (this.selectedShapeId && !this.draft && !this.activeTool && (t.key === "ArrowLeft" || t.key === "ArrowRight" || t.key === "ArrowUp" || t.key === "ArrowDown")) {
|
|
1732
|
+
const e = this.shapes.find((i) => i.id === this.selectedShapeId);
|
|
1733
|
+
if (e) {
|
|
1734
|
+
const i = this.getArrowKeyDelta(t.key), s = this.moveShape(e, i);
|
|
1735
|
+
return this.emitShapeModified(s), !0;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return !1;
|
|
1739
|
+
}
|
|
1740
|
+
getArrowKeyDelta(t) {
|
|
1741
|
+
const e = q(this.candles);
|
|
1742
|
+
if (t === "ArrowLeft") return {
|
|
1743
|
+
time: -e,
|
|
1744
|
+
price: 0
|
|
1745
|
+
};
|
|
1746
|
+
if (t === "ArrowRight") return {
|
|
1747
|
+
time: e,
|
|
1748
|
+
price: 0
|
|
1749
|
+
};
|
|
1750
|
+
const i = this.viewport ? this.viewport.priceRange / this.canvas.height * 10 : 0;
|
|
1751
|
+
return t === "ArrowUp" ? {
|
|
1752
|
+
time: 0,
|
|
1753
|
+
price: i
|
|
1754
|
+
} : {
|
|
1755
|
+
time: 0,
|
|
1756
|
+
price: -i
|
|
1757
|
+
};
|
|
1776
1758
|
}
|
|
1777
1759
|
handlePointerDown(t) {
|
|
1778
|
-
const e =
|
|
1760
|
+
const e = $(this.canvas, t), i = ht(e, this.getConverter());
|
|
1779
1761
|
if (this.activeTool)
|
|
1780
|
-
return
|
|
1762
|
+
return ct(t) && this.handleToolPointerDown({
|
|
1781
1763
|
point: e,
|
|
1782
1764
|
vertex: i
|
|
1783
1765
|
}), !0;
|
|
1784
|
-
if (!
|
|
1785
|
-
const
|
|
1786
|
-
if (
|
|
1787
|
-
const n = this.shapes.find((o) => o.id ===
|
|
1788
|
-
return n ? (this.setSelectedShapeId(n.id), this.dragState = {
|
|
1766
|
+
if (!ct(t)) return !1;
|
|
1767
|
+
const s = this.findHandleAtPoint(e);
|
|
1768
|
+
if (s) {
|
|
1769
|
+
const n = this.shapes.find((o) => o.id === s.shapeId);
|
|
1770
|
+
return n ? (this.setSelectedShapeId(n.id), this.checkTouchDoubleTap(n, t), this.dragState = {
|
|
1789
1771
|
edit: {
|
|
1790
1772
|
mode: "resize",
|
|
1791
1773
|
shape: n,
|
|
1792
|
-
handleType:
|
|
1793
|
-
handleIndex:
|
|
1774
|
+
handleType: s.type,
|
|
1775
|
+
handleIndex: s.index,
|
|
1794
1776
|
startPoint: e,
|
|
1795
1777
|
startVertex: i
|
|
1796
1778
|
},
|
|
1797
1779
|
lastModifiedShape: n
|
|
1798
|
-
}, this.canvas.style.cursor =
|
|
1780
|
+
}, this.canvas.style.cursor = s.cursor ?? "grab", !0) : !1;
|
|
1799
1781
|
}
|
|
1800
|
-
const
|
|
1801
|
-
if (
|
|
1802
|
-
const n = this.findHandleAtPointForShape(
|
|
1803
|
-
return n ? (this.setSelectedShapeId(
|
|
1782
|
+
const r = this.findShapeAtPoint(e);
|
|
1783
|
+
if (r) {
|
|
1784
|
+
const n = this.findHandleAtPointForShape(r, e);
|
|
1785
|
+
return n ? (this.setSelectedShapeId(r.id), this.checkTouchDoubleTap(r, t), this.dragState = {
|
|
1804
1786
|
edit: {
|
|
1805
1787
|
mode: "resize",
|
|
1806
|
-
shape:
|
|
1788
|
+
shape: r,
|
|
1807
1789
|
handleType: n.type,
|
|
1808
1790
|
handleIndex: n.index,
|
|
1809
1791
|
startPoint: e,
|
|
1810
1792
|
startVertex: i
|
|
1811
1793
|
},
|
|
1812
|
-
lastModifiedShape:
|
|
1813
|
-
}, this.canvas.style.cursor = n.cursor ?? "grab", !0) : (this.setSelectedShapeId(
|
|
1794
|
+
lastModifiedShape: r
|
|
1795
|
+
}, this.canvas.style.cursor = n.cursor ?? "grab", !0) : (this.setSelectedShapeId(r.id), this.checkTouchDoubleTap(r, t), this.hoveredShapeId = r.id, this.dragState = {
|
|
1814
1796
|
edit: {
|
|
1815
1797
|
mode: "move",
|
|
1816
|
-
shape:
|
|
1798
|
+
shape: r,
|
|
1817
1799
|
startPoint: e,
|
|
1818
1800
|
startVertex: i
|
|
1819
1801
|
},
|
|
1820
|
-
lastModifiedShape:
|
|
1802
|
+
lastModifiedShape: r
|
|
1821
1803
|
}, this.canvas.style.cursor = "move", !0);
|
|
1822
1804
|
}
|
|
1823
1805
|
return this.setSelectedShapeId(null), this.hoveredShapeId = null, this.canvas.style.cursor = "crosshair", !1;
|
|
1824
1806
|
}
|
|
1825
1807
|
handlePointerMove(t) {
|
|
1826
|
-
const e =
|
|
1808
|
+
const e = $(this.canvas, t), i = ht(e, this.getConverter());
|
|
1827
1809
|
if (this.draft)
|
|
1828
1810
|
return this.updateDraftPreview(i), !0;
|
|
1829
1811
|
if (this.dragState) {
|
|
@@ -1832,17 +1814,27 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1832
1814
|
}
|
|
1833
1815
|
if (this.activeTool)
|
|
1834
1816
|
return this.canvas.style.cursor = "crosshair", !0;
|
|
1835
|
-
const
|
|
1836
|
-
if (
|
|
1837
|
-
return this.canvas.style.cursor = "pointer", this.hoveredShapeId =
|
|
1838
|
-
const
|
|
1839
|
-
return
|
|
1817
|
+
const s = this.findHandleAtPoint(e);
|
|
1818
|
+
if (s)
|
|
1819
|
+
return this.canvas.style.cursor = "pointer", this.hoveredShapeId = s.shapeId, !0;
|
|
1820
|
+
const r = this.findShapeAtPoint(e);
|
|
1821
|
+
return r ? (this.hoveredShapeId = r.id, this.canvas.style.cursor = "pointer", !0) : this.hoveredShapeId !== null ? (this.hoveredShapeId = null, this.canvas.style.cursor = "crosshair", !0) : !1;
|
|
1840
1822
|
}
|
|
1841
1823
|
handlePointerUp() {
|
|
1842
1824
|
if (!this.dragState) return !1;
|
|
1843
1825
|
const t = this.dragState.lastModifiedShape;
|
|
1844
1826
|
return this.dragState = null, this.setSelectedShapeId(t.id), this.emitShapeModified(t), !0;
|
|
1845
1827
|
}
|
|
1828
|
+
handleDoubleClick(t) {
|
|
1829
|
+
if (!this.onShapeDoubleClicked) return !1;
|
|
1830
|
+
const e = $(this.canvas, t), i = this.findShapeAtPoint(e);
|
|
1831
|
+
return i ? (this.onShapeDoubleClicked(this.createShapeSelectedPayload(i)), !0) : !1;
|
|
1832
|
+
}
|
|
1833
|
+
checkTouchDoubleTap(t, e) {
|
|
1834
|
+
if (!(e instanceof PointerEvent) || e.pointerType !== "touch") return;
|
|
1835
|
+
const i = Date.now();
|
|
1836
|
+
t.id === this.lastTapShapeId && i - this.lastTapTime < 300 && this.onShapeDoubleClicked?.(this.createShapeSelectedPayload(t)), this.lastTapTime = i, this.lastTapShapeId = t.id;
|
|
1837
|
+
}
|
|
1846
1838
|
handleContextMenu() {
|
|
1847
1839
|
return this.draft?.type === "path" ? (this.completePathDraft(), !0) : this.activeTool !== null;
|
|
1848
1840
|
}
|
|
@@ -1907,14 +1899,14 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1907
1899
|
}), this.draft = null, this.setActiveToolAndEmit(null));
|
|
1908
1900
|
}
|
|
1909
1901
|
addPositionShape(t, e) {
|
|
1910
|
-
const i = this.getConverter(),
|
|
1902
|
+
const i = this.getConverter(), s = t === "longPosition" ? this.config.longPosition : this.config.shortPosition, r = H.createFromVertex({
|
|
1911
1903
|
id: U(),
|
|
1912
1904
|
type: t,
|
|
1913
1905
|
entry: e,
|
|
1914
1906
|
converter: i,
|
|
1915
|
-
config:
|
|
1907
|
+
config: s
|
|
1916
1908
|
});
|
|
1917
|
-
this.addShape(
|
|
1909
|
+
this.addShape(r), this.setActiveToolAndEmit(null);
|
|
1918
1910
|
}
|
|
1919
1911
|
updateDraftPreview(t) {
|
|
1920
1912
|
if (this.draft) {
|
|
@@ -1958,80 +1950,80 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
1958
1950
|
return this.resizeShape(e.shape, e.handleType, t, e.handleIndex);
|
|
1959
1951
|
}
|
|
1960
1952
|
moveShape(t, e) {
|
|
1961
|
-
return t.type === "trendline" ?
|
|
1953
|
+
return t.type === "trendline" ? M.move(t, e) : t.type === "rectangle" ? D.move(t, e) : t.type === "path" ? R.move(t, e) : t.type === "fibRetracement" ? L.move(t, e) : H.move(t, e);
|
|
1962
1954
|
}
|
|
1963
|
-
resizeShape(t, e, i,
|
|
1964
|
-
return t.type === "trendline" ?
|
|
1955
|
+
resizeShape(t, e, i, s) {
|
|
1956
|
+
return t.type === "trendline" ? M.resize(t, e, i) : t.type === "rectangle" ? D.resize(t, e, i) : t.type === "fibRetracement" ? L.resize(t, e, i) : t.type === "path" ? R.resize(t, s ?? -1, i) : H.resize({
|
|
1965
1957
|
shape: t,
|
|
1966
1958
|
handleType: e,
|
|
1967
1959
|
vertex: i,
|
|
1968
1960
|
converter: this.getConverter()
|
|
1969
1961
|
});
|
|
1970
1962
|
}
|
|
1971
|
-
drawShape({ shape: t, converter: e, selected: i, hovered:
|
|
1963
|
+
drawShape({ shape: t, converter: e, selected: i, hovered: s }) {
|
|
1972
1964
|
if (t.type === "trendline") {
|
|
1973
1965
|
const n = this.getTrendlineConfig(t);
|
|
1974
|
-
|
|
1966
|
+
M.draw({
|
|
1975
1967
|
ctx: this.ctx,
|
|
1976
1968
|
shape: t,
|
|
1977
1969
|
converter: e,
|
|
1978
1970
|
config: n,
|
|
1979
1971
|
selected: i,
|
|
1980
|
-
hovered:
|
|
1972
|
+
hovered: s
|
|
1981
1973
|
});
|
|
1982
1974
|
return;
|
|
1983
1975
|
}
|
|
1984
1976
|
if (t.type === "rectangle") {
|
|
1985
1977
|
const n = this.getRectangleConfig(t);
|
|
1986
|
-
|
|
1978
|
+
D.draw({
|
|
1987
1979
|
ctx: this.ctx,
|
|
1988
1980
|
shape: t,
|
|
1989
1981
|
converter: e,
|
|
1990
1982
|
config: n,
|
|
1991
1983
|
selected: i,
|
|
1992
|
-
hovered:
|
|
1984
|
+
hovered: s
|
|
1993
1985
|
});
|
|
1994
1986
|
return;
|
|
1995
1987
|
}
|
|
1996
1988
|
if (t.type === "path") {
|
|
1997
1989
|
const n = this.getPathConfig(t);
|
|
1998
|
-
|
|
1990
|
+
R.draw({
|
|
1999
1991
|
ctx: this.ctx,
|
|
2000
1992
|
shape: t,
|
|
2001
1993
|
converter: e,
|
|
2002
1994
|
config: n,
|
|
2003
1995
|
selected: i,
|
|
2004
|
-
hovered:
|
|
1996
|
+
hovered: s
|
|
2005
1997
|
});
|
|
2006
1998
|
return;
|
|
2007
1999
|
}
|
|
2008
2000
|
if (t.type === "fibRetracement") {
|
|
2009
2001
|
const n = this.getFibRetracementConfig(t);
|
|
2010
|
-
|
|
2002
|
+
L.draw({
|
|
2011
2003
|
ctx: this.ctx,
|
|
2012
2004
|
shape: t,
|
|
2013
2005
|
converter: e,
|
|
2014
2006
|
config: n,
|
|
2015
2007
|
selected: i,
|
|
2016
|
-
hovered:
|
|
2008
|
+
hovered: s
|
|
2017
2009
|
});
|
|
2018
2010
|
return;
|
|
2019
2011
|
}
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2012
|
+
const r = this.getPositionConfig(t);
|
|
2013
|
+
H.draw({
|
|
2022
2014
|
ctx: this.ctx,
|
|
2023
2015
|
activeSymbol: this.activeSymbol,
|
|
2024
2016
|
shape: t,
|
|
2025
2017
|
converter: e,
|
|
2026
|
-
config:
|
|
2018
|
+
config: r,
|
|
2027
2019
|
selected: i,
|
|
2028
|
-
hovered:
|
|
2020
|
+
hovered: s
|
|
2029
2021
|
});
|
|
2030
2022
|
}
|
|
2031
2023
|
drawDraft(t) {
|
|
2032
2024
|
if (this.draft) {
|
|
2033
2025
|
if (this.draft.type === "trendline") {
|
|
2034
|
-
|
|
2026
|
+
M.drawDraft({
|
|
2035
2027
|
ctx: this.ctx,
|
|
2036
2028
|
vertices: this.draft.vertices,
|
|
2037
2029
|
converter: t,
|
|
@@ -2040,7 +2032,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2040
2032
|
return;
|
|
2041
2033
|
}
|
|
2042
2034
|
if (this.draft.type === "rectangle") {
|
|
2043
|
-
|
|
2035
|
+
D.drawDraft({
|
|
2044
2036
|
ctx: this.ctx,
|
|
2045
2037
|
vertices: this.draft.vertices,
|
|
2046
2038
|
converter: t,
|
|
@@ -2049,7 +2041,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2049
2041
|
return;
|
|
2050
2042
|
}
|
|
2051
2043
|
if (this.draft.type === "fibRetracement") {
|
|
2052
|
-
|
|
2044
|
+
L.drawDraft({
|
|
2053
2045
|
ctx: this.ctx,
|
|
2054
2046
|
vertices: this.draft.vertices,
|
|
2055
2047
|
converter: t,
|
|
@@ -2057,7 +2049,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2057
2049
|
});
|
|
2058
2050
|
return;
|
|
2059
2051
|
}
|
|
2060
|
-
this.draft.type === "path" &&
|
|
2052
|
+
this.draft.type === "path" && R.drawDraft({
|
|
2061
2053
|
ctx: this.ctx,
|
|
2062
2054
|
vertices: this.draft.vertices,
|
|
2063
2055
|
previewVertex: this.draft.previewVertex,
|
|
@@ -2071,55 +2063,54 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2071
2063
|
this.handleHitboxes = [];
|
|
2072
2064
|
return;
|
|
2073
2065
|
}
|
|
2074
|
-
const t = this.getConverter(), e = [], i = this.shapes.find((
|
|
2075
|
-
i && e.push(i),
|
|
2066
|
+
const t = this.getConverter(), e = [], i = this.shapes.find((r) => r.id === this.selectedShapeId), s = this.hoveredShapeId && this.hoveredShapeId !== this.selectedShapeId ? this.shapes.find((r) => r.id === this.hoveredShapeId) ?? null : null;
|
|
2067
|
+
i && e.push(i), s && e.push(s), this.handleHitboxes = e.flatMap((r) => this.getShapeHandles(r, t));
|
|
2076
2068
|
}
|
|
2077
2069
|
getShapeHandles(t, e) {
|
|
2078
|
-
return t.type === "trendline" ?
|
|
2070
|
+
return t.type === "trendline" ? M.getHandles(t, e) : t.type === "rectangle" ? D.getHandles(t, e) : t.type === "path" ? R.getHandles(t, e) : t.type === "fibRetracement" ? L.getHandles(t, e) : H.getHandles(t, e);
|
|
2079
2071
|
}
|
|
2080
2072
|
findHandleAtPoint(t) {
|
|
2081
2073
|
for (let e = this.handleHitboxes.length - 1; e >= 0; e -= 1) {
|
|
2082
2074
|
const i = this.handleHitboxes[e];
|
|
2083
|
-
if (
|
|
2075
|
+
if (j(t, i)) return i;
|
|
2084
2076
|
}
|
|
2085
2077
|
return null;
|
|
2086
2078
|
}
|
|
2087
2079
|
findHandleAtPointForShape(t, e) {
|
|
2088
|
-
const i = this.getConverter(),
|
|
2089
|
-
for (const
|
|
2080
|
+
const i = this.getConverter(), s = this.getShapeHandles(t, i);
|
|
2081
|
+
for (const r of s) if (j(e, r)) return r;
|
|
2090
2082
|
return null;
|
|
2091
2083
|
}
|
|
2092
2084
|
findShapeAtPoint(t) {
|
|
2093
2085
|
const e = this.getConverter();
|
|
2094
2086
|
for (let i = this.shapes.length - 1; i >= 0; i -= 1) {
|
|
2095
|
-
const
|
|
2096
|
-
if (this.isShapeHit(
|
|
2087
|
+
const s = this.shapes[i];
|
|
2088
|
+
if (this.isShapeHit(s, t, e)) return s;
|
|
2097
2089
|
}
|
|
2098
2090
|
return null;
|
|
2099
2091
|
}
|
|
2100
2092
|
isShapeHit(t, e, i) {
|
|
2101
|
-
return t.type === "trendline" ?
|
|
2093
|
+
return t.type === "trendline" ? M.hitTest({
|
|
2102
2094
|
point: e,
|
|
2103
2095
|
shape: t,
|
|
2104
2096
|
converter: i
|
|
2105
|
-
}) : t.type === "rectangle" ?
|
|
2097
|
+
}) : t.type === "rectangle" ? D.hitTest({
|
|
2106
2098
|
point: e,
|
|
2107
2099
|
shape: t,
|
|
2108
2100
|
converter: i
|
|
2109
|
-
}) : t.type === "path" ?
|
|
2101
|
+
}) : t.type === "path" ? R.hitTest({
|
|
2110
2102
|
point: e,
|
|
2111
2103
|
shape: t,
|
|
2112
2104
|
converter: i
|
|
2113
|
-
}) : t.type === "fibRetracement" ?
|
|
2105
|
+
}) : t.type === "fibRetracement" ? L.hitTest({
|
|
2114
2106
|
point: e,
|
|
2115
2107
|
shape: t,
|
|
2116
2108
|
converter: i,
|
|
2117
2109
|
config: this.getFibRetracementConfig(t)
|
|
2118
|
-
}) :
|
|
2110
|
+
}) : H.hitTest({
|
|
2119
2111
|
point: e,
|
|
2120
2112
|
shape: t,
|
|
2121
|
-
converter: i
|
|
2122
|
-
config: this.getPositionConfig(t)
|
|
2113
|
+
converter: i
|
|
2123
2114
|
});
|
|
2124
2115
|
}
|
|
2125
2116
|
setSelectedShapeId(t) {
|
|
@@ -2204,8 +2195,8 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2204
2195
|
getNearestCandleTimeForX: (e) => {
|
|
2205
2196
|
const i = this.getTimeForX(e);
|
|
2206
2197
|
if (this.candles.length > 0 && i > this.candles[this.candles.length - 1].time) return i;
|
|
2207
|
-
const
|
|
2208
|
-
return
|
|
2198
|
+
const s = Z(this.candles, i);
|
|
2199
|
+
return s >= 0 ? this.candles[s].time : i;
|
|
2209
2200
|
},
|
|
2210
2201
|
getCandleWidth: () => t ? this.getCandleStepWidth(t) : 12
|
|
2211
2202
|
};
|
|
@@ -2213,19 +2204,19 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2213
2204
|
getXForTime(t) {
|
|
2214
2205
|
if (!this.viewport || this.candles.length === 0) return 0;
|
|
2215
2206
|
if (t > this.candles[this.candles.length - 1].time) {
|
|
2216
|
-
const i =
|
|
2207
|
+
const i = q(this.candles);
|
|
2217
2208
|
return (t - this.candles[0].time) / i * this.viewport.candleSpacing + this.viewport.offsetX + this.viewport.candleWidth / 2;
|
|
2218
2209
|
}
|
|
2219
|
-
const e =
|
|
2210
|
+
const e = Z(this.candles, t);
|
|
2220
2211
|
return e < 0 ? 0 : e * this.viewport.candleSpacing + this.viewport.offsetX + this.viewport.candleWidth / 2;
|
|
2221
2212
|
}
|
|
2222
2213
|
getTimeForX(t) {
|
|
2223
2214
|
if (!this.viewport) return Date.now();
|
|
2224
2215
|
const e = Math.round((t - this.viewport.offsetX - this.viewport.candleWidth / 2) / this.viewport.candleSpacing);
|
|
2225
|
-
return e >= 0 && e < this.candles.length ? this.candles[e].time : this.candles.length === 0 ? Date.now() :
|
|
2216
|
+
return e >= 0 && e < this.candles.length ? this.candles[e].time : this.candles.length === 0 ? Date.now() : Zt(this.candles, this.candles[0].time, e);
|
|
2226
2217
|
}
|
|
2227
2218
|
getYForPrice(t) {
|
|
2228
|
-
return this.viewport ?
|
|
2219
|
+
return this.viewport ? O({
|
|
2229
2220
|
price: t,
|
|
2230
2221
|
minPrice: this.viewport.minPrice,
|
|
2231
2222
|
priceRange: this.viewport.priceRange,
|
|
@@ -2233,7 +2224,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2233
2224
|
}) : this.canvas.height / 2;
|
|
2234
2225
|
}
|
|
2235
2226
|
getPriceForY(t) {
|
|
2236
|
-
return this.viewport ?
|
|
2227
|
+
return this.viewport ? mt({
|
|
2237
2228
|
y: t,
|
|
2238
2229
|
minPrice: this.viewport.minPrice,
|
|
2239
2230
|
priceRange: this.viewport.priceRange,
|
|
@@ -2246,33 +2237,33 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2246
2237
|
mergeConfig(t) {
|
|
2247
2238
|
return {
|
|
2248
2239
|
trendline: {
|
|
2249
|
-
...
|
|
2240
|
+
...M.defaultConfig,
|
|
2250
2241
|
...t?.trendline ?? {}
|
|
2251
2242
|
},
|
|
2252
2243
|
rectangle: {
|
|
2253
|
-
...
|
|
2244
|
+
...D.defaultConfig,
|
|
2254
2245
|
...t?.rectangle ?? {}
|
|
2255
2246
|
},
|
|
2256
2247
|
path: {
|
|
2257
|
-
...
|
|
2248
|
+
...R.defaultConfig,
|
|
2258
2249
|
...t?.path ?? {}
|
|
2259
2250
|
},
|
|
2260
2251
|
fibRetracement: {
|
|
2261
|
-
...
|
|
2252
|
+
...L.defaultConfig,
|
|
2262
2253
|
...t?.fibRetracement ?? {},
|
|
2263
|
-
levels: t?.fibRetracement?.levels ??
|
|
2254
|
+
levels: t?.fibRetracement?.levels ?? L.defaultConfig.levels
|
|
2264
2255
|
},
|
|
2265
2256
|
shortPosition: {
|
|
2266
|
-
...
|
|
2257
|
+
...H.defaultShortConfig,
|
|
2267
2258
|
...t?.shortPosition ?? {}
|
|
2268
2259
|
},
|
|
2269
2260
|
longPosition: {
|
|
2270
|
-
...
|
|
2261
|
+
...H.defaultLongConfig,
|
|
2271
2262
|
...t?.longPosition ?? {}
|
|
2272
2263
|
}
|
|
2273
2264
|
};
|
|
2274
2265
|
}
|
|
2275
|
-
},
|
|
2266
|
+
}, te = class {
|
|
2276
2267
|
#t;
|
|
2277
2268
|
#e;
|
|
2278
2269
|
isDragging;
|
|
@@ -2321,51 +2312,51 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2321
2312
|
for (const t of this.trades) this.drawTrade({ trade: t });
|
|
2322
2313
|
this.drawTemporaryProtectionDrag();
|
|
2323
2314
|
}
|
|
2324
|
-
createHitBox = ({ price: t, trade: e, type: i, x:
|
|
2325
|
-
const { showCloseSection: l, widthClose: d } = this.getHandleStyleConfig(i).handle, u = l ? d : 0, g = n - u, m =
|
|
2315
|
+
createHitBox = ({ price: t, trade: e, type: i, x: s, y: r, width: n, height: o, viewport: a }) => {
|
|
2316
|
+
const { showCloseSection: l, widthClose: d } = this.getHandleStyleConfig(i).handle, u = l ? d : 0, g = n - u, m = s + n - u;
|
|
2326
2317
|
return {
|
|
2327
2318
|
kind: "existingHandle",
|
|
2328
2319
|
price: p(t),
|
|
2329
2320
|
trade: e,
|
|
2330
2321
|
type: i,
|
|
2331
|
-
x:
|
|
2332
|
-
y:
|
|
2322
|
+
x: s,
|
|
2323
|
+
y: r,
|
|
2333
2324
|
width: n,
|
|
2334
2325
|
height: o,
|
|
2335
2326
|
viewport: a,
|
|
2336
2327
|
labelArea: {
|
|
2337
|
-
x:
|
|
2338
|
-
y:
|
|
2328
|
+
x: s,
|
|
2329
|
+
y: r,
|
|
2339
2330
|
width: g,
|
|
2340
2331
|
height: o
|
|
2341
2332
|
},
|
|
2342
2333
|
closeButtonArea: {
|
|
2343
2334
|
x: m,
|
|
2344
|
-
y:
|
|
2335
|
+
y: r,
|
|
2345
2336
|
width: u,
|
|
2346
2337
|
height: o
|
|
2347
2338
|
}
|
|
2348
2339
|
};
|
|
2349
2340
|
};
|
|
2350
|
-
createMissingProtectionHitBox = ({ price: t, trade: e, type: i, x:
|
|
2341
|
+
createMissingProtectionHitBox = ({ price: t, trade: e, type: i, x: s, y: r, width: n, height: o, viewport: a }) => ({
|
|
2351
2342
|
kind: "missingProtectionHandle",
|
|
2352
2343
|
price: p(t),
|
|
2353
2344
|
trade: e,
|
|
2354
2345
|
type: i,
|
|
2355
|
-
x:
|
|
2356
|
-
y:
|
|
2346
|
+
x: s,
|
|
2347
|
+
y: r,
|
|
2357
2348
|
width: n,
|
|
2358
2349
|
height: o,
|
|
2359
2350
|
viewport: a,
|
|
2360
2351
|
labelArea: {
|
|
2361
|
-
x:
|
|
2362
|
-
y:
|
|
2352
|
+
x: s,
|
|
2353
|
+
y: r,
|
|
2363
2354
|
width: n,
|
|
2364
2355
|
height: o
|
|
2365
2356
|
},
|
|
2366
2357
|
closeButtonArea: {
|
|
2367
|
-
x:
|
|
2368
|
-
y:
|
|
2358
|
+
x: s + n,
|
|
2359
|
+
y: r,
|
|
2369
2360
|
width: 0,
|
|
2370
2361
|
height: o
|
|
2371
2362
|
}
|
|
@@ -2393,21 +2384,21 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2393
2384
|
type: "takeProfit",
|
|
2394
2385
|
trade: t
|
|
2395
2386
|
});
|
|
2396
|
-
for (const
|
|
2397
|
-
this.addMissingProtectionHitbox(
|
|
2398
|
-
x:
|
|
2399
|
-
y:
|
|
2400
|
-
width:
|
|
2401
|
-
config:
|
|
2402
|
-
}), this.drawMissingProtectionHandleLabel(
|
|
2387
|
+
for (const s of i)
|
|
2388
|
+
this.addMissingProtectionHitbox(s), this.drawMissingProtectionHandleRect({
|
|
2389
|
+
x: s.handleX,
|
|
2390
|
+
y: s.handleY,
|
|
2391
|
+
width: s.handleWidth,
|
|
2392
|
+
config: s.config
|
|
2393
|
+
}), this.drawMissingProtectionHandleLabel(s);
|
|
2403
2394
|
}
|
|
2404
2395
|
drawTradeHandle({ price: t, type: e, trade: i }) {
|
|
2405
|
-
const
|
|
2396
|
+
const s = this.getTradeHandleRenderState({
|
|
2406
2397
|
price: t,
|
|
2407
2398
|
type: e,
|
|
2408
2399
|
trade: i
|
|
2409
2400
|
});
|
|
2410
|
-
return
|
|
2401
|
+
return s ? (this.drawTradeHandleFromRenderState({ renderState: s }), s) : null;
|
|
2411
2402
|
}
|
|
2412
2403
|
drawTradeHandleFromRenderState({ renderState: t, blockedRanges: e = [] }) {
|
|
2413
2404
|
this.addHandleHitbox(t), this.drawHandleHorizontalLines({
|
|
@@ -2429,26 +2420,26 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2429
2420
|
y: t.y
|
|
2430
2421
|
});
|
|
2431
2422
|
}
|
|
2432
|
-
drawHandleLine({ x1: t, x2: e, y: i, config:
|
|
2423
|
+
drawHandleLine({ x1: t, x2: e, y: i, config: s }) {
|
|
2433
2424
|
if (e <= t) return;
|
|
2434
|
-
const
|
|
2435
|
-
|
|
2425
|
+
const r = this.#e;
|
|
2426
|
+
r.save(), r.globalAlpha = s.opacity, r.strokeStyle = s.color, r.lineWidth = s.width, r.setLineDash(this.getHandleLineDash(s)), r.beginPath(), r.moveTo(t, i), r.lineTo(e, i), r.stroke(), r.restore();
|
|
2436
2427
|
}
|
|
2437
|
-
drawConnectorLine({ x1: t, y1: e, x2: i, y2:
|
|
2428
|
+
drawConnectorLine({ x1: t, y1: e, x2: i, y2: s, config: r }) {
|
|
2438
2429
|
const n = this.#e;
|
|
2439
|
-
n.save(), n.globalAlpha =
|
|
2430
|
+
n.save(), n.globalAlpha = r.opacity, n.strokeStyle = r.color, n.lineWidth = r.width, n.setLineDash(this.getHandleLineDash(r)), n.beginPath(), n.moveTo(t, e), n.lineTo(i, s), n.stroke(), n.restore();
|
|
2440
2431
|
}
|
|
2441
|
-
drawHandleRect({ x: t, y: e, width: i, config:
|
|
2442
|
-
const
|
|
2432
|
+
drawHandleRect({ x: t, y: e, width: i, config: s }) {
|
|
2433
|
+
const r = this.#e;
|
|
2443
2434
|
this.clearRectArea({
|
|
2444
2435
|
x: t,
|
|
2445
2436
|
y: e,
|
|
2446
2437
|
width: i,
|
|
2447
|
-
height:
|
|
2448
|
-
padding: Math.max(1,
|
|
2449
|
-
}),
|
|
2438
|
+
height: s.height,
|
|
2439
|
+
padding: Math.max(1, s.borderWidth)
|
|
2440
|
+
}), r.save(), r.globalAlpha = s.backgroundOpacity, r.fillStyle = s.backgroundColor, r.fillRect(t, e, i, s.height), r.globalAlpha = s.borderOpacity, r.strokeStyle = s.borderColor, r.lineWidth = s.borderWidth, r.strokeRect(t, e, i, s.height), r.restore();
|
|
2450
2441
|
}
|
|
2451
|
-
drawHandleSections({ handleType: t, handleX: e, handleY: i, handleWidth:
|
|
2442
|
+
drawHandleSections({ handleType: t, handleX: e, handleY: i, handleWidth: s, handleHeight: r, handleConfig: n, trade: o, y: a }) {
|
|
2452
2443
|
const l = this.#e, d = c.tradeHandles, u = this.getHandleSections({
|
|
2453
2444
|
handleType: t,
|
|
2454
2445
|
handleConfig: n,
|
|
@@ -2461,10 +2452,10 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2461
2452
|
section: m,
|
|
2462
2453
|
currentX: g,
|
|
2463
2454
|
y: a
|
|
2464
|
-
}), g += m.width, g < e +
|
|
2455
|
+
}), g += m.width, g < e + s && this.drawHandleSectionDivider({
|
|
2465
2456
|
x: g,
|
|
2466
2457
|
y1: i + 4,
|
|
2467
|
-
y2: i +
|
|
2458
|
+
y2: i + r - 4,
|
|
2468
2459
|
config: n
|
|
2469
2460
|
}));
|
|
2470
2461
|
l.restore();
|
|
@@ -2473,8 +2464,8 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2473
2464
|
if (t === "startPrice") return this.formatPnlLabel(e.pnl);
|
|
2474
2465
|
const i = t === "stopLoss" ? e.sl : e.tp;
|
|
2475
2466
|
if (!i) return "N/A";
|
|
2476
|
-
const
|
|
2477
|
-
return this.formatPnlLabel(
|
|
2467
|
+
const s = ut(e.type, e.openPrice, i, e.volume, e.symbol);
|
|
2468
|
+
return this.formatPnlLabel(s);
|
|
2478
2469
|
}
|
|
2479
2470
|
getHandleWidth(t) {
|
|
2480
2471
|
let e = 0;
|
|
@@ -2503,8 +2494,8 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2503
2494
|
}
|
|
2504
2495
|
}
|
|
2505
2496
|
getProtectionDirection({ trade: t, type: e }) {
|
|
2506
|
-
const i = this.isBuyTrade(t),
|
|
2507
|
-
return i ?
|
|
2497
|
+
const i = this.isBuyTrade(t), s = e === "takeProfit" ? 1 : -1;
|
|
2498
|
+
return i ? s : -s;
|
|
2508
2499
|
}
|
|
2509
2500
|
constrainProtectionPrice({ price: t, trade: e, type: i }) {
|
|
2510
2501
|
return this.getProtectionDirection({
|
|
@@ -2529,18 +2520,18 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2529
2520
|
if (!this.viewport) return null;
|
|
2530
2521
|
const e = this.getTimeX(t.openTime), i = this.getTimeX(t.closeTime);
|
|
2531
2522
|
if (e === null || i === null) return null;
|
|
2532
|
-
const
|
|
2523
|
+
const s = this.getPriceY(t.openPrice, this.viewport), r = this.getPriceY(t.closePrice, this.viewport), n = c.closedTradeIndicators.arrow, o = n.width, a = n.height;
|
|
2533
2524
|
return {
|
|
2534
2525
|
trade: t,
|
|
2535
2526
|
start: {
|
|
2536
2527
|
x: e,
|
|
2537
|
-
y:
|
|
2528
|
+
y: s,
|
|
2538
2529
|
time: t.openTime,
|
|
2539
2530
|
price: t.openPrice
|
|
2540
2531
|
},
|
|
2541
2532
|
close: {
|
|
2542
2533
|
x: i,
|
|
2543
|
-
y:
|
|
2534
|
+
y: r,
|
|
2544
2535
|
time: t.closeTime,
|
|
2545
2536
|
price: t.closePrice
|
|
2546
2537
|
},
|
|
@@ -2558,7 +2549,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2558
2549
|
config: i
|
|
2559
2550
|
});
|
|
2560
2551
|
}
|
|
2561
|
-
drawClosedTradeArrows({ trade: t, start: e, close: i, arrowWidth:
|
|
2552
|
+
drawClosedTradeArrows({ trade: t, start: e, close: i, arrowWidth: s, arrowHeight: r }) {
|
|
2562
2553
|
const n = c.closedTradeIndicators.arrow;
|
|
2563
2554
|
if (!n.visible) return;
|
|
2564
2555
|
const o = t.type === "buy" ? "sell" : "buy";
|
|
@@ -2566,39 +2557,39 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2566
2557
|
x: e.x,
|
|
2567
2558
|
y: e.y,
|
|
2568
2559
|
type: t.type,
|
|
2569
|
-
width:
|
|
2570
|
-
height:
|
|
2560
|
+
width: s,
|
|
2561
|
+
height: r,
|
|
2571
2562
|
config: n
|
|
2572
2563
|
}), this.drawClosedTradeArrow({
|
|
2573
2564
|
x: i.x,
|
|
2574
2565
|
y: i.y,
|
|
2575
2566
|
type: o,
|
|
2576
|
-
width:
|
|
2577
|
-
height:
|
|
2567
|
+
width: s,
|
|
2568
|
+
height: r,
|
|
2578
2569
|
config: n
|
|
2579
2570
|
});
|
|
2580
2571
|
}
|
|
2581
|
-
drawClosedTradeArrow({ x: t, y: e, type: i, width:
|
|
2582
|
-
if (
|
|
2583
|
-
const o = this.#e, a = i === "buy", l = a ? n.buyColor : n.sellColor, d = a ? n.buyBorderColor : n.sellBorderColor, u = a ? 1 : -1, g = t, m = e,
|
|
2584
|
-
o.beginPath(), o.moveTo(
|
|
2572
|
+
drawClosedTradeArrow({ x: t, y: e, type: i, width: s, height: r, config: n }) {
|
|
2573
|
+
if (s <= 0 || r <= 0) return;
|
|
2574
|
+
const o = this.#e, a = i === "buy", l = a ? n.buyColor : n.sellColor, d = a ? n.buyBorderColor : n.sellBorderColor, u = a ? 1 : -1, g = t, m = e, b = t, v = e + u * r, S = r / 2, T = S / Math.SQRT2, k = S / Math.SQRT2, Ht = g - T, kt = g + T, tt = m + u * k, et = Math.max(1, n.shaftWidthRatio), Mt = et + n.borderWidth * 2, it = () => {
|
|
2575
|
+
o.beginPath(), o.moveTo(b, v), o.lineTo(g, m), o.moveTo(g, m), o.lineTo(Ht, tt), o.moveTo(g, m), o.lineTo(kt, tt), o.stroke();
|
|
2585
2576
|
};
|
|
2586
|
-
o.save(), o.globalAlpha = n.opacity, o.lineCap = "round", o.lineJoin = "round", o.strokeStyle = d, o.lineWidth =
|
|
2577
|
+
o.save(), o.globalAlpha = n.opacity, o.lineCap = "round", o.lineJoin = "round", o.strokeStyle = d, o.lineWidth = Mt, it(), o.strokeStyle = l, o.lineWidth = et, it(), o.restore();
|
|
2587
2578
|
}
|
|
2588
2579
|
getTimeX(t) {
|
|
2589
2580
|
if (!this.viewport || this.candles.length === 0 || !Number.isFinite(t)) return null;
|
|
2590
|
-
const e = this.normalizeTimestamp(t), i = this.candles[0],
|
|
2591
|
-
if (!i || !
|
|
2581
|
+
const e = this.normalizeTimestamp(t), i = this.candles[0], s = this.candles[this.candles.length - 1];
|
|
2582
|
+
if (!i || !s) return null;
|
|
2592
2583
|
if (this.candles.length === 1) return this.getCandleCenterX(0);
|
|
2593
2584
|
if (e <= i.time) {
|
|
2594
2585
|
const d = this.getCandleTimeInterval(0), u = (i.time - e) / d;
|
|
2595
2586
|
return this.getCandleCenterX(0) - u * this.viewport.candleSpacing;
|
|
2596
2587
|
}
|
|
2597
|
-
if (e >=
|
|
2598
|
-
const d = this.candles.length - 1, u = this.getCandleTimeInterval(d), g = (e -
|
|
2588
|
+
if (e >= s.time) {
|
|
2589
|
+
const d = this.candles.length - 1, u = this.getCandleTimeInterval(d), g = (e - s.time) / u;
|
|
2599
2590
|
return this.getCandleCenterX(d) + g * this.viewport.candleSpacing;
|
|
2600
2591
|
}
|
|
2601
|
-
const
|
|
2592
|
+
const r = this.getFirstCandleIndexAtOrAfterTime(e), n = Math.max(0, r - 1), o = this.candles[n], a = this.candles[r];
|
|
2602
2593
|
if (!o || !a || a.time === o.time) return this.getCandleCenterX(n);
|
|
2603
2594
|
const l = (e - o.time) / (a.time - o.time);
|
|
2604
2595
|
return this.getCandleCenterX(n) + l * this.viewport.candleSpacing;
|
|
@@ -2609,8 +2600,8 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2609
2600
|
getFirstCandleIndexAtOrAfterTime(t) {
|
|
2610
2601
|
let e = 0, i = this.candles.length - 1;
|
|
2611
2602
|
for (; e < i; ) {
|
|
2612
|
-
const
|
|
2613
|
-
this.candles[
|
|
2603
|
+
const s = Math.floor((e + i) / 2);
|
|
2604
|
+
this.candles[s].time < t ? e = s + 1 : i = s;
|
|
2614
2605
|
}
|
|
2615
2606
|
return e;
|
|
2616
2607
|
}
|
|
@@ -2618,18 +2609,18 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2618
2609
|
return this.viewport ? t * this.viewport.candleSpacing + this.viewport.offsetX + this.viewport.candleWidth / 2 : 0;
|
|
2619
2610
|
}
|
|
2620
2611
|
getCandleTimeInterval(t) {
|
|
2621
|
-
const e = this.candles[t], i = this.candles[t - 1],
|
|
2622
|
-
return e &&
|
|
2612
|
+
const e = this.candles[t], i = this.candles[t - 1], s = this.candles[t + 1];
|
|
2613
|
+
return e && s && s.time > e.time ? s.time - e.time : e && i && e.time > i.time ? e.time - i.time : 60 * 1e3;
|
|
2623
2614
|
}
|
|
2624
2615
|
getTradeHandleRenderState({ price: t, type: e, trade: i }) {
|
|
2625
2616
|
if (!this.viewport) return null;
|
|
2626
|
-
const
|
|
2617
|
+
const s = this.viewport, r = this.getPriceY(t, s), n = this.getHandleStyleConfig(e), o = n.handle, a = n.handleLine, l = this.getHandleWidth(o), d = o.height;
|
|
2627
2618
|
return {
|
|
2628
2619
|
price: t,
|
|
2629
2620
|
type: e,
|
|
2630
2621
|
trade: i,
|
|
2631
|
-
viewport:
|
|
2632
|
-
y:
|
|
2622
|
+
viewport: s,
|
|
2623
|
+
y: r,
|
|
2633
2624
|
handleStyleConfig: n,
|
|
2634
2625
|
handleConfig: o,
|
|
2635
2626
|
lineConfig: a,
|
|
@@ -2637,13 +2628,13 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2637
2628
|
handleWidth: l,
|
|
2638
2629
|
config: o
|
|
2639
2630
|
}),
|
|
2640
|
-
handleY:
|
|
2631
|
+
handleY: r - d / 2,
|
|
2641
2632
|
handleWidth: l,
|
|
2642
2633
|
handleHeight: d
|
|
2643
2634
|
};
|
|
2644
2635
|
}
|
|
2645
2636
|
getPriceY(t, e) {
|
|
2646
|
-
return
|
|
2637
|
+
return O({
|
|
2647
2638
|
price: t,
|
|
2648
2639
|
minPrice: e.minPrice,
|
|
2649
2640
|
priceRange: e.priceRange,
|
|
@@ -2674,20 +2665,20 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2674
2665
|
viewport: t.viewport
|
|
2675
2666
|
}));
|
|
2676
2667
|
}
|
|
2677
|
-
drawHandleHorizontalLines({ handleX: t, handleWidth: e, y: i, lineConfig:
|
|
2668
|
+
drawHandleHorizontalLines({ handleX: t, handleWidth: e, y: i, lineConfig: s, blockedRanges: r = [] }) {
|
|
2678
2669
|
this.drawHorizontalLineAroundBlockedRanges({
|
|
2679
2670
|
y: i,
|
|
2680
|
-
config:
|
|
2671
|
+
config: s,
|
|
2681
2672
|
blockedRanges: [{
|
|
2682
2673
|
x1: t,
|
|
2683
2674
|
x2: t + e
|
|
2684
|
-
}, ...
|
|
2675
|
+
}, ...r]
|
|
2685
2676
|
});
|
|
2686
2677
|
}
|
|
2687
|
-
drawTemporaryProtectionHorizontalLines({ handleX: t, handleWidth: e, y: i, lineConfig:
|
|
2678
|
+
drawTemporaryProtectionHorizontalLines({ handleX: t, handleWidth: e, y: i, lineConfig: s }) {
|
|
2688
2679
|
this.drawHorizontalLineAroundBlockedRanges({
|
|
2689
2680
|
y: i,
|
|
2690
|
-
config:
|
|
2681
|
+
config: s,
|
|
2691
2682
|
blockedRanges: [{
|
|
2692
2683
|
x1: t,
|
|
2693
2684
|
x2: t + e
|
|
@@ -2695,34 +2686,34 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2695
2686
|
});
|
|
2696
2687
|
}
|
|
2697
2688
|
drawHorizontalLineAroundBlockedRanges({ y: t, config: e, blockedRanges: i }) {
|
|
2698
|
-
const
|
|
2699
|
-
let
|
|
2700
|
-
for (const n of
|
|
2701
|
-
n.x1 >
|
|
2702
|
-
x1:
|
|
2689
|
+
const s = this.getMergedBlockedRanges(i);
|
|
2690
|
+
let r = 0;
|
|
2691
|
+
for (const n of s)
|
|
2692
|
+
n.x1 > r && this.drawHandleLine({
|
|
2693
|
+
x1: r,
|
|
2703
2694
|
x2: n.x1,
|
|
2704
2695
|
y: t,
|
|
2705
2696
|
config: e
|
|
2706
|
-
}),
|
|
2707
|
-
|
|
2708
|
-
x1:
|
|
2697
|
+
}), r = Math.max(r, n.x2);
|
|
2698
|
+
r < this.#t.width && this.drawHandleLine({
|
|
2699
|
+
x1: r,
|
|
2709
2700
|
x2: this.#t.width,
|
|
2710
2701
|
y: t,
|
|
2711
2702
|
config: e
|
|
2712
2703
|
});
|
|
2713
2704
|
}
|
|
2714
2705
|
getMergedBlockedRanges(t) {
|
|
2715
|
-
const e = t.map((
|
|
2716
|
-
x1: Math.max(0, Math.min(
|
|
2717
|
-
x2: Math.max(0, Math.min(
|
|
2718
|
-
})).filter((
|
|
2719
|
-
for (const
|
|
2720
|
-
const
|
|
2721
|
-
if (!
|
|
2722
|
-
i.push({ ...
|
|
2706
|
+
const e = t.map((s) => ({
|
|
2707
|
+
x1: Math.max(0, Math.min(s.x1, this.#t.width)),
|
|
2708
|
+
x2: Math.max(0, Math.min(s.x2, this.#t.width))
|
|
2709
|
+
})).filter((s) => s.x2 > s.x1).sort((s, r) => s.x1 - r.x1), i = [];
|
|
2710
|
+
for (const s of e) {
|
|
2711
|
+
const r = i.at(-1);
|
|
2712
|
+
if (!r || s.x1 > r.x2) {
|
|
2713
|
+
i.push({ ...s });
|
|
2723
2714
|
continue;
|
|
2724
2715
|
}
|
|
2725
|
-
|
|
2716
|
+
r.x2 = Math.max(r.x2, s.x2);
|
|
2726
2717
|
}
|
|
2727
2718
|
return i;
|
|
2728
2719
|
}
|
|
@@ -2737,7 +2728,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2737
2728
|
}
|
|
2738
2729
|
}
|
|
2739
2730
|
getHandleSections({ handleType: t, handleConfig: e, trade: i }) {
|
|
2740
|
-
const
|
|
2731
|
+
const s = this.getHandlePnLLabel({
|
|
2741
2732
|
handleType: t,
|
|
2742
2733
|
trade: i
|
|
2743
2734
|
});
|
|
@@ -2748,7 +2739,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2748
2739
|
visible: e.showVolumeSection
|
|
2749
2740
|
},
|
|
2750
2741
|
{
|
|
2751
|
-
label:
|
|
2742
|
+
label: s,
|
|
2752
2743
|
width: e.widthPNL,
|
|
2753
2744
|
visible: e.showPnlSection,
|
|
2754
2745
|
color: this.getHandlePnlTextColor({
|
|
@@ -2765,18 +2756,18 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2765
2756
|
];
|
|
2766
2757
|
}
|
|
2767
2758
|
drawHandleSectionLabel({ section: t, currentX: e, y: i }) {
|
|
2768
|
-
const
|
|
2769
|
-
|
|
2759
|
+
const s = this.#e, r = c.tradeHandles, n = e + t.width / 2;
|
|
2760
|
+
s.fillStyle = t.color ?? r.textColor, s.fillText(t.label, n - s.measureText(t.label).width / 2, i);
|
|
2770
2761
|
}
|
|
2771
|
-
drawHandleSectionDivider({ x: t, y1: e, y2: i, config:
|
|
2772
|
-
const
|
|
2773
|
-
|
|
2762
|
+
drawHandleSectionDivider({ x: t, y1: e, y2: i, config: s }) {
|
|
2763
|
+
const r = this.#e;
|
|
2764
|
+
r.strokeStyle = s.sectionDividerColor, r.lineWidth = 1, r.beginPath(), r.moveTo(t, e), r.lineTo(t, i), r.stroke();
|
|
2774
2765
|
}
|
|
2775
2766
|
getMissingProtectionRenderStates({ trade: t, startPriceRenderState: e }) {
|
|
2776
2767
|
if (!c.tradeHandles.missingProtectionHandles.visible) return [];
|
|
2777
2768
|
const i = this.getMissingProtectionHandleTypes(t);
|
|
2778
|
-
return i.map((
|
|
2779
|
-
type:
|
|
2769
|
+
return i.map((s) => this.getMissingProtectionHandleRenderState({
|
|
2770
|
+
type: s,
|
|
2780
2771
|
trade: t,
|
|
2781
2772
|
startPriceRenderState: e,
|
|
2782
2773
|
visibleTypes: i
|
|
@@ -2786,12 +2777,12 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2786
2777
|
const e = [];
|
|
2787
2778
|
return t.sl || e.push("stopLoss"), t.tp || e.push("takeProfit"), e;
|
|
2788
2779
|
}
|
|
2789
|
-
getMissingProtectionHandleRenderState({ type: t, trade: e, startPriceRenderState: i, visibleTypes:
|
|
2790
|
-
const
|
|
2780
|
+
getMissingProtectionHandleRenderState({ type: t, trade: e, startPriceRenderState: i, visibleTypes: s }) {
|
|
2781
|
+
const r = this.getMissingProtectionHandleConfig(t), n = r.width, o = r.height, a = this.getMissingProtectionHandleX({
|
|
2791
2782
|
type: t,
|
|
2792
|
-
config:
|
|
2783
|
+
config: r,
|
|
2793
2784
|
startPriceRenderState: i,
|
|
2794
|
-
visibleTypes:
|
|
2785
|
+
visibleTypes: s
|
|
2795
2786
|
}), l = i.y - o / 2;
|
|
2796
2787
|
return {
|
|
2797
2788
|
price: e.openPrice,
|
|
@@ -2799,15 +2790,15 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2799
2790
|
trade: e,
|
|
2800
2791
|
viewport: i.viewport,
|
|
2801
2792
|
y: i.y,
|
|
2802
|
-
config:
|
|
2793
|
+
config: r,
|
|
2803
2794
|
handleX: a,
|
|
2804
2795
|
handleY: l,
|
|
2805
2796
|
handleWidth: n,
|
|
2806
2797
|
handleHeight: o
|
|
2807
2798
|
};
|
|
2808
2799
|
}
|
|
2809
|
-
getMissingProtectionHandleX({ type: t, config: e, startPriceRenderState: i, visibleTypes:
|
|
2810
|
-
const
|
|
2800
|
+
getMissingProtectionHandleX({ type: t, config: e, startPriceRenderState: i, visibleTypes: s }) {
|
|
2801
|
+
const r = s.indexOf(t), n = e.gapFromStartPriceHandle + r * (e.width + e.gapBetweenHandles);
|
|
2811
2802
|
return e.placement === "left" ? i.handleX - n - e.width : i.handleX + i.handleWidth + n;
|
|
2812
2803
|
}
|
|
2813
2804
|
getLineBlockedRangesFromMissingProtectionHandles(t) {
|
|
@@ -2820,19 +2811,19 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2820
2811
|
const e = c.tradeHandles.missingProtectionHandles;
|
|
2821
2812
|
return t === "stopLoss" ? e.slHandle : e.tpHandle;
|
|
2822
2813
|
}
|
|
2823
|
-
drawMissingProtectionHandleRect({ x: t, y: e, width: i, config:
|
|
2824
|
-
const
|
|
2814
|
+
drawMissingProtectionHandleRect({ x: t, y: e, width: i, config: s }) {
|
|
2815
|
+
const r = this.#e;
|
|
2825
2816
|
this.clearRectArea({
|
|
2826
2817
|
x: t,
|
|
2827
2818
|
y: e,
|
|
2828
2819
|
width: i,
|
|
2829
|
-
height:
|
|
2830
|
-
padding: Math.max(1,
|
|
2831
|
-
}),
|
|
2820
|
+
height: s.height,
|
|
2821
|
+
padding: Math.max(1, s.borderWidth)
|
|
2822
|
+
}), r.save(), r.globalAlpha = s.backgroundOpacity, r.fillStyle = s.backgroundColor, r.fillRect(t, e, i, s.height), r.globalAlpha = s.borderOpacity, r.strokeStyle = s.borderColor, r.lineWidth = s.borderWidth, r.strokeRect(t, e, i, s.height), r.restore();
|
|
2832
2823
|
}
|
|
2833
|
-
drawMissingProtectionHandleLabel({ type: t, handleX: e, y: i, handleWidth:
|
|
2834
|
-
const n = this.#e, o = t === "stopLoss" ? "SL" : "TP", a = e +
|
|
2835
|
-
n.save(), n.font =
|
|
2824
|
+
drawMissingProtectionHandleLabel({ type: t, handleX: e, y: i, handleWidth: s, config: r }) {
|
|
2825
|
+
const n = this.#e, o = t === "stopLoss" ? "SL" : "TP", a = e + s / 2;
|
|
2826
|
+
n.save(), n.font = r.font, n.textBaseline = "middle", n.globalAlpha = r.textOpacity, n.fillStyle = r.textColor, n.fillText(o, a - n.measureText(o).width / 2, i), n.restore();
|
|
2836
2827
|
}
|
|
2837
2828
|
drawTemporaryProtectionDrag() {
|
|
2838
2829
|
const t = this.getTemporaryProtectionRenderState();
|
|
@@ -2845,20 +2836,20 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2845
2836
|
}
|
|
2846
2837
|
getTemporaryProtectionRenderState() {
|
|
2847
2838
|
if (!this.temporaryProtectionDrag) return null;
|
|
2848
|
-
const { trade: t, type: e, viewport: i } = this.temporaryProtectionDrag,
|
|
2839
|
+
const { trade: t, type: e, viewport: i } = this.temporaryProtectionDrag, s = p(this.temporaryProtectionDrag.price), r = this.getPriceY(s, i), n = this.getTemporaryProtectionHandleConfig(e), o = this.getTemporaryProtectionLineConfig(e), a = n.widthPNL, l = n.height;
|
|
2849
2840
|
return {
|
|
2850
|
-
price:
|
|
2841
|
+
price: s,
|
|
2851
2842
|
type: e,
|
|
2852
2843
|
trade: t,
|
|
2853
2844
|
viewport: i,
|
|
2854
|
-
y:
|
|
2845
|
+
y: r,
|
|
2855
2846
|
handleConfig: n,
|
|
2856
2847
|
lineConfig: o,
|
|
2857
2848
|
handleX: this.getTemporaryProtectionHandleX({
|
|
2858
2849
|
handleWidth: a,
|
|
2859
2850
|
config: n
|
|
2860
2851
|
}),
|
|
2861
|
-
handleY:
|
|
2852
|
+
handleY: r - l / 2,
|
|
2862
2853
|
handleWidth: a,
|
|
2863
2854
|
handleHeight: l
|
|
2864
2855
|
};
|
|
@@ -2871,22 +2862,22 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2871
2862
|
const e = c.tradeHandles.missingProtectionHandles;
|
|
2872
2863
|
return t === "stopLoss" ? e.temporarySlLine : e.temporaryTpLine;
|
|
2873
2864
|
}
|
|
2874
|
-
drawTemporaryProtectionHandleRect({ x: t, y: e, width: i, config:
|
|
2875
|
-
const
|
|
2865
|
+
drawTemporaryProtectionHandleRect({ x: t, y: e, width: i, config: s }) {
|
|
2866
|
+
const r = this.#e;
|
|
2876
2867
|
this.clearRectArea({
|
|
2877
2868
|
x: t,
|
|
2878
2869
|
y: e,
|
|
2879
2870
|
width: i,
|
|
2880
|
-
height:
|
|
2881
|
-
padding: Math.max(1,
|
|
2882
|
-
}),
|
|
2871
|
+
height: s.height,
|
|
2872
|
+
padding: Math.max(1, s.borderWidth)
|
|
2873
|
+
}), r.save(), r.globalAlpha = s.backgroundOpacity, r.fillStyle = s.backgroundColor, r.fillRect(t, e, i, s.height), r.globalAlpha = s.borderOpacity, r.strokeStyle = s.borderColor, r.lineWidth = s.borderWidth, r.strokeRect(t, e, i, s.height), r.restore();
|
|
2883
2874
|
}
|
|
2884
|
-
drawTemporaryProtectionPnLLabel({ trade: t, type: e, price: i, handleX:
|
|
2885
|
-
const a = this.#e, l =
|
|
2886
|
-
a.save(), a.font = o.font, a.textBaseline = "middle", a.globalAlpha = o.textOpacity, a.fillStyle = this.getProtectionPnlTextColor(e), a.fillText(d, u - a.measureText(d).width / 2,
|
|
2875
|
+
drawTemporaryProtectionPnLLabel({ trade: t, type: e, price: i, handleX: s, y: r, handleWidth: n, handleConfig: o }) {
|
|
2876
|
+
const a = this.#e, l = ut(t.type, t.openPrice, i, t.volume, t.symbol), d = this.formatPnlLabel(l), u = s + n / 2;
|
|
2877
|
+
a.save(), a.font = o.font, a.textBaseline = "middle", a.globalAlpha = o.textOpacity, a.fillStyle = this.getProtectionPnlTextColor(e), a.fillText(d, u - a.measureText(d).width / 2, r), a.restore();
|
|
2887
2878
|
}
|
|
2888
|
-
clearRectArea({ x: t, y: e, width: i, height:
|
|
2889
|
-
this.#e.clearRect(t -
|
|
2879
|
+
clearRectArea({ x: t, y: e, width: i, height: s, padding: r = 0 }) {
|
|
2880
|
+
this.#e.clearRect(t - r, e - r, i + r * 2, s + r * 2);
|
|
2890
2881
|
}
|
|
2891
2882
|
getPositionedHandleX({ handleWidth: t, position: e }) {
|
|
2892
2883
|
const i = this.#t.width;
|
|
@@ -2911,30 +2902,30 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2911
2902
|
formatPnlLabel(t) {
|
|
2912
2903
|
return `${t >= 0 ? "+" : ""}${t.toFixed(2)}`;
|
|
2913
2904
|
}
|
|
2914
|
-
},
|
|
2905
|
+
}, ee = [
|
|
2915
2906
|
"pointerdown",
|
|
2916
2907
|
"pointermove",
|
|
2917
2908
|
"pointerup"
|
|
2918
|
-
],
|
|
2909
|
+
], ie = class {
|
|
2919
2910
|
#t;
|
|
2920
2911
|
#e;
|
|
2921
2912
|
#r;
|
|
2922
|
-
#s;
|
|
2923
|
-
#c;
|
|
2924
2913
|
#i;
|
|
2925
|
-
#l;
|
|
2926
2914
|
#u;
|
|
2915
|
+
#s;
|
|
2916
|
+
#l;
|
|
2917
|
+
#g;
|
|
2927
2918
|
#n;
|
|
2928
2919
|
#a = null;
|
|
2929
2920
|
#o = null;
|
|
2930
2921
|
#d = !1;
|
|
2931
2922
|
#h = 0;
|
|
2932
|
-
#
|
|
2923
|
+
#m = 0;
|
|
2933
2924
|
constructor(t) {
|
|
2934
|
-
this.#t = t.canvas, this.#e = t.getHandleHitboxes, this.#r = t.getCurrentPrice, this.#
|
|
2925
|
+
this.#t = t.canvas, this.#e = t.getHandleHitboxes, this.#r = t.getCurrentPrice, this.#i = t.onDrag, this.#u = t.onMissingProtectionDrag, this.#s = t.onMissingProtectionDragEnd, this.#l = t.onMissingProtectionDragCancel, this.#g = t.onTradeModified, this.#n = t.onTradeCloseClicked;
|
|
2935
2926
|
}
|
|
2936
2927
|
cancelActiveInteraction() {
|
|
2937
|
-
this.#o && this.#l?.(), this.#a = null, this.#o = null, this.#d = !1, this.#h = 0, this.#
|
|
2928
|
+
this.#o && this.#l?.(), this.#a = null, this.#o = null, this.#d = !1, this.#h = 0, this.#m = 0;
|
|
2938
2929
|
}
|
|
2939
2930
|
handlePointerEvent(t) {
|
|
2940
2931
|
if (!this.isSupportedEventType(t.type)) return !1;
|
|
@@ -2947,19 +2938,19 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2947
2938
|
return i ? this.handleHoveredHitbox(t, i, e) : (this.resetCursorIfIdle(), !1);
|
|
2948
2939
|
}
|
|
2949
2940
|
isSupportedEventType(t) {
|
|
2950
|
-
return
|
|
2941
|
+
return ee.includes(t);
|
|
2951
2942
|
}
|
|
2952
2943
|
getCanvasMousePoint(t) {
|
|
2953
|
-
const e = this.#t.getBoundingClientRect(), i = this.#t.width / e.width,
|
|
2944
|
+
const e = this.#t.getBoundingClientRect(), i = this.#t.width / e.width, s = this.#t.height / e.height;
|
|
2954
2945
|
return {
|
|
2955
2946
|
x: (t.clientX - e.left) * i,
|
|
2956
|
-
y: (t.clientY - e.top) *
|
|
2947
|
+
y: (t.clientY - e.top) * s
|
|
2957
2948
|
};
|
|
2958
2949
|
}
|
|
2959
2950
|
handleActiveDrag(t, e) {
|
|
2960
2951
|
if (!this.#a) return !1;
|
|
2961
2952
|
const i = this.getNextDragPrice(e.y);
|
|
2962
|
-
return this.#a.price = i, this.#
|
|
2953
|
+
return this.#a.price = i, this.#i?.({
|
|
2963
2954
|
trade: this.#a.trade,
|
|
2964
2955
|
type: this.#a.type,
|
|
2965
2956
|
price: i
|
|
@@ -2967,25 +2958,25 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
2967
2958
|
}
|
|
2968
2959
|
handleActiveMissingProtectionDrag(t, e) {
|
|
2969
2960
|
if (!this.#o || !this.isProtectionHandleType(this.#o.type)) return !1;
|
|
2970
|
-
const i = e.y - this.#h,
|
|
2971
|
-
if (!this.#d && Math.abs(i) <
|
|
2961
|
+
const i = e.y - this.#h, s = c.tradeHandles.missingProtectionHandles.dragActivationThresholdPx;
|
|
2962
|
+
if (!this.#d && Math.abs(i) < s)
|
|
2972
2963
|
return this.consumeEvent(t), !0;
|
|
2973
2964
|
this.#d = !0;
|
|
2974
|
-
const
|
|
2975
|
-
return this.#o.price =
|
|
2965
|
+
const r = this.getNextMissingProtectionPrice(e.y);
|
|
2966
|
+
return this.#o.price = r, this.#u?.({
|
|
2976
2967
|
trade: this.#o.trade,
|
|
2977
2968
|
type: this.#o.type,
|
|
2978
|
-
price:
|
|
2969
|
+
price: r
|
|
2979
2970
|
}), this.consumeEvent(t), !0;
|
|
2980
2971
|
}
|
|
2981
2972
|
getNextDragPrice(t) {
|
|
2982
2973
|
if (!this.#a) return 0;
|
|
2983
|
-
const e = t - this.#h, i = this.#a.viewport.priceRange / this.#t.height,
|
|
2974
|
+
const e = t - this.#h, i = this.#a.viewport.priceRange / this.#t.height, s = p(this.#m - e * i);
|
|
2984
2975
|
return this.isProtectionHandleType(this.#a.type) ? this.constrainExistingProtectionPrice({
|
|
2985
|
-
price:
|
|
2976
|
+
price: s,
|
|
2986
2977
|
hitbox: this.#a,
|
|
2987
2978
|
type: this.#a.type
|
|
2988
|
-
}) :
|
|
2979
|
+
}) : s;
|
|
2989
2980
|
}
|
|
2990
2981
|
getNextMissingProtectionPrice(t) {
|
|
2991
2982
|
if (!this.#o || !this.isProtectionHandleType(this.#o.type)) return 0;
|
|
@@ -3000,7 +2991,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3000
2991
|
return this.#a && this.modifyActiveDragTrade(), this.#a = null, !1;
|
|
3001
2992
|
}
|
|
3002
2993
|
handleMissingProtectionDragEnd() {
|
|
3003
|
-
return this.#o && this.#d && this.isProtectionHandleType(this.#o.type) ? this.#
|
|
2994
|
+
return this.#o && this.#d && this.isProtectionHandleType(this.#o.type) ? this.#s?.({
|
|
3004
2995
|
trade: this.#o.trade,
|
|
3005
2996
|
type: this.#o.type,
|
|
3006
2997
|
price: p(this.#o.price)
|
|
@@ -3010,13 +3001,13 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3010
3001
|
if (!this.#a) return;
|
|
3011
3002
|
const t = p(this.#a.price);
|
|
3012
3003
|
if (this.#a.type === "stopLoss") {
|
|
3013
|
-
this.#
|
|
3004
|
+
this.#g?.({
|
|
3014
3005
|
ticket: this.#a.trade.ticket,
|
|
3015
3006
|
sl: t
|
|
3016
3007
|
});
|
|
3017
3008
|
return;
|
|
3018
3009
|
}
|
|
3019
|
-
this.#
|
|
3010
|
+
this.#g?.({
|
|
3020
3011
|
ticket: this.#a.trade.ticket,
|
|
3021
3012
|
tp: t
|
|
3022
3013
|
});
|
|
@@ -3026,21 +3017,21 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3026
3017
|
}
|
|
3027
3018
|
handleHoveredHitbox(t, e, i) {
|
|
3028
3019
|
if (e.kind === "missingProtectionHandle") return this.handleMissingProtectionHandleHover(t, e, i);
|
|
3029
|
-
const
|
|
3030
|
-
return
|
|
3020
|
+
const s = this.isPointInsideArea(i, e.closeButtonArea), r = this.isPointInsideArea(i, e.labelArea);
|
|
3021
|
+
return s ? this.handleCloseButtonHover(t, e) : (this.updateHandleCursor(e), r && t.type === "pointerdown" && e.type !== "startPrice" && this.startDrag(e, i.y), e.type !== "startPrice" ? (this.consumeEvent(t), !0) : !1);
|
|
3031
3022
|
}
|
|
3032
3023
|
handleMissingProtectionHandleHover(t, e, i) {
|
|
3033
3024
|
return document.body.style.cursor = "ns-resize", t.type === "pointerdown" ? (this.startMissingProtectionDrag(e, i.y), this.consumeEvent(t), !0) : (this.consumeEvent(t), !0);
|
|
3034
3025
|
}
|
|
3035
3026
|
handleCloseButtonHover(t, e) {
|
|
3036
|
-
return document.body.style.cursor = "pointer", t.type
|
|
3027
|
+
return document.body.style.cursor = "pointer", this.consumeEvent(t), t.type === "pointerdown" && this.handleCloseButtonClick(e), !0;
|
|
3037
3028
|
}
|
|
3038
3029
|
handleCloseButtonClick(t) {
|
|
3039
3030
|
if (t.type === "startPrice") {
|
|
3040
3031
|
this.#n?.({ ticket: t.trade.ticket });
|
|
3041
3032
|
return;
|
|
3042
3033
|
}
|
|
3043
|
-
this.#
|
|
3034
|
+
this.#g?.({
|
|
3044
3035
|
ticket: t.trade.ticket,
|
|
3045
3036
|
...t.type === "stopLoss" ? { sl: null } : {},
|
|
3046
3037
|
...t.type === "takeProfit" ? { tp: null } : {}
|
|
@@ -3050,7 +3041,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3050
3041
|
document.body.style.cursor = t.type === "startPrice" ? "crosshair" : "ns-resize";
|
|
3051
3042
|
}
|
|
3052
3043
|
startDrag(t, e) {
|
|
3053
|
-
this.#a = t, this.#h = e, this.#
|
|
3044
|
+
this.#a = t, this.#h = e, this.#m = t.price;
|
|
3054
3045
|
}
|
|
3055
3046
|
startMissingProtectionDrag(t, e) {
|
|
3056
3047
|
this.#o = t, this.#h = e, this.#d = !1;
|
|
@@ -3059,19 +3050,19 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3059
3050
|
!this.#a && !this.#o && (document.body.style.cursor = "crosshair");
|
|
3060
3051
|
}
|
|
3061
3052
|
isPointInsideArea(t, e) {
|
|
3062
|
-
const i = t.x >= e.x && t.x <= e.x + e.width,
|
|
3063
|
-
return i &&
|
|
3053
|
+
const i = t.x >= e.x && t.x <= e.x + e.width, s = t.y >= e.y && t.y <= e.y + e.height;
|
|
3054
|
+
return i && s;
|
|
3064
3055
|
}
|
|
3065
3056
|
isProtectionHandleType(t) {
|
|
3066
3057
|
return t === "stopLoss" || t === "takeProfit";
|
|
3067
3058
|
}
|
|
3068
3059
|
constrainExistingProtectionPrice({ price: t, hitbox: e, type: i }) {
|
|
3069
|
-
const
|
|
3070
|
-
return p(i === "takeProfit" ?
|
|
3060
|
+
const s = this.isBuyTrade(e), r = e.trade.openPrice, n = this.#r?.() ?? 0;
|
|
3061
|
+
return p(i === "takeProfit" ? s ? Math.max(t, r, n) : Math.min(t, r, n) : s ? Math.min(t, n) : Math.max(t, n));
|
|
3071
3062
|
}
|
|
3072
3063
|
constrainProtectionPrice({ price: t, hitbox: e, type: i }) {
|
|
3073
|
-
const
|
|
3074
|
-
return p(i === "takeProfit" ?
|
|
3064
|
+
const s = this.isBuyTrade(e), r = e.trade.openPrice, n = this.#r?.() ?? 0;
|
|
3065
|
+
return p(i === "takeProfit" ? s ? Math.max(t, r, n) : Math.min(t, r, n) : s ? Math.min(t, n) : Math.max(t, n));
|
|
3075
3066
|
}
|
|
3076
3067
|
isBuyTrade(t) {
|
|
3077
3068
|
return String(t.trade.type).toLowerCase().includes("buy");
|
|
@@ -3079,7 +3070,7 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3079
3070
|
consumeEvent(t) {
|
|
3080
3071
|
t.stopPropagation(), t.preventDefault();
|
|
3081
3072
|
}
|
|
3082
|
-
},
|
|
3073
|
+
}, se = class {
|
|
3083
3074
|
#t;
|
|
3084
3075
|
#e;
|
|
3085
3076
|
candles;
|
|
@@ -3106,34 +3097,34 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3106
3097
|
}
|
|
3107
3098
|
render() {
|
|
3108
3099
|
if (this.clearCanvas(), !c.volume.visible || !this.viewport || this.candles.length === 0) return;
|
|
3109
|
-
const t = this.#e, e = this.#t.width, i = this.#t.height, { startIndex:
|
|
3110
|
-
if (
|
|
3111
|
-
const n = this.candles.slice(
|
|
3100
|
+
const t = this.#e, e = this.#t.width, i = this.#t.height, { startIndex: s, endIndex: r } = this.getVisibleRange(e);
|
|
3101
|
+
if (r < s) return;
|
|
3102
|
+
const n = this.candles.slice(s, r + 1), o = this.getMaxVolume(n);
|
|
3112
3103
|
o <= 0 || this.drawVolumeBars({
|
|
3113
3104
|
ctx: t,
|
|
3114
3105
|
candles: n,
|
|
3115
|
-
startIndex:
|
|
3106
|
+
startIndex: s,
|
|
3116
3107
|
maxVolume: o,
|
|
3117
3108
|
chartHeight: i
|
|
3118
3109
|
});
|
|
3119
3110
|
}
|
|
3120
|
-
drawVolumeBars({ ctx: t, candles: e, startIndex: i, maxVolume:
|
|
3111
|
+
drawVolumeBars({ ctx: t, candles: e, startIndex: i, maxVolume: s, chartHeight: r }) {
|
|
3121
3112
|
t.save(), t.globalAlpha = this.opacity, e.forEach((n, o) => {
|
|
3122
3113
|
const a = i + o, l = this.getCandleX(a);
|
|
3123
3114
|
this.drawSingleVolumeBar({
|
|
3124
3115
|
ctx: t,
|
|
3125
3116
|
candle: n,
|
|
3126
3117
|
candleX: l,
|
|
3127
|
-
maxVolume:
|
|
3128
|
-
chartHeight:
|
|
3118
|
+
maxVolume: s,
|
|
3119
|
+
chartHeight: r
|
|
3129
3120
|
});
|
|
3130
3121
|
}), t.restore();
|
|
3131
3122
|
}
|
|
3132
|
-
drawSingleVolumeBar({ ctx: t, candle: e, candleX: i, maxVolume:
|
|
3123
|
+
drawSingleVolumeBar({ ctx: t, candle: e, candleX: i, maxVolume: s, chartHeight: r }) {
|
|
3133
3124
|
if (!this.viewport || e.volume <= 0) return;
|
|
3134
|
-
const n = this.getVolumeAreaHeight(
|
|
3125
|
+
const n = this.getVolumeAreaHeight(r);
|
|
3135
3126
|
if (n <= 0) return;
|
|
3136
|
-
const o = n * (e.volume /
|
|
3127
|
+
const o = n * (e.volume / s), a = Math.min(n, Math.max(o, this.minBarHeight)), l = r - this.bottomOffset - a, d = Math.max(1, this.viewport.candleWidth);
|
|
3137
3128
|
t.fillStyle = this.getVolumeBarColor(e), t.fillRect(i, l, d, a);
|
|
3138
3129
|
}
|
|
3139
3130
|
getVisibleRange(t) {
|
|
@@ -3165,23 +3156,23 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3165
3156
|
clearCanvas() {
|
|
3166
3157
|
this.#e.clearRect(0, 0, this.#t.width, this.#t.height);
|
|
3167
3158
|
}
|
|
3168
|
-
},
|
|
3159
|
+
}, A = (t) => {
|
|
3169
3160
|
const e = document.createElement("canvas");
|
|
3170
3161
|
return e.className = t, e;
|
|
3171
3162
|
}, re = (t, e) => {
|
|
3172
3163
|
const i = document.createElement("div");
|
|
3173
3164
|
i.className = "trading-reload-chart", i.style.backgroundColor = e, i.tabIndex = 0;
|
|
3174
|
-
const r = document.createElement("div");
|
|
3175
|
-
r.className = "trading-reload-chart__layout";
|
|
3176
3165
|
const s = document.createElement("div");
|
|
3177
|
-
s.className = "trading-reload-
|
|
3178
|
-
const
|
|
3179
|
-
|
|
3180
|
-
const
|
|
3181
|
-
|
|
3166
|
+
s.className = "trading-reload-chart__layout";
|
|
3167
|
+
const r = document.createElement("div");
|
|
3168
|
+
r.className = "trading-reload-chart__stack";
|
|
3169
|
+
const n = A("trading-reload-chart__volume"), o = A("trading-reload-chart__plot"), a = A("trading-reload-chart__shapes"), l = A("trading-reload-chart__trades"), d = A("trading-reload-chart__overlay"), u = A("trading-reload-chart__axis-x");
|
|
3170
|
+
r.append(n, o, a, l, d, u);
|
|
3171
|
+
const g = A("trading-reload-chart__axis-y");
|
|
3172
|
+
return s.append(r, g), i.append(s), t.append(i), {
|
|
3182
3173
|
root: i,
|
|
3183
|
-
layout:
|
|
3184
|
-
stack:
|
|
3174
|
+
layout: s,
|
|
3175
|
+
stack: r,
|
|
3185
3176
|
volumeCanvas: n,
|
|
3186
3177
|
candleCanvas: o,
|
|
3187
3178
|
shapesCanvas: a,
|
|
@@ -3189,69 +3180,70 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3189
3180
|
overlayCanvas: d,
|
|
3190
3181
|
axisXCanvas: u,
|
|
3191
3182
|
axisYCanvas: g,
|
|
3192
|
-
interactionTarget:
|
|
3183
|
+
interactionTarget: s
|
|
3193
3184
|
};
|
|
3194
|
-
},
|
|
3185
|
+
}, gt = (t) => typeof t == "object" && t !== null && !Array.isArray(t), Lt = (t, e) => {
|
|
3195
3186
|
const i = { ...t };
|
|
3196
|
-
for (const
|
|
3197
|
-
const
|
|
3198
|
-
if (
|
|
3199
|
-
if (
|
|
3200
|
-
i[
|
|
3187
|
+
for (const s of Object.keys(e)) {
|
|
3188
|
+
const r = e[s], n = t[s];
|
|
3189
|
+
if (r !== void 0) {
|
|
3190
|
+
if (gt(r) && gt(n)) {
|
|
3191
|
+
i[s] = Lt(n, r);
|
|
3201
3192
|
continue;
|
|
3202
3193
|
}
|
|
3203
|
-
i[
|
|
3194
|
+
i[s] = r;
|
|
3204
3195
|
}
|
|
3205
3196
|
}
|
|
3206
3197
|
return i;
|
|
3207
|
-
},
|
|
3198
|
+
}, ft = (t) => Lt(c, t ?? {}), pt = (t, e) => e === void 0 || t.time >= 1e12 ? t : {
|
|
3208
3199
|
...t,
|
|
3209
3200
|
time: t.time * 1e3 - e
|
|
3210
|
-
},
|
|
3201
|
+
}, ne = 12, oe = class {
|
|
3211
3202
|
#t;
|
|
3212
3203
|
#e;
|
|
3213
3204
|
#r;
|
|
3214
|
-
#s = null;
|
|
3215
|
-
#c = null;
|
|
3216
3205
|
#i = null;
|
|
3217
|
-
#l = null;
|
|
3218
3206
|
#u = null;
|
|
3207
|
+
#s = null;
|
|
3208
|
+
#l = null;
|
|
3209
|
+
#g = null;
|
|
3219
3210
|
#n = null;
|
|
3220
3211
|
#a = null;
|
|
3221
3212
|
#o = null;
|
|
3222
3213
|
#d = null;
|
|
3223
3214
|
#h = null;
|
|
3224
|
-
#
|
|
3225
|
-
#
|
|
3226
|
-
#
|
|
3227
|
-
#x = 0;
|
|
3215
|
+
#m = !1;
|
|
3216
|
+
#y = 0;
|
|
3217
|
+
#w = !1;
|
|
3228
3218
|
#T = 0;
|
|
3229
|
-
#
|
|
3230
|
-
#
|
|
3219
|
+
#L = 0;
|
|
3220
|
+
#f = null;
|
|
3221
|
+
#C = null;
|
|
3231
3222
|
#P = null;
|
|
3223
|
+
#b = null;
|
|
3232
3224
|
constructor(t, e) {
|
|
3233
|
-
this.#t = t, this.#e = e, this.#r =
|
|
3234
|
-
canvas: this.#
|
|
3225
|
+
this.#t = t, this.#e = e, this.#r = ft(e.config), this.#i = re(t, this.#r.colors.background), this.#h = new Vt({
|
|
3226
|
+
canvas: this.#i.overlayCanvas,
|
|
3235
3227
|
crosshairColor: this.#r.crosshair.color,
|
|
3236
3228
|
crosshairThickness: this.#r.crosshair.thickness,
|
|
3237
3229
|
crosshairStyle: this.#r.crosshair.style
|
|
3238
|
-
}), this.#
|
|
3230
|
+
}), this.#B(), this.#W(), this.#M(), this.updateProps(e);
|
|
3239
3231
|
}
|
|
3240
3232
|
updateProps(t) {
|
|
3241
3233
|
const e = this.#e.activeShapeTool;
|
|
3242
|
-
this.#e = t, this.#r =
|
|
3234
|
+
this.#e = t, this.#r = ft(t.config), this.#i && (this.#i.root.style.backgroundColor = this.#r.colors.background, this.#i.layout.style.setProperty("--axis-x-height", `${this.#r.axis.axisX.height}px`)), !this.#m && t.candles.length > 0 && this.#I(t.candles), this.#s && (t.activeShapeTool !== e && this.#Y(t.activeShapeTool), this.#l?.setConfig(this.#r.shapes), this.#l?.setShapes(t.shapes), this.#l?.setActiveTool(t.activeShapeTool), this.#g?.setConfig(this.#r.shapes.previousDayHighLow ?? null), this.#g?.setPreviousDay(t.previousDay), this.#n?.setClosedTrades(t.closedTrades ?? []), this.#x(), this.#E(), this.#c());
|
|
3243
3235
|
}
|
|
3244
3236
|
resetChartView() {
|
|
3245
|
-
this.#
|
|
3237
|
+
this.#s?.resetView(), this.#c();
|
|
3246
3238
|
}
|
|
3247
3239
|
destroy() {
|
|
3248
|
-
this.#
|
|
3240
|
+
this.#b?.abort(), this.#b = null, this.#P?.disconnect(), this.#P = null, this.#i?.root.remove(), this.#i = null, this.#u = null, this.#s = null, this.#l = null, this.#g = null, this.#n = null, this.#a = null, this.#o = null, this.#d = null, this.#h = null, this.#f = null, this.#m = !1;
|
|
3249
3241
|
}
|
|
3250
|
-
#
|
|
3251
|
-
if (!this.#
|
|
3252
|
-
const e = t.map((
|
|
3253
|
-
this.#
|
|
3254
|
-
canvas: this.#
|
|
3242
|
+
#I(t) {
|
|
3243
|
+
if (!this.#i || this.#m) return;
|
|
3244
|
+
const e = t.map((s) => pt(s, this.#e.brokerTimezoneOffsetMs));
|
|
3245
|
+
this.#u = new se({
|
|
3246
|
+
canvas: this.#i.volumeCanvas,
|
|
3255
3247
|
candles: e,
|
|
3256
3248
|
bullishColor: this.#r.volume.bullishColor,
|
|
3257
3249
|
bearishColor: this.#r.volume.bearishColor,
|
|
@@ -3259,8 +3251,8 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3259
3251
|
height: this.#r.volume.height,
|
|
3260
3252
|
bottomOffset: this.#r.volume.bottomOffset,
|
|
3261
3253
|
minBarHeight: this.#r.volume.minBarHeight
|
|
3262
|
-
}), this.#
|
|
3263
|
-
canvas: this.#
|
|
3254
|
+
}), this.#s = new _t({
|
|
3255
|
+
canvas: this.#i.candleCanvas,
|
|
3264
3256
|
candles: e,
|
|
3265
3257
|
baseCandleWidth: this.#r.candles.defaultWidth,
|
|
3266
3258
|
baseCandleGap: this.#r.candles.defaultGap,
|
|
@@ -3269,120 +3261,123 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3269
3261
|
autoFollowLatestCandle: this.#r.candles.autoFollowLatestCandle,
|
|
3270
3262
|
autoFollowThresholdCandles: this.#r.candles.autoFollowThresholdCandles,
|
|
3271
3263
|
rightOffsetCandles: this.#r.candles.rightOffsetCandles
|
|
3272
|
-
}), this.#l = new
|
|
3273
|
-
canvas: this.#
|
|
3264
|
+
}), this.#l = new Qt({
|
|
3265
|
+
canvas: this.#i.shapesCanvas,
|
|
3274
3266
|
activeSymbol: this.#e.activeSymbol,
|
|
3275
3267
|
candles: e,
|
|
3276
3268
|
shapes: this.#e.shapes,
|
|
3277
3269
|
activeTool: this.#e.activeShapeTool,
|
|
3278
3270
|
config: this.#r.shapes,
|
|
3279
|
-
onShapeAdded: (
|
|
3280
|
-
this.#e.onShapeAdded?.(
|
|
3271
|
+
onShapeAdded: (s) => {
|
|
3272
|
+
this.#e.onShapeAdded?.(s);
|
|
3273
|
+
},
|
|
3274
|
+
onShapeModified: (s) => {
|
|
3275
|
+
this.#e.onShapeModified?.(s);
|
|
3281
3276
|
},
|
|
3282
|
-
|
|
3283
|
-
this.#e.
|
|
3277
|
+
onShapeSelected: (s) => {
|
|
3278
|
+
this.#e.onShapeSelected?.(s);
|
|
3284
3279
|
},
|
|
3285
|
-
|
|
3286
|
-
this.#e.
|
|
3280
|
+
onShapeDoubleClicked: (s) => {
|
|
3281
|
+
this.#e.onShapeDoubleClicked?.(s);
|
|
3287
3282
|
},
|
|
3288
|
-
onToolChange: (
|
|
3289
|
-
this.#e.onActiveShapeToolChange?.(
|
|
3283
|
+
onToolChange: (s) => {
|
|
3284
|
+
this.#e.onActiveShapeToolChange?.(s);
|
|
3290
3285
|
}
|
|
3291
3286
|
});
|
|
3292
|
-
const i = this.#
|
|
3293
|
-
i && (this.#
|
|
3287
|
+
const i = this.#i.shapesCanvas.getContext("2d");
|
|
3288
|
+
i && (this.#g = new Gt({
|
|
3294
3289
|
ctx: i,
|
|
3295
3290
|
config: this.#r.shapes.previousDayHighLow ?? null
|
|
3296
|
-
}), this.#
|
|
3297
|
-
canvas: this.#
|
|
3291
|
+
}), this.#g.setPreviousDay(this.#e.previousDay)), this.#n = new te({ canvas: this.#i.tradesCanvas }), this.#n.setCandles(e), this.#n.setClosedTrades(this.#e.closedTrades ?? []), this.#x(), this.#o = new Ot({
|
|
3292
|
+
canvas: this.#i.axisXCanvas,
|
|
3298
3293
|
candles: e
|
|
3299
|
-
}), this.#d = new
|
|
3300
|
-
canvas: this.#
|
|
3301
|
-
getHandleHitboxes: () => this.#
|
|
3302
|
-
getCurrentPrice: () => this.#
|
|
3303
|
-
onDrag: (
|
|
3304
|
-
onMissingProtectionDrag: (
|
|
3305
|
-
onMissingProtectionDragEnd: (
|
|
3306
|
-
onMissingProtectionDragCancel: () => this.#
|
|
3307
|
-
onTradeModified: (
|
|
3308
|
-
onTradeCloseClicked: (
|
|
3309
|
-
}), this.#
|
|
3310
|
-
}
|
|
3311
|
-
#
|
|
3312
|
-
if (!this.#
|
|
3313
|
-
this.#
|
|
3314
|
-
const { signal: t } = this.#
|
|
3315
|
-
e.addEventListener("pointerdown", (i) => this.#
|
|
3294
|
+
}), this.#d = new zt({ canvas: this.#i.axisYCanvas }), this.#a = new ie({
|
|
3295
|
+
canvas: this.#i.tradesCanvas,
|
|
3296
|
+
getHandleHitboxes: () => this.#p() ? [] : this.#n?.handleHitboxes ?? [],
|
|
3297
|
+
getCurrentPrice: () => this.#s?.liveCandle?.close ?? 0,
|
|
3298
|
+
onDrag: (s) => this.#z(s),
|
|
3299
|
+
onMissingProtectionDrag: (s) => this.#V(s),
|
|
3300
|
+
onMissingProtectionDragEnd: (s) => this.#N(s),
|
|
3301
|
+
onMissingProtectionDragCancel: () => this.#_(),
|
|
3302
|
+
onTradeModified: (s) => this.#R(s),
|
|
3303
|
+
onTradeCloseClicked: (s) => this.#e.onTradeClose?.(s)
|
|
3304
|
+
}), this.#m = !0, this.#c();
|
|
3305
|
+
}
|
|
3306
|
+
#B() {
|
|
3307
|
+
if (!this.#i) return;
|
|
3308
|
+
this.#b = new AbortController();
|
|
3309
|
+
const { signal: t } = this.#b, e = this.#i.interactionTarget;
|
|
3310
|
+
e.addEventListener("pointerdown", (i) => this.#J(i), { signal: t }), e.addEventListener("pointerup", (i) => this.#j(i), { signal: t }), e.addEventListener("pointermove", (i) => this.#K(i), { signal: t }), e.addEventListener("pointerenter", (i) => this.#Z(i), { signal: t }), e.addEventListener("pointerleave", () => this.#q(), { signal: t }), e.addEventListener("contextmenu", (i) => this.#Q(i), { signal: t }), e.addEventListener("dblclick", (i) => this.#tt(i), { signal: t }), e.addEventListener("wheel", (i) => this.#U(i), {
|
|
3316
3311
|
passive: !1,
|
|
3317
3312
|
signal: t
|
|
3318
|
-
}), this.#
|
|
3313
|
+
}), this.#i.axisXCanvas.addEventListener("pointerenter", (i) => this.#D(i), { signal: t }), this.#i.axisXCanvas.addEventListener("pointerdown", (i) => this.#A(i, "x"), { signal: t }), this.#i.axisXCanvas.addEventListener("pointermove", (i) => this.#X(i), { signal: t }), this.#i.axisXCanvas.addEventListener("pointerup", (i) => this.#S(i), { signal: t }), this.#i.axisXCanvas.addEventListener("pointercancel", (i) => this.#S(i), { signal: t }), this.#i.axisYCanvas.addEventListener("pointerenter", (i) => this.#D(i), { signal: t }), this.#i.axisYCanvas.addEventListener("pointerdown", (i) => this.#A(i, "y"), { signal: t }), this.#i.axisYCanvas.addEventListener("pointermove", (i) => this.#X(i), { signal: t }), this.#i.axisYCanvas.addEventListener("pointerup", (i) => this.#S(i), { signal: t }), this.#i.axisYCanvas.addEventListener("pointercancel", (i) => this.#S(i), { signal: t }), this.#i.axisYCanvas.addEventListener("wheel", (i) => this.#$(i), {
|
|
3319
3314
|
passive: !1,
|
|
3320
3315
|
signal: t
|
|
3321
|
-
}), document.addEventListener("keydown", (i) => this.#
|
|
3316
|
+
}), document.addEventListener("keydown", (i) => this.#et(i), { signal: t });
|
|
3322
3317
|
}
|
|
3323
3318
|
#W() {
|
|
3324
|
-
this.#
|
|
3325
|
-
this.#
|
|
3326
|
-
}), this.#
|
|
3319
|
+
this.#P = new ResizeObserver(() => {
|
|
3320
|
+
this.#M(), this.#c();
|
|
3321
|
+
}), this.#P.observe(this.#t);
|
|
3327
3322
|
}
|
|
3328
|
-
#
|
|
3329
|
-
const t = this.#r.axis.axisY.width, e = this.#r.axis.axisX.height, i = this.#t.clientWidth,
|
|
3323
|
+
#F() {
|
|
3324
|
+
const t = this.#r.axis.axisY.width, e = this.#r.axis.axisX.height, i = this.#t.clientWidth, s = this.#t.clientHeight;
|
|
3330
3325
|
return {
|
|
3331
3326
|
axisYWidth: t,
|
|
3332
3327
|
axisXHeight: e,
|
|
3333
3328
|
plotWidth: Math.max(0, i - t),
|
|
3334
|
-
plotHeight: Math.max(0,
|
|
3329
|
+
plotHeight: Math.max(0, s - e)
|
|
3335
3330
|
};
|
|
3336
3331
|
}
|
|
3337
|
-
#
|
|
3332
|
+
#v(t, e, i) {
|
|
3338
3333
|
t.width = e, t.height = i;
|
|
3339
3334
|
}
|
|
3340
|
-
#
|
|
3341
|
-
if (!this.#
|
|
3342
|
-
const { plotWidth: t, plotHeight: e, axisYWidth: i, axisXHeight:
|
|
3343
|
-
if (this.#
|
|
3344
|
-
const
|
|
3345
|
-
this.#
|
|
3335
|
+
#M() {
|
|
3336
|
+
if (!this.#i) return;
|
|
3337
|
+
const { plotWidth: t, plotHeight: e, axisYWidth: i, axisXHeight: s } = this.#F();
|
|
3338
|
+
if (this.#s && this.#y > 0 && t !== this.#y) {
|
|
3339
|
+
const r = t - this.#y;
|
|
3340
|
+
this.#s.panHorizontally(r);
|
|
3346
3341
|
}
|
|
3347
|
-
this.#
|
|
3342
|
+
this.#y = t, this.#v(this.#i.volumeCanvas, t, e), this.#v(this.#i.candleCanvas, t, e), this.#v(this.#i.shapesCanvas, t, e), this.#v(this.#i.overlayCanvas, t, e), this.#v(this.#i.tradesCanvas, t, e), this.#v(this.#i.axisXCanvas, t, s), this.#v(this.#i.axisYCanvas, i, e);
|
|
3348
3343
|
}
|
|
3349
|
-
#
|
|
3350
|
-
this.#
|
|
3344
|
+
#H() {
|
|
3345
|
+
this.#s && (this.#o?.setCandles(this.#s.candles), this.#o?.setViewport(this.#s.viewport), this.#o?.render(), this.#d?.setViewport(this.#s.viewport), this.#d?.render());
|
|
3351
3346
|
}
|
|
3352
|
-
#
|
|
3353
|
-
this.#
|
|
3347
|
+
#c() {
|
|
3348
|
+
this.#s && (this.#u?.setCandles(this.#s.candles), this.#u?.setLiveCandle(this.#s.liveCandle), this.#u?.setViewport(this.#s.viewport), this.#u?.render(), this.#s.render(), this.#l?.setCandles(this.#s.candles), this.#l?.setViewport(this.#s.viewport), this.#l?.render(), this.#g?.setViewport(this.#s.viewport), this.#g?.render(), this.#n?.setCandles(this.#s.candles), this.#n?.setViewport(this.#s.viewport), this.#n?.isDragging ? this.#n.renderLiveFeed() : this.#n?.render(), this.#H(), this.#h?.render());
|
|
3354
3349
|
}
|
|
3355
|
-
#
|
|
3350
|
+
#p() {
|
|
3356
3351
|
return this.#e.activeShapeTool !== null;
|
|
3357
3352
|
}
|
|
3358
|
-
#
|
|
3359
|
-
t !== null && (this.#
|
|
3353
|
+
#Y(t) {
|
|
3354
|
+
t !== null && (this.#w = !1, this.#n?.setIsDragging(!1), this.#a?.cancelActiveInteraction()), this.#l?.setActiveTool(t);
|
|
3360
3355
|
}
|
|
3361
|
-
#
|
|
3356
|
+
#O() {
|
|
3362
3357
|
const t = this.#e.openTrades ?? [];
|
|
3363
|
-
return this.#
|
|
3358
|
+
return this.#C ? t.map((e) => e.ticket !== this.#C?.ticket ? e : {
|
|
3364
3359
|
...e,
|
|
3365
|
-
...this.#
|
|
3366
|
-
...this.#
|
|
3360
|
+
...this.#C.sl !== void 0 ? { sl: this.#C.sl } : {},
|
|
3361
|
+
...this.#C.tp !== void 0 ? { tp: this.#C.tp } : {}
|
|
3367
3362
|
}) : t;
|
|
3368
3363
|
}
|
|
3369
|
-
#
|
|
3370
|
-
this.#n?.setTrades(this.#
|
|
3364
|
+
#x() {
|
|
3365
|
+
this.#n?.setTrades(this.#O());
|
|
3371
3366
|
}
|
|
3372
|
-
#
|
|
3367
|
+
#E() {
|
|
3373
3368
|
const t = this.#e.liveCandle;
|
|
3374
|
-
if (!t || !this.#
|
|
3375
|
-
const e =
|
|
3376
|
-
this.#
|
|
3369
|
+
if (!t || !this.#s) return;
|
|
3370
|
+
const e = pt(t, this.#e.brokerTimezoneOffsetMs);
|
|
3371
|
+
this.#s.updateLiveCandle(e), this.#n?.setLiveCandle(this.#s.liveCandle), this.#n?.setCandles(this.#s.candles);
|
|
3377
3372
|
}
|
|
3378
|
-
#
|
|
3379
|
-
this.#n && (this.#n.setIsDragging(!0), this.#
|
|
3373
|
+
#z({ trade: t, type: e, price: i }) {
|
|
3374
|
+
this.#n && (this.#n.setIsDragging(!0), this.#C = {
|
|
3380
3375
|
ticket: t.ticket,
|
|
3381
3376
|
...e === "stopLoss" ? { sl: i } : {},
|
|
3382
3377
|
...e === "takeProfit" ? { tp: i } : {}
|
|
3383
|
-
}, this.#
|
|
3378
|
+
}, this.#x(), this.#n.render());
|
|
3384
3379
|
}
|
|
3385
|
-
#
|
|
3380
|
+
#V({ trade: t, type: e, price: i }) {
|
|
3386
3381
|
this.#n?.viewport && (this.#n.setIsDragging(!0), this.#n.setTemporaryProtectionDrag({
|
|
3387
3382
|
visible: !0,
|
|
3388
3383
|
trade: t,
|
|
@@ -3391,28 +3386,28 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3391
3386
|
viewport: this.#n.viewport
|
|
3392
3387
|
}), this.#n.render());
|
|
3393
3388
|
}
|
|
3394
|
-
#
|
|
3395
|
-
this.#n?.setIsDragging(!1), this.#
|
|
3389
|
+
#N({ trade: t, type: e, price: i }) {
|
|
3390
|
+
this.#n?.setIsDragging(!1), this.#R({
|
|
3396
3391
|
ticket: t.ticket,
|
|
3397
3392
|
...e === "stopLoss" ? { sl: i } : {},
|
|
3398
3393
|
...e === "takeProfit" ? { tp: i } : {}
|
|
3399
3394
|
});
|
|
3400
3395
|
}
|
|
3401
|
-
#
|
|
3396
|
+
#_() {
|
|
3402
3397
|
this.#n?.setIsDragging(!1), this.#n?.clearTemporaryProtectionDrag(), this.#n?.render();
|
|
3403
3398
|
}
|
|
3404
|
-
#
|
|
3405
|
-
this.#n?.setIsDragging(!1), this.#
|
|
3399
|
+
#R(t) {
|
|
3400
|
+
this.#n?.setIsDragging(!1), this.#C = null, this.#n?.clearTemporaryProtectionDrag(), this.#e.onTradeModify?.(t), this.#x(), this.#n?.render();
|
|
3406
3401
|
}
|
|
3407
|
-
#
|
|
3408
|
-
if (!this.#h || !this.#
|
|
3409
|
-
if (!this.#
|
|
3402
|
+
#k(t) {
|
|
3403
|
+
if (!this.#h || !this.#i) return;
|
|
3404
|
+
if (!this.#s) {
|
|
3410
3405
|
this.#h.updateMousePosition(t.clientX, t.clientY), this.#h.render();
|
|
3411
3406
|
return;
|
|
3412
3407
|
}
|
|
3413
|
-
const e =
|
|
3414
|
-
this.#h.updateMousePosition(t.clientX, t.clientY, { snapX:
|
|
3415
|
-
const n = this.#
|
|
3408
|
+
const e = vt(this.#i.overlayCanvas, t), i = this.#s.getNearestCandleIndexByX(e.x), s = i === null ? null : this.#s.candles[i] ?? null, r = i === null ? e.x : this.#s.getRawCandleSnapX(e.x);
|
|
3409
|
+
this.#h.updateMousePosition(t.clientX, t.clientY, { snapX: r });
|
|
3410
|
+
const n = this.#s.getPriceAtY(this.#h.mouseY);
|
|
3416
3411
|
this.#d?.setCrosshair({
|
|
3417
3412
|
visible: !0,
|
|
3418
3413
|
y: this.#h.mouseY,
|
|
@@ -3420,75 +3415,105 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3420
3415
|
}), this.#o?.setCrosshair({
|
|
3421
3416
|
visible: !0,
|
|
3422
3417
|
x: this.#h.mouseX,
|
|
3423
|
-
candle:
|
|
3424
|
-
}), this.#
|
|
3418
|
+
candle: s
|
|
3419
|
+
}), this.#H(), this.#h.render();
|
|
3425
3420
|
}
|
|
3426
|
-
#
|
|
3427
|
-
this.#h?.hide(), this.#o?.hideCrosshair(), this.#d?.hideCrosshair(), this.#
|
|
3421
|
+
#G() {
|
|
3422
|
+
this.#h?.hide(), this.#o?.hideCrosshair(), this.#d?.hideCrosshair(), this.#H(), this.#h?.render();
|
|
3428
3423
|
}
|
|
3429
|
-
#
|
|
3430
|
-
if (!this.#
|
|
3431
|
-
this.#
|
|
3424
|
+
#U(t) {
|
|
3425
|
+
if (!this.#s || !this.#n) return;
|
|
3426
|
+
this.#p() || this.#a?.handlePointerEvent(t), t.preventDefault();
|
|
3432
3427
|
const e = t.deltaY < 0 ? 1 : -1;
|
|
3433
|
-
t.ctrlKey || t.metaKey ? this.#
|
|
3428
|
+
t.ctrlKey || t.metaKey ? this.#s.zoomVertically(e) : this.#s.zoomHorizontally(e), this.#c();
|
|
3434
3429
|
}
|
|
3435
|
-
|
|
3436
|
-
if (!this.#
|
|
3430
|
+
#$(t) {
|
|
3431
|
+
if (!this.#s) return;
|
|
3437
3432
|
t.preventDefault(), t.stopPropagation();
|
|
3438
3433
|
const e = t.deltaY < 0 ? 1 : -1;
|
|
3439
|
-
this.#
|
|
3434
|
+
this.#s.zoomVertically(e), this.#c();
|
|
3435
|
+
}
|
|
3436
|
+
#D(t) {
|
|
3437
|
+
const e = t.currentTarget;
|
|
3438
|
+
e.style.cursor = e === this.#i?.axisXCanvas ? "ew-resize" : "ns-resize";
|
|
3439
|
+
}
|
|
3440
|
+
#A(t, e) {
|
|
3441
|
+
t.stopPropagation(), t.button === 0 && (t.currentTarget.setPointerCapture(t.pointerId), this.#f = {
|
|
3442
|
+
axis: e,
|
|
3443
|
+
lastClientPosition: e === "x" ? t.clientX : t.clientY,
|
|
3444
|
+
pointerId: t.pointerId
|
|
3445
|
+
}, t.preventDefault());
|
|
3446
|
+
}
|
|
3447
|
+
#X(t) {
|
|
3448
|
+
t.stopPropagation();
|
|
3449
|
+
const e = t.currentTarget, i = e === this.#i?.axisXCanvas ? "x" : "y";
|
|
3450
|
+
if (e.style.cursor = i === "x" ? "ew-resize" : "ns-resize", !this.#f || this.#f.pointerId !== t.pointerId || this.#f.axis !== i) return;
|
|
3451
|
+
const s = i === "x" ? t.clientX : t.clientY, r = s - this.#f.lastClientPosition;
|
|
3452
|
+
if (this.#f.lastClientPosition = s, !this.#s || r === 0) return;
|
|
3453
|
+
const n = (i === "x" ? r : -r) / ne;
|
|
3454
|
+
i === "x" ? this.#s.zoomHorizontally(n) : this.#s.zoomVertically(n), t.preventDefault(), this.#c();
|
|
3455
|
+
}
|
|
3456
|
+
#S(t) {
|
|
3457
|
+
if (t.stopPropagation(), this.#f?.pointerId !== t.pointerId) return;
|
|
3458
|
+
const e = t.currentTarget;
|
|
3459
|
+
e.hasPointerCapture(t.pointerId) && e.releasePointerCapture(t.pointerId), this.#f = null, t.preventDefault();
|
|
3440
3460
|
}
|
|
3441
|
-
#
|
|
3442
|
-
if (this.#
|
|
3443
|
-
this.#
|
|
3444
|
-
|
|
3461
|
+
#J(t) {
|
|
3462
|
+
if (!(!this.#p() && this.#a?.handlePointerEvent(t))) {
|
|
3463
|
+
if (this.#l?.handlePointerEvent(t) ?? !1) {
|
|
3464
|
+
this.#c();
|
|
3465
|
+
return;
|
|
3466
|
+
}
|
|
3467
|
+
this.#p() || (this.#w = !0, this.#T = t.clientX, this.#L = t.clientY);
|
|
3445
3468
|
}
|
|
3446
|
-
this.#m() || this.#a?.handlePointerEvent(t) || (this.#y = !0, this.#x = t.clientX, this.#T = t.clientY);
|
|
3447
3469
|
}
|
|
3448
|
-
#
|
|
3470
|
+
#K(t) {
|
|
3449
3471
|
const e = this.#l?.handlePointerEvent(t) ?? !1;
|
|
3450
|
-
if (this.#
|
|
3451
|
-
this.#
|
|
3472
|
+
if (this.#p() || this.#a?.handlePointerEvent(t), this.#k(t), e) {
|
|
3473
|
+
this.#c(), this.#k(t);
|
|
3452
3474
|
return;
|
|
3453
3475
|
}
|
|
3454
|
-
if (!this.#
|
|
3455
|
-
const i = t.clientX - this.#
|
|
3456
|
-
this.#
|
|
3476
|
+
if (!this.#w || !this.#s || this.#p()) return;
|
|
3477
|
+
const i = t.clientX - this.#T, s = t.clientY - this.#L;
|
|
3478
|
+
this.#T = t.clientX, this.#L = t.clientY, this.#s.panHorizontally(i), this.#s.panVertically(s), this.#c(), this.#k(t);
|
|
3457
3479
|
}
|
|
3458
|
-
#
|
|
3459
|
-
if (this.#
|
|
3460
|
-
this.#
|
|
3480
|
+
#j(t) {
|
|
3481
|
+
if (this.#w = !1, this.#l?.handlePointerEvent(t) ?? !1) {
|
|
3482
|
+
this.#c();
|
|
3461
3483
|
return;
|
|
3462
3484
|
}
|
|
3463
|
-
this.#
|
|
3485
|
+
this.#p() || this.#a?.handlePointerEvent(t);
|
|
3464
3486
|
}
|
|
3465
|
-
#
|
|
3466
|
-
document.body.style.cursor = "crosshair", this.#l?.handlePointerEvent(t), this.#
|
|
3487
|
+
#Z(t) {
|
|
3488
|
+
document.body.style.cursor = "crosshair", this.#l?.handlePointerEvent(t), this.#p() || this.#a?.handlePointerEvent(t);
|
|
3467
3489
|
}
|
|
3468
|
-
|
|
3469
|
-
this.#l?.clearHoverState(), document.body.style.cursor = "", this.#
|
|
3490
|
+
#q() {
|
|
3491
|
+
this.#l?.clearHoverState(), document.body.style.cursor = "", this.#G();
|
|
3470
3492
|
}
|
|
3471
|
-
#
|
|
3472
|
-
((this.#l?.handlePointerEvent(t) ?? !1) || this.#
|
|
3493
|
+
#Q(t) {
|
|
3494
|
+
((this.#l?.handlePointerEvent(t) ?? !1) || this.#p()) && (t.preventDefault(), t.stopPropagation(), this.#c());
|
|
3473
3495
|
}
|
|
3474
|
-
#
|
|
3475
|
-
|
|
3496
|
+
#tt(t) {
|
|
3497
|
+
this.#l?.handlePointerEvent(t);
|
|
3498
|
+
}
|
|
3499
|
+
#et(t) {
|
|
3500
|
+
(this.#l?.handleKeyboardEvent(t) ?? !1) && (t.preventDefault(), this.#c());
|
|
3476
3501
|
}
|
|
3477
|
-
},
|
|
3478
|
-
const
|
|
3479
|
-
return o.current = i,
|
|
3502
|
+
}, he = Rt(({ className: t, style: e, ...i }, s) => {
|
|
3503
|
+
const r = N(null), n = N(null), o = N(i);
|
|
3504
|
+
return o.current = i, Dt(s, () => ({ resetChartView() {
|
|
3480
3505
|
n.current?.resetChartView();
|
|
3481
|
-
} })),
|
|
3482
|
-
const a =
|
|
3506
|
+
} })), st(() => {
|
|
3507
|
+
const a = r.current;
|
|
3483
3508
|
if (!a) return;
|
|
3484
|
-
const l = new
|
|
3509
|
+
const l = new oe(a, o.current);
|
|
3485
3510
|
return n.current = l, () => {
|
|
3486
3511
|
l.destroy(), n.current = null;
|
|
3487
3512
|
};
|
|
3488
|
-
}, []),
|
|
3513
|
+
}, []), st(() => {
|
|
3489
3514
|
n.current?.updateProps(o.current);
|
|
3490
|
-
}, [i]), /* @__PURE__ */
|
|
3491
|
-
ref:
|
|
3515
|
+
}, [i]), /* @__PURE__ */ At("div", {
|
|
3516
|
+
ref: r,
|
|
3492
3517
|
className: t,
|
|
3493
3518
|
style: {
|
|
3494
3519
|
width: "100%",
|
|
@@ -3499,5 +3524,5 @@ var U = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID(
|
|
|
3499
3524
|
});
|
|
3500
3525
|
export {
|
|
3501
3526
|
c as CHART_CONFIG,
|
|
3502
|
-
|
|
3527
|
+
he as TradingReload
|
|
3503
3528
|
};
|