@alphacharts/drawings 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,4882 @@
1
+ import { crisp as e, parseColor as t, rgba as n } from "@alphacharts/core";
2
+ //#region \0rolldown/runtime.js
3
+ var r = Object.defineProperty, i = (e, t) => {
4
+ let n = {};
5
+ for (var i in e) r(n, i, {
6
+ get: e[i],
7
+ enumerable: !0
8
+ });
9
+ return t || r(n, Symbol.toStringTag, { value: "Module" }), n;
10
+ }, a = class {
11
+ map = /* @__PURE__ */ new Map();
12
+ on(e, t) {
13
+ let n = this.map.get(e);
14
+ return n || this.map.set(e, n = /* @__PURE__ */ new Set()), n.add(t), () => this.map.get(e)?.delete(t);
15
+ }
16
+ emit(e, t) {
17
+ let n = this.map.get(e);
18
+ if (n) for (let e of [...n]) e(t);
19
+ }
20
+ }, o = /* @__PURE__ */ i({
21
+ arcPoints: () => d,
22
+ arrowHead: () => ee,
23
+ circumcircle: () => m,
24
+ clipLine: () => l,
25
+ controlThrough: () => p,
26
+ dist: () => s,
27
+ distToPolyline: () => g,
28
+ distToSegment: () => c,
29
+ ellipsePoints: () => u,
30
+ intersect: () => _,
31
+ pointInPolygon: () => h,
32
+ quadPoints: () => f
33
+ });
34
+ function s(e, t, n, r) {
35
+ return Math.hypot(n - e, r - t);
36
+ }
37
+ function c(e, t, n, r, i, a) {
38
+ let o = i - n, c = a - r, l = o * o + c * c;
39
+ if (l === 0) return s(e, t, n, r);
40
+ let u = ((e - n) * o + (t - r) * c) / l;
41
+ return u = Math.max(0, Math.min(1, u)), s(e, t, n + u * o, r + u * c);
42
+ }
43
+ function l(e, t, n, r, i, a, o, s, c = 2) {
44
+ let l = n - e, u = r - t;
45
+ if (l === 0 && u === 0) return null;
46
+ let d = -Infinity, f = Infinity, p = (e, t) => {
47
+ if (e === 0) return t >= 0;
48
+ let n = t / e;
49
+ if (e < 0) {
50
+ if (n > f) return !1;
51
+ n > d && (d = n);
52
+ } else {
53
+ if (n < d) return !1;
54
+ n < f && (f = n);
55
+ }
56
+ return !0;
57
+ };
58
+ if (!p(-l, e + c) || !p(l, o + c - e) || !p(-u, t + c) || !p(u, s + c - t)) return null;
59
+ let m = i ? d : Math.max(d, 0), h = a ? f : Math.min(f, 1);
60
+ return m > h ? null : [
61
+ e + m * l,
62
+ t + m * u,
63
+ e + h * l,
64
+ t + h * u
65
+ ];
66
+ }
67
+ function u(e, t, n, r, i, a = 72) {
68
+ let o = [], s = Math.cos(i), c = Math.sin(i);
69
+ for (let i = 0; i < a; i++) {
70
+ let l = i / a * Math.PI * 2, u = n * Math.cos(l), d = r * Math.sin(l);
71
+ o.push(e + u * s - d * c, t + u * c + d * s);
72
+ }
73
+ return o;
74
+ }
75
+ function d(e, t, n, r, i) {
76
+ let a = Math.max(6, Math.min(180, Math.ceil(Math.abs(i - r) * n / 4))), o = [];
77
+ for (let s = 0; s <= a; s++) {
78
+ let c = r + (i - r) * s / a;
79
+ o.push(e + n * Math.cos(c), t + n * Math.sin(c));
80
+ }
81
+ return o;
82
+ }
83
+ function f(e, t, n, r = 48) {
84
+ let i = [];
85
+ for (let a = 0; a <= r; a++) {
86
+ let o = a / r, s = 1 - o;
87
+ i.push(s * s * e.x + 2 * s * o * t.x + o * o * n.x, s * s * e.y + 2 * s * o * t.y + o * o * n.y);
88
+ }
89
+ return i;
90
+ }
91
+ function p(e, t, n) {
92
+ return {
93
+ x: 2 * t.x - (e.x + n.x) / 2,
94
+ y: 2 * t.y - (e.y + n.y) / 2
95
+ };
96
+ }
97
+ function m(e, t, n) {
98
+ let r = 2 * (e.x * (t.y - n.y) + t.x * (n.y - e.y) + n.x * (e.y - t.y));
99
+ if (Math.abs(r) < 1e-9) return null;
100
+ let i = e.x * e.x + e.y * e.y, a = t.x * t.x + t.y * t.y, o = n.x * n.x + n.y * n.y, c = (i * (t.y - n.y) + a * (n.y - e.y) + o * (e.y - t.y)) / r, l = (i * (n.x - t.x) + a * (e.x - n.x) + o * (t.x - e.x)) / r;
101
+ return {
102
+ cx: c,
103
+ cy: l,
104
+ r: s(c, l, e.x, e.y)
105
+ };
106
+ }
107
+ function h(e, t, n) {
108
+ let r = !1, i = n.length / 2;
109
+ for (let a = 0, o = i - 1; a < i; o = a++) {
110
+ let i = n[2 * a], s = n[2 * a + 1], c = n[2 * o], l = n[2 * o + 1];
111
+ s > t != l > t && e < (c - i) * (t - s) / (l - s) + i && (r = !r);
112
+ }
113
+ return r;
114
+ }
115
+ function g(e, t, n, r) {
116
+ let i = n.length / 2;
117
+ if (i === 0) return Infinity;
118
+ if (i === 1) return s(e, t, n[0], n[1]);
119
+ let a = Infinity, o = r ? i : i - 1;
120
+ for (let r = 0; r < o; r++) {
121
+ let o = (r + 1) % i;
122
+ a = Math.min(a, c(e, t, n[2 * r], n[2 * r + 1], n[2 * o], n[2 * o + 1]));
123
+ }
124
+ return a;
125
+ }
126
+ function _(e, t, n, r) {
127
+ let i = (t.x - e.x) * (r.y - n.y) - (t.y - e.y) * (r.x - n.x);
128
+ if (Math.abs(i) < 1e-12) return null;
129
+ let a = ((n.x - e.x) * (r.y - n.y) - (n.y - e.y) * (r.x - n.x)) / i;
130
+ return {
131
+ x: e.x + a * (t.x - e.x),
132
+ y: e.y + a * (t.y - e.y)
133
+ };
134
+ }
135
+ function ee(e, t, n, r, i) {
136
+ let a = Math.atan2(r - t, n - e), o = .45;
137
+ return [
138
+ n,
139
+ r,
140
+ n - i * Math.cos(a - o),
141
+ r - i * Math.sin(a - o),
142
+ n - i * Math.cos(a + o),
143
+ r - i * Math.sin(a + o)
144
+ ];
145
+ }
146
+ //#endregion
147
+ //#region src/history.ts
148
+ var te = class {
149
+ items = [];
150
+ index = /* @__PURE__ */ new Map();
151
+ get list() {
152
+ return this.items;
153
+ }
154
+ get(e) {
155
+ return this.index.get(e);
156
+ }
157
+ require(e) {
158
+ let t = this.index.get(e);
159
+ if (!t) throw Error(`drawings: no drawing with id "${e}"`);
160
+ return t;
161
+ }
162
+ insert(e, t) {
163
+ if (this.index.has(e.id)) throw Error(`drawings: duplicate drawing id "${e.id}"`);
164
+ if (!Number.isInteger(t) || t < 0 || t > this.items.length) throw RangeError(`drawings: insert index ${t} outside 0..${this.items.length}`);
165
+ this.items.splice(t, 0, e), this.index.set(e.id, e);
166
+ }
167
+ remove(e) {
168
+ let t = this.items.findIndex((t) => t.id === e);
169
+ if (t < 0) throw Error(`drawings: no drawing with id "${e}"`);
170
+ return this.items.splice(t, 1), this.index.delete(e), t;
171
+ }
172
+ replace(e) {
173
+ let t = this.items.findIndex((t) => t.id === e.id);
174
+ if (t < 0) throw Error(`drawings: no drawing with id "${e.id}"`);
175
+ this.items[t] = e, this.index.set(e.id, e);
176
+ }
177
+ setOrder(e) {
178
+ if (e.length !== this.items.length || new Set(e).size !== e.length) throw Error("drawings: setOrder needs every id exactly once");
179
+ this.items = e.map((e) => this.require(e));
180
+ }
181
+ clear() {
182
+ this.items = [], this.index.clear();
183
+ }
184
+ snapshot() {
185
+ return JSON.stringify(this.items);
186
+ }
187
+ }, v = (e) => structuredClone(e), y = class {
188
+ d;
189
+ at;
190
+ label = "add";
191
+ ids;
192
+ constructor(e, t) {
193
+ this.d = e, this.at = t, this.ids = [e.id];
194
+ }
195
+ apply(e) {
196
+ e.insert(v(this.d), this.at);
197
+ }
198
+ revert(e) {
199
+ e.remove(this.d.id);
200
+ }
201
+ }, ne = class {
202
+ label = "remove";
203
+ ids;
204
+ entries;
205
+ constructor(e) {
206
+ this.entries = [...e].sort((e, t) => e.at - t.at).map((e) => ({
207
+ d: v(e.d),
208
+ at: e.at
209
+ })), this.ids = this.entries.map((e) => e.d.id);
210
+ }
211
+ apply(e) {
212
+ for (let t of this.entries) e.remove(t.d.id);
213
+ }
214
+ revert(e) {
215
+ for (let t of this.entries) e.insert(v(t.d), t.at);
216
+ }
217
+ }, b = class {
218
+ label;
219
+ before;
220
+ after;
221
+ ids;
222
+ constructor(e, t, n) {
223
+ if (this.label = e, this.before = t, this.after = n, t.length !== n.length || t.some((e, t) => e.id !== n[t].id)) throw Error("drawings: PatchCommand needs matching before/after drawings");
224
+ this.ids = t.map((e) => e.id), this.before = t.map(v), this.after = n.map(v);
225
+ }
226
+ apply(e) {
227
+ for (let t of this.after) e.replace(v(t));
228
+ }
229
+ revert(e) {
230
+ for (let t of this.before) e.replace(v(t));
231
+ }
232
+ }, re = class {
233
+ before;
234
+ after;
235
+ label = "reorder";
236
+ ids;
237
+ constructor(e, t) {
238
+ this.before = e, this.after = t, this.ids = t;
239
+ }
240
+ apply(e) {
241
+ e.setOrder(this.after);
242
+ }
243
+ revert(e) {
244
+ e.setOrder(this.before);
245
+ }
246
+ }, ie = class {
247
+ label;
248
+ cmds;
249
+ ids;
250
+ constructor(e, t) {
251
+ this.label = e, this.cmds = t, this.ids = t.flatMap((e) => e.ids);
252
+ }
253
+ apply(e) {
254
+ for (let t of this.cmds) t.apply(e);
255
+ }
256
+ revert(e) {
257
+ for (let t = this.cmds.length - 1; t >= 0; t--) this.cmds[t].revert(e);
258
+ }
259
+ }, ae = class {
260
+ store;
261
+ max;
262
+ undoStack = [];
263
+ redoStack = [];
264
+ constructor(e, t = 500) {
265
+ this.store = e, this.max = t;
266
+ }
267
+ get canUndo() {
268
+ return this.undoStack.length > 0;
269
+ }
270
+ get canRedo() {
271
+ return this.redoStack.length > 0;
272
+ }
273
+ run(e) {
274
+ e.apply(this.store), this.undoStack.push(e), this.undoStack.length > this.max && this.undoStack.shift(), this.redoStack = [];
275
+ }
276
+ record(e) {
277
+ this.undoStack.push(e), this.undoStack.length > this.max && this.undoStack.shift(), this.redoStack = [];
278
+ }
279
+ undo() {
280
+ let e = this.undoStack.pop();
281
+ if (e) return e.revert(this.store), this.redoStack.push(e), e;
282
+ }
283
+ redo() {
284
+ let e = this.redoStack.pop();
285
+ if (e) return e.apply(this.store), this.undoStack.push(e), e;
286
+ }
287
+ clear() {
288
+ this.undoStack = [], this.redoStack = [];
289
+ }
290
+ };
291
+ //#endregion
292
+ //#region src/shapes.ts
293
+ function oe(e, t) {
294
+ return e === "solid" ? [] : e === "dashed" ? [4 * t, 3 * t] : [t, 2 * t];
295
+ }
296
+ var x = /* @__PURE__ */ new Map();
297
+ function S(e, r) {
298
+ let i = `${e}|${r}`, a = x.get(i);
299
+ if (a === void 0) {
300
+ x.size > 2048 && x.clear();
301
+ let o = n(t(e));
302
+ a = `rgba(${Math.round(o[0] * 255)},${Math.round(o[1] * 255)},${Math.round(o[2] * 255)},${r})`, x.set(i, a);
303
+ }
304
+ return a;
305
+ }
306
+ var C = /* @__PURE__ */ new Map();
307
+ function se(e, t) {
308
+ let n = t ?? e.fontSize, r = `${e.italic ? "i" : ""}${e.bold ? "b" : ""}${n}`, i = C.get(r);
309
+ return i === void 0 && (C.size > 512 && C.clear(), i = `${e.italic ? "italic " : ""}${e.bold ? "bold " : ""}${n}px system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif`, C.set(r, i)), i;
310
+ }
311
+ function ce(e, t, n) {
312
+ let r = e.size ?? t.fontSize, i = e.pad ?? (e.bg || e.border ? 4 : 0), a = se(t, r), o, s;
313
+ if (e.text.indexOf("\n") < 0) o = n(e.text, a) + 2 * i, s = 1;
314
+ else {
315
+ let t = e.text.split("\n");
316
+ o = Math.max(...t.map((e) => n(e, a))) + 2 * i, s = t.length;
317
+ }
318
+ let c = s * r * 1.25 + 2 * i;
319
+ return {
320
+ x: e.align === "right" ? e.x - o : e.align === "center" ? e.x - o / 2 : e.x,
321
+ y: e.base === "bottom" ? e.y - c : e.base === "middle" ? e.y - c / 2 : e.y,
322
+ w: o,
323
+ h: c
324
+ };
325
+ }
326
+ function le(e, t) {
327
+ let n = [], r = e.map((e) => ({
328
+ it: e,
329
+ b: ce(e.s, e.style, t)
330
+ })).sort((e, t) => e.b.y - t.b.y);
331
+ for (let { it: e, b: t } of r) {
332
+ let r = t.y;
333
+ for (let e = !0, i = 0; e && i < 64; i++) {
334
+ e = !1;
335
+ for (let i of n) t.x < i.x + i.w && i.x < t.x + t.w && r < i.y + i.h && i.y < r + t.h && (r = i.y + i.h + 1, e = !0);
336
+ }
337
+ r !== t.y && (e.s.y += r - t.y), n.push({
338
+ x: t.x,
339
+ y: r,
340
+ w: t.w,
341
+ h: t.h
342
+ });
343
+ }
344
+ }
345
+ var ue = /* @__PURE__ */ new Map(), de = 0;
346
+ function fe(e, t, n) {
347
+ let r = ue.get(n);
348
+ r || ue.set(n, r = /* @__PURE__ */ new Map());
349
+ let i = r.get(t);
350
+ return i === void 0 && (de > 4096 && (ue.clear(), de = 0, ue.set(n, r = /* @__PURE__ */ new Map())), e.font = n, r.set(t, i = e.measureText(t).width), de++), i;
351
+ }
352
+ function w(e, t, n, r, i, a, o) {
353
+ return n < -o || e > i + o || r < -o || t > a + o;
354
+ }
355
+ function pe(e, t, n, r, i, a = {}) {
356
+ let o = a.widthBoost ?? 0;
357
+ e.lineJoin = "round", e.lineCap = "round";
358
+ let s, c, u = -1, d, f = (t) => {
359
+ let r = (t.width ?? n.width) + o;
360
+ if (r <= 0) return !1;
361
+ let i = t.color ?? n.color;
362
+ i !== s && (e.strokeStyle = s = i), r !== u && (e.lineWidth = u = r);
363
+ let a = t.dash ?? n.dash, c = a === "solid" ? "" : `${a}${r}`;
364
+ return c !== d && (e.setLineDash(oe(a, r)), d = c), !0;
365
+ }, p = (t) => {
366
+ t !== c && (e.fillStyle = c = t);
367
+ };
368
+ for (let a of t) {
369
+ let t = (a.width ?? n.width) + o + 2;
370
+ switch (a.k) {
371
+ case "line": {
372
+ let t = l(a.x1, a.y1, a.x2, a.y2, a.extA ?? !1, a.extB ?? !1, r, i);
373
+ if (!t || !f(a)) break;
374
+ e.beginPath(), e.moveTo(t[0], t[1]), e.lineTo(t[2], t[3]), e.stroke();
375
+ break;
376
+ }
377
+ case "poly": {
378
+ let n = a.pts.length / 2;
379
+ if (n < 2) break;
380
+ let o = Infinity, s = Infinity, c = -Infinity, l = -Infinity;
381
+ for (let e = 0; e < a.pts.length; e += 2) {
382
+ let t = a.pts[e], n = a.pts[e + 1];
383
+ t < o && (o = t), t > c && (c = t), n < s && (s = n), n > l && (l = n);
384
+ }
385
+ if (w(o, s, c, l, r, i, t)) break;
386
+ e.beginPath(), e.moveTo(a.pts[0], a.pts[1]);
387
+ for (let t = 1; t < n; t++) e.lineTo(a.pts[2 * t], a.pts[2 * t + 1]);
388
+ a.close && e.closePath(), a.fill && (p(a.fill), e.fill()), f(a) && e.stroke();
389
+ break;
390
+ }
391
+ case "ellipse": {
392
+ let n = Math.max(Math.abs(a.rx), Math.abs(a.ry));
393
+ if (w(a.cx - n, a.cy - n, a.cx + n, a.cy + n, r, i, t)) break;
394
+ e.beginPath(), e.ellipse(a.cx, a.cy, Math.max(0, a.rx), Math.max(0, a.ry), a.rot ?? 0, 0, Math.PI * 2), a.fill && (p(a.fill), e.fill()), f(a) && e.stroke();
395
+ break;
396
+ }
397
+ case "arc":
398
+ if (w(a.cx - Math.abs(a.r), a.cy - Math.abs(a.r), a.cx + Math.abs(a.r), a.cy + Math.abs(a.r), r, i, t)) break;
399
+ e.beginPath(), a.fill && e.moveTo(a.cx, a.cy), e.arc(a.cx, a.cy, Math.max(0, a.r), a.a0, a.a1, a.a1 < a.a0), a.fill && (e.closePath(), p(a.fill), e.fill()), f(a) && e.stroke();
400
+ break;
401
+ case "text": {
402
+ let t = a.size ?? n.fontSize, o = ce(a, n, (t, n) => fe(e, t, n));
403
+ if (w(o.x, o.y, o.x + o.w, o.y + o.h, r, i, 2)) break;
404
+ e.font = se(n, t), a.bg && (p(a.bg), e.fillRect(o.x, o.y, o.w, o.h)), a.border && (e.strokeStyle = s = a.border, e.lineWidth = u = 1, e.setLineDash([]), d = "", e.strokeRect(o.x + .5, o.y + .5, o.w - 1, o.h - 1)), p(a.textColor ?? n.textColor), e.textAlign = "left", e.textBaseline = "top";
405
+ let c = a.pad ?? (a.bg || a.border ? 4 : 0);
406
+ a.text.indexOf("\n") < 0 ? e.fillText(a.text, o.x + c, o.y + c + t * .125) : a.text.split("\n").forEach((n, r) => e.fillText(n, o.x + c, o.y + c + r * t * 1.25 + t * .125));
407
+ break;
408
+ }
409
+ }
410
+ }
411
+ e.setLineDash([]);
412
+ }
413
+ function me(e, t, n) {
414
+ switch (e.k) {
415
+ case "line": {
416
+ let r = l(e.x1, e.y1, e.x2, e.y2, e.extA ?? !1, e.extB ?? !1, t, n, 1e6);
417
+ return r ? [{
418
+ pts: [...r],
419
+ close: !1,
420
+ fill: !1
421
+ }] : [];
422
+ }
423
+ case "poly": return [{
424
+ pts: e.pts,
425
+ close: e.close ?? !1,
426
+ fill: !!e.fill
427
+ }];
428
+ case "ellipse": return [{
429
+ pts: u(e.cx, e.cy, e.rx, e.ry, e.rot ?? 0),
430
+ close: !0,
431
+ fill: !!e.fill
432
+ }];
433
+ case "arc": {
434
+ let t = d(e.cx, e.cy, e.r, e.a0, e.a1);
435
+ return [{
436
+ pts: e.fill ? [
437
+ e.cx,
438
+ e.cy,
439
+ ...t
440
+ ] : t,
441
+ close: !!e.fill,
442
+ fill: !!e.fill
443
+ }];
444
+ }
445
+ case "text": return [];
446
+ }
447
+ }
448
+ function he(e, t, n, r, i, a, o) {
449
+ if (e.hit === !1) return Infinity;
450
+ if (e.k === "text") {
451
+ let r = ce(e, a, o), i = Math.max(r.x - t, 0, t - (r.x + r.w)), s = Math.max(r.y - n, 0, n - (r.y + r.h));
452
+ return Math.hypot(i, s);
453
+ }
454
+ if (e.k === "line") {
455
+ let a = l(e.x1, e.y1, e.x2, e.y2, e.extA ?? !1, e.extB ?? !1, r, i, 1e6);
456
+ return a ? c(t, n, a[0], a[1], a[2], a[3]) : Infinity;
457
+ }
458
+ let s = Infinity;
459
+ for (let a of me(e, r, i)) {
460
+ if (a.fill && a.close && h(t, n, a.pts)) return 0;
461
+ ((e.width ?? 1) > 0 || !a.fill) && (s = Math.min(s, g(t, n, a.pts, a.close)));
462
+ }
463
+ return s;
464
+ }
465
+ function ge(e, t, n, r, i, a, o) {
466
+ let s = (e, t) => Math.min(e, t), c = (e, t) => Math.max(e, t), l = (e, a) => e >= s(t, r) && e <= c(t, r) && a >= s(n, i) && a <= c(n, i);
467
+ if (e.hit === !1) return !1;
468
+ if (e.k === "text") return l(e.x, e.y);
469
+ if (e.k === "line" && (l(e.x1, e.y1) || l(e.x2, e.y2))) return !0;
470
+ for (let t of me(e, a, o)) for (let e = 0; e < t.pts.length; e += 2) if (l(t.pts[e], t.pts[e + 1])) return !0;
471
+ return !1;
472
+ }
473
+ //#endregion
474
+ //#region src/templates.ts
475
+ function _e(e) {
476
+ if (!e || e.includes("/")) throw RangeError(`template name must be non-empty and contain no "/", got "${e}"`);
477
+ }
478
+ var ve = class {
479
+ store;
480
+ prefix;
481
+ constructor(e, t = "drawings/") {
482
+ this.store = e, this.prefix = t;
483
+ }
484
+ key(e, t) {
485
+ return _e(e), _e(t), `${this.prefix}template/${e}/${t}`;
486
+ }
487
+ async save(e, t) {
488
+ let n = {
489
+ version: 1,
490
+ tool: t.tool,
491
+ name: e,
492
+ style: { ...t.style },
493
+ props: structuredClone(t.props)
494
+ };
495
+ await this.store.save(this.key(t.tool, e), n);
496
+ }
497
+ async load(e, t) {
498
+ let n = await this.store.load(this.key(e, t));
499
+ if (!n) throw Error(`drawings: no template "${t}" for tool "${e}"`);
500
+ if (n.version !== 1 || n.tool !== e) throw Error(`drawings: template "${t}" is not a version 1 template of "${e}"`);
501
+ return n;
502
+ }
503
+ async list(e) {
504
+ let t = `${this.prefix}template/`, n = [];
505
+ for (let r of await this.store.keys()) {
506
+ if (!r.startsWith(t)) continue;
507
+ let [i, a] = r.slice(t.length).split("/");
508
+ i && a && (e === void 0 || i === e) && n.push({
509
+ tool: i,
510
+ name: a
511
+ });
512
+ }
513
+ return n;
514
+ }
515
+ async remove(e, t) {
516
+ await this.store.remove(this.key(e, t));
517
+ }
518
+ async favourites() {
519
+ let e = await this.store.load(`${this.prefix}favourites`);
520
+ if (e === void 0) return [];
521
+ if (!Array.isArray(e) || e.some((e) => typeof e != "string")) throw TypeError("drawings: stored favourites are not a list of tool ids");
522
+ return e;
523
+ }
524
+ async setFavourite(e, t) {
525
+ let n = await this.favourites(), r = t ? n.includes(e) ? n : [...n, e] : n.filter((t) => t !== e);
526
+ return await this.store.save(`${this.prefix}favourites`, r), r;
527
+ }
528
+ }, T = {
529
+ color: "#2962ff",
530
+ width: 1.5,
531
+ dash: "solid",
532
+ fill: null,
533
+ textColor: "#d1d4dc",
534
+ fontSize: 12,
535
+ bold: !1,
536
+ italic: !1,
537
+ text: "",
538
+ extendLeft: !1,
539
+ extendRight: !1
540
+ }, ye = 1, be = 4, xe = {
541
+ mouse: 5,
542
+ pen: 8,
543
+ touch: 14
544
+ }, Se = 16, Ce = 5, we = class {
545
+ options;
546
+ id;
547
+ events = new a();
548
+ loading = !1;
549
+ get restoring() {
550
+ return this.loading;
551
+ }
552
+ templates;
553
+ api = null;
554
+ tools = /* @__PURE__ */ new Map();
555
+ store = new te();
556
+ history = new ae(this.store);
557
+ selected = /* @__PURE__ */ new Set();
558
+ hover = null;
559
+ tool = null;
560
+ creating = null;
561
+ drag = null;
562
+ clipboard = [];
563
+ nextId = 1;
564
+ last = null;
565
+ source;
566
+ intervalMs;
567
+ magnetMode;
568
+ continuous;
569
+ onError;
570
+ reported = /* @__PURE__ */ new Set();
571
+ measureCanvas;
572
+ constructor(e) {
573
+ this.options = e, this.id = e.id ?? "drawings";
574
+ for (let t of e.tools) {
575
+ if (this.tools.has(t.id)) throw Error(`drawings: tool "${t.id}" registered twice`);
576
+ this.tools.set(t.id, t);
577
+ }
578
+ this.source = e.source ?? null, this.intervalMs = e.interval ?? null, this.magnetMode = e.magnet ?? "off", this.continuous = e.continuous ?? !1, this.templates = e.store ? new ve(e.store) : null, this.onError = e.onError ?? ((e, t) => console.error(`alphacharts drawings${t ? ` (${t.tool} ${t.id})` : ""}:`, e));
579
+ }
580
+ install(e) {
581
+ this.api = e;
582
+ }
583
+ uninstall() {
584
+ this.api = null, this.creating = null, this.drag = null;
585
+ }
586
+ dataChanged() {
587
+ this.api?.requestRender();
588
+ }
589
+ viewChanged() {}
590
+ toolDef(e) {
591
+ let t = this.tools.get(e);
592
+ if (!t) throw Error(`drawings: unknown tool "${e}" (registered: ${[...this.tools.keys()].join(", ") || "none"})`);
593
+ return t;
594
+ }
595
+ toolIds() {
596
+ return [...this.tools.keys()];
597
+ }
598
+ setSource(e) {
599
+ this.source = e, this.render();
600
+ }
601
+ setInterval(e) {
602
+ if (e !== null && !(e > 0)) throw RangeError(`drawings: interval must be positive, got ${e}`);
603
+ this.intervalMs = e, this.render();
604
+ }
605
+ setMagnet(e) {
606
+ this.magnetMode = e;
607
+ }
608
+ magnet() {
609
+ return this.magnetMode;
610
+ }
611
+ list() {
612
+ return this.store.list.map(v);
613
+ }
614
+ get(e) {
615
+ let t = this.store.get(e);
616
+ return t ? v(t) : void 0;
617
+ }
618
+ selection() {
619
+ return [...this.selected];
620
+ }
621
+ activeTool() {
622
+ return this.tool;
623
+ }
624
+ get canUndo() {
625
+ return this.history.canUndo;
626
+ }
627
+ get canRedo() {
628
+ return this.history.canRedo;
629
+ }
630
+ newId() {
631
+ let e;
632
+ do
633
+ e = `d${this.nextId++}`;
634
+ while (this.store.get(e));
635
+ return e;
636
+ }
637
+ build(e, t, n) {
638
+ let r = this.toolDef(e.tool), i = r.defaults(), a = {
639
+ id: e.id ?? this.newId(),
640
+ tool: e.tool,
641
+ pane: e.pane ?? 0,
642
+ anchors: t.map((e) => ({
643
+ time: e.time,
644
+ price: e.price
645
+ })),
646
+ style: {
647
+ ...T,
648
+ ...i.style,
649
+ ...e.style
650
+ },
651
+ props: {
652
+ ...v(i.props ?? {}),
653
+ ...v(e.props ?? {})
654
+ },
655
+ locked: e.locked ?? !1,
656
+ hidden: e.hidden ?? !1,
657
+ intervals: e.intervals ?? null
658
+ };
659
+ return r.onCreate && n && r.onCreate(a, this.ctxFor(n)), a;
660
+ }
661
+ validate(e) {
662
+ let t = this.toolDef(e.tool);
663
+ if (typeof e.id != "string" || !e.id) throw TypeError("drawings: a drawing needs a string id");
664
+ if (!Number.isInteger(e.pane) || e.pane < 0) throw RangeError(`drawings: ${e.tool} "${e.id}" has invalid pane ${e.pane}`);
665
+ if (!Array.isArray(e.anchors)) throw TypeError(`drawings: ${e.tool} "${e.id}" anchors must be an array`);
666
+ if (t.variable ? e.anchors.length < t.anchors : e.anchors.length !== t.anchors) throw RangeError(`drawings: ${e.tool} "${e.id}" needs ${t.variable ? "at least " : ""}${t.anchors} anchors, got ${e.anchors.length}`);
667
+ e.anchors.forEach((t, n) => {
668
+ if (typeof t?.time != "number" || typeof t?.price != "number" || !Number.isFinite(t.time) || !Number.isFinite(t.price)) throw TypeError(`drawings: ${e.tool} "${e.id}" anchor ${n} must be {time, price} with finite numbers`);
669
+ });
670
+ for (let t of Object.keys(T)) if (typeof e.style?.[t] != typeof T[t] && (t !== "fill" || e.style?.fill !== null && typeof e.style?.fill != "string")) throw TypeError(`drawings: ${e.tool} "${e.id}" style.${t} has the wrong type`);
671
+ if (e.intervals !== null && (!Array.isArray(e.intervals) || e.intervals.some((e) => !(e > 0)))) throw TypeError(`drawings: ${e.tool} "${e.id}" intervals must be null or positive numbers`);
672
+ if (t.needsSource && !this.source) throw Error(`drawings: ${e.tool} needs a BarSource; pass \`source\` to DrawingsPlugin`);
673
+ if (t.screen && (typeof e.props.fx != "number" || typeof e.props.fy != "number")) throw TypeError(`drawings: ${e.tool} "${e.id}" needs numeric props fx and fy`);
674
+ t.validate?.(e);
675
+ }
676
+ add(e) {
677
+ let t = this.api && (e.pane ?? 0) < this.api.paneCount ? this.api.paneView(e.pane ?? 0) : null, n = this.build(e, e.anchors ?? [], t);
678
+ if (this.store.get(n.id)) throw Error(`drawings: id "${n.id}" is already used`);
679
+ return this.validate(n), this.exec(new y(n, this.store.list.length)), v(n);
680
+ }
681
+ update(e, t) {
682
+ let n = v(this.store.require(e)), r = this.applyPatch(n, t);
683
+ return this.validate(r), this.exec(new b("update", [n], [r])), v(r);
684
+ }
685
+ applyPatch(e, t) {
686
+ let n = v(e);
687
+ return t.anchors && (n.anchors = t.anchors.map((e) => ({
688
+ time: e.time,
689
+ price: e.price
690
+ }))), t.style && (n.style = {
691
+ ...n.style,
692
+ ...t.style
693
+ }), t.props && (n.props = {
694
+ ...n.props,
695
+ ...v(t.props)
696
+ }), t.locked !== void 0 && (n.locked = t.locked), t.hidden !== void 0 && (n.hidden = t.hidden), t.intervals !== void 0 && (n.intervals = t.intervals), n;
697
+ }
698
+ updateMany(e, t) {
699
+ let n = e.map((e) => v(this.store.require(e))), r = n.map((e) => this.applyPatch(e, t));
700
+ r.forEach((e) => this.validate(e)), this.exec(new b("update", n, r));
701
+ }
702
+ remove(e) {
703
+ if (e.length === 0) return;
704
+ let t = e.map((e) => ({
705
+ d: this.store.require(e),
706
+ at: this.store.list.indexOf(this.store.require(e))
707
+ }));
708
+ this.exec(new ne(t));
709
+ }
710
+ clear() {
711
+ this.remove(this.store.list.map((e) => e.id));
712
+ }
713
+ exec(e, t = "run") {
714
+ this.drag && this.cancelDrag();
715
+ let n = (e) => new Map(e.map((e) => [e, this.store.get(e) ? JSON.stringify(this.store.get(e)) : void 0])), r = n(e.ids);
716
+ t === "run" ? this.history.run(e) : t === "undo" ? this.history.undo() : this.history.redo();
717
+ let i = n(e.ids);
718
+ for (let t of e.ids) {
719
+ let e = r.get(t), n = i.get(t);
720
+ e === void 0 && n !== void 0 ? this.events.emit("created", JSON.parse(n)) : e !== void 0 && n === void 0 ? this.events.emit("removed", JSON.parse(e)) : n !== void 0 && n !== e && this.events.emit("changed", JSON.parse(n));
721
+ }
722
+ this.afterMutation();
723
+ }
724
+ afterMutation() {
725
+ let e = !1;
726
+ for (let t of [...this.selected]) this.store.get(t) || (this.selected.delete(t), e = !0);
727
+ this.hover && !this.store.get(this.hover) && (this.hover = null), e && this.events.emit("selected", this.selection()), this.events.emit("history", {
728
+ canUndo: this.history.canUndo,
729
+ canRedo: this.history.canRedo
730
+ }), this.render();
731
+ }
732
+ undo() {
733
+ let e = this.peekUndo();
734
+ return e ? (this.exec(e, "undo"), !0) : !1;
735
+ }
736
+ redo() {
737
+ let e = this.peekRedo();
738
+ return e ? (this.exec(e, "redo"), !0) : !1;
739
+ }
740
+ peekUndo() {
741
+ return this.history.undoStack.at(-1);
742
+ }
743
+ peekRedo() {
744
+ return this.history.redoStack.at(-1);
745
+ }
746
+ select(e) {
747
+ for (let t of e) this.store.require(t);
748
+ if (!(e.length === this.selected.size && e.every((e) => this.selected.has(e)))) {
749
+ this.selected.clear();
750
+ for (let t of e) this.selected.add(t);
751
+ this.events.emit("selected", this.selection()), this.render();
752
+ }
753
+ }
754
+ selectAll() {
755
+ this.select(this.store.list.filter((e) => !e.hidden).map((e) => e.id));
756
+ }
757
+ setTool(e) {
758
+ if (e !== null && this.options.readOnly) throw Error("drawings: a read-only plugin takes no tool");
759
+ e !== null && this.toolDef(e), this.creating = null, this.tool !== e && (this.tool = e, e !== null && this.select([]), this.events.emit("tool", e), this.render());
760
+ }
761
+ anchorAt(e, t, n) {
762
+ if (!this.api) throw Error("drawings: the plugin is not installed on a chart");
763
+ let r = this.api.paneView(e);
764
+ return {
765
+ time: r.xToTime(t),
766
+ price: r.yToPrice(n)
767
+ };
768
+ }
769
+ pixelOf(e, t) {
770
+ if (!this.api) throw Error("drawings: the plugin is not installed on a chart");
771
+ let n = this.api.paneView(e);
772
+ return {
773
+ x: n.timeToX(t.time),
774
+ y: n.priceToY(t.price)
775
+ };
776
+ }
777
+ reorder(e, t) {
778
+ let n = this.store.list.map((e) => e.id), r = t([...n], new Set(e));
779
+ r.every((e, t) => e === n[t]) || this.exec(new re(n, r));
780
+ }
781
+ bringToFront(e = this.selection()) {
782
+ this.reorder(e, (e, t) => [...e.filter((e) => !t.has(e)), ...e.filter((e) => t.has(e))]);
783
+ }
784
+ sendToBack(e = this.selection()) {
785
+ this.reorder(e, (e, t) => [...e.filter((e) => t.has(e)), ...e.filter((e) => !t.has(e))]);
786
+ }
787
+ bringForward(e = this.selection()) {
788
+ this.reorder(e, (e, t) => {
789
+ for (let n = e.length - 2; n >= 0; n--) t.has(e[n]) && !t.has(e[n + 1]) && ([e[n], e[n + 1]] = [e[n + 1], e[n]]);
790
+ return e;
791
+ });
792
+ }
793
+ sendBackward(e = this.selection()) {
794
+ this.reorder(e, (e, t) => {
795
+ for (let n = 1; n < e.length; n++) t.has(e[n]) && !t.has(e[n - 1]) && ([e[n], e[n - 1]] = [e[n - 1], e[n]]);
796
+ return e;
797
+ });
798
+ }
799
+ copy(e = this.selection()) {
800
+ return this.clipboard = e.map((e) => v(this.store.require(e))), v(this.clipboard);
801
+ }
802
+ paste(e) {
803
+ if (this.clipboard.length === 0) return [];
804
+ let t = this.clipboard.find((e) => e.anchors.length > 0)?.anchors[0], n = e && t ? e.time - t.time : 0, r = e && t ? e.price - t.price : 0;
805
+ return this.pasteShifted(n, r);
806
+ }
807
+ duplicate() {
808
+ if (this.selected.size === 0) return [];
809
+ let e = this.barMs();
810
+ return this.copy(), this.pasteShifted(5 * e, 0);
811
+ }
812
+ barMs() {
813
+ let e = this.intervalMs ?? (this.source && this.source.length > 1 ? this.source.interval : null);
814
+ if (e === null) throw Error("drawings: the bar interval is unknown; pass `interval` or a `source` with two bars");
815
+ return e;
816
+ }
817
+ pasteShifted(e, t) {
818
+ let n = [], r = [], i = this.store.list.length;
819
+ for (let a of this.clipboard) {
820
+ let o = v(a);
821
+ o.id = this.newId(), o.locked = !1, o.anchors = o.anchors.map((n) => ({
822
+ time: n.time + e,
823
+ price: n.price + t
824
+ })), this.validate(o), n.push(new y(o, i++)), r.push(o);
825
+ }
826
+ return this.exec(new ie("paste", n)), this.select(r.map((e) => e.id)), v(r);
827
+ }
828
+ async saveTemplate(e, t) {
829
+ if (!this.templates) throw Error("drawings: pass `store` to DrawingsPlugin to keep templates");
830
+ await this.templates.save(t, this.store.require(e));
831
+ }
832
+ async applyTemplate(e, t) {
833
+ if (!this.templates) throw Error("drawings: pass `store` to DrawingsPlugin to keep templates");
834
+ let n = new Set(e.map((e) => this.store.require(e).tool));
835
+ if (n.size !== 1) throw Error("drawings: a template applies to drawings of one tool");
836
+ let r = await this.templates.load([...n][0], t);
837
+ this.updateMany(e, {
838
+ style: r.style,
839
+ props: r.props
840
+ });
841
+ }
842
+ toJSON() {
843
+ return {
844
+ version: 1,
845
+ drawings: this.list()
846
+ };
847
+ }
848
+ validateState(e) {
849
+ this.parseState(e);
850
+ }
851
+ parseState(e) {
852
+ if (typeof e != "object" || !e) throw TypeError("drawings: saved state must be an object");
853
+ let t = e;
854
+ if (typeof t.version != "number" || !Number.isInteger(t.version) || t.version < 1) throw TypeError(`drawings: invalid saved version ${String(t.version)}`);
855
+ if (t.version > 1) throw RangeError(`drawings: saved version ${t.version} is newer than this library understands (1)`);
856
+ if (!Array.isArray(t.drawings)) throw TypeError("drawings: saved state has no drawings array");
857
+ let n = /* @__PURE__ */ new Set();
858
+ return t.drawings.map((e) => {
859
+ let t = v(e);
860
+ if (this.validate(t), n.has(t.id)) throw Error(`drawings: saved state repeats id "${t.id}"`);
861
+ return n.add(t.id), t;
862
+ });
863
+ }
864
+ fromJSON(e) {
865
+ let t = this.parseState(e), n = this.store.list.map(v);
866
+ this.store.clear(), t.forEach((e, t) => this.store.insert(e, t));
867
+ for (let e of t) {
868
+ let t = /^d(\d+)$/.exec(e.id);
869
+ t && (this.nextId = Math.max(this.nextId, Number(t[1]) + 1));
870
+ }
871
+ this.history.clear(), this.selected.clear(), this.creating = null, this.drag = null, this.hover = null, this.loading = !0;
872
+ try {
873
+ n.forEach((e) => this.events.emit("removed", e)), t.forEach((e) => this.events.emit("created", v(e)));
874
+ } finally {
875
+ this.loading = !1;
876
+ }
877
+ this.events.emit("selected", []), this.events.emit("history", {
878
+ canUndo: !1,
879
+ canRedo: !1
880
+ }), this.render();
881
+ }
882
+ render() {
883
+ this.api?.requestRender();
884
+ }
885
+ report(e, t) {
886
+ let n = e instanceof Error ? e : Error(String(e)), r = `${t?.id ?? ""}:${n.message}`;
887
+ this.reported.has(r) || (this.reported.add(r), this.onError(n, t ? v(t) : null));
888
+ }
889
+ measure = (e, t) => {
890
+ this.measureCanvas === void 0 && (this.measureCanvas = typeof document < "u" ? document.createElement("canvas").getContext("2d") : null);
891
+ let n = this.measureCanvas;
892
+ return n ? (n.font = t, n.measureText(e).width) : e.length * parseFloat(t.match(/(\d+(?:\.\d+)?)px/)?.[1] ?? "12") * .6;
893
+ };
894
+ sourceInterval() {
895
+ return this.intervalMs ?? (this.source && this.source.length > 1 ? this.source.interval : null);
896
+ }
897
+ ctxFor(e) {
898
+ return {
899
+ W: e.width,
900
+ H: e.height,
901
+ dpr: e.dpr,
902
+ X: (t) => e.timeToX(t),
903
+ Y: (t) => e.priceToY(t),
904
+ T: (t) => e.xToTime(t),
905
+ P: (t) => e.yToPrice(t),
906
+ fmt: (t) => e.formatPrice(t),
907
+ source: this.source,
908
+ interval: this.sourceInterval()
909
+ };
910
+ }
911
+ visible(e) {
912
+ if (e.hidden) return !1;
913
+ if (e.intervals === null) return !0;
914
+ let t = this.intervalMs;
915
+ return t === null ? (this.report(/* @__PURE__ */ Error("the chart interval is unknown (call setInterval); drawings limited to intervals are shown on every interval"), e), !0) : e.intervals.includes(t);
916
+ }
917
+ shapesOf(e, t) {
918
+ try {
919
+ return this.toolDef(e.tool).shapes(e, t);
920
+ } catch (t) {
921
+ return this.report(t, e), [];
922
+ }
923
+ }
924
+ handlePoints(e, t) {
925
+ let n = this.toolDef(e.tool);
926
+ if (n.noHandles || e.locked) return [];
927
+ if (n.screen) return [{
928
+ x: e.props.fx * t.W,
929
+ y: e.props.fy * t.H
930
+ }];
931
+ try {
932
+ return n.handlePoints ? n.handlePoints(e, t) : e.anchors.map((e) => ({
933
+ x: t.X(e.time),
934
+ y: t.Y(e.price)
935
+ }));
936
+ } catch (t) {
937
+ return this.report(t, e), [];
938
+ }
939
+ }
940
+ tolerance(e) {
941
+ return xe[e ?? this.last?.pointerType ?? "mouse"] ?? xe.mouse;
942
+ }
943
+ hitTest(e, t, n, r = this.tolerance()) {
944
+ if (!this.api) throw Error("drawings: the plugin is not installed on a chart");
945
+ let i = this.api.paneView(e), a = this.ctxFor(i), o = this.store.list;
946
+ for (let i = o.length - 1; i >= 0; i--) {
947
+ let c = o[i];
948
+ if (c.pane !== e || !this.selected.has(c.id) || c.locked) continue;
949
+ let l = this.handlePoints(c, a);
950
+ for (let e = 0; e < l.length; e++) if (s(t, n, l[e].x, l[e].y) <= r + 3) return {
951
+ id: c.id,
952
+ handle: e
953
+ };
954
+ }
955
+ for (let i = o.length - 1; i >= 0; i--) {
956
+ let s = o[i];
957
+ if (s.pane === e && this.visible(s)) {
958
+ for (let e of this.shapesOf(s, a)) if (he(e, t, n, a.W, a.H, s.style, this.measure) <= r) return {
959
+ id: s.id,
960
+ handle: null
961
+ };
962
+ }
963
+ }
964
+ return null;
965
+ }
966
+ snap(e) {
967
+ let t = {
968
+ time: e.time,
969
+ price: e.price
970
+ };
971
+ if (this.magnetMode === "off" || !this.source || this.source.length === 0 || e.pane !== 0 || !this.api) return t;
972
+ let n = this.api.paneView(0), r = this.source.nearest(e.time);
973
+ if (!r) return t;
974
+ let i = n.timeToX(r.time), a = null;
975
+ for (let t of [
976
+ r.open,
977
+ r.high,
978
+ r.low,
979
+ r.close
980
+ ]) {
981
+ let r = Math.abs(n.priceToY(t) - e.y);
982
+ (!a || r < a.d) && (a = {
983
+ price: t,
984
+ d: r
985
+ });
986
+ }
987
+ return !a || this.magnetMode === "weak" && (a.d > 16 || Math.abs(i - e.x) > 16) ? t : {
988
+ time: r.time,
989
+ price: a.price
990
+ };
991
+ }
992
+ drawPane(e, t) {
993
+ let n = this.ctxFor(t), r = [];
994
+ for (let e of this.store.list) e.pane === t.pane && this.visible(e) && r.push({
995
+ d: e,
996
+ shapes: this.shapesOf(e, n)
997
+ });
998
+ let i = [];
999
+ for (let { d: e, shapes: t } of r) for (let n of t) n.k === "text" && n.stack && i.push({
1000
+ s: n,
1001
+ style: e.style
1002
+ });
1003
+ i.length > 1 && le(i, this.measure);
1004
+ for (let { d: t, shapes: i } of r) {
1005
+ let r = this.selected.has(t.id);
1006
+ pe(e, i, t.style, n.W, n.H, { widthBoost: r || t.id === this.hover ? .5 : 0 });
1007
+ }
1008
+ for (let r of this.store.list) if (r.pane === t.pane && this.selected.has(r.id) && this.visible(r)) for (let t of this.handlePoints(r, n)) e.beginPath(), e.arc(t.x, t.y, 4, 0, Math.PI * 2), e.fillStyle = "#ffffff", e.fill(), e.lineWidth = 1.5, e.strokeStyle = r.style.color, e.stroke();
1009
+ let a = this.creating;
1010
+ if (a && a.pane === t.pane) {
1011
+ let t = this.previewDrawing(a);
1012
+ if (t) {
1013
+ e.save(), pe(e, this.shapesOf(t, n), t.style, n.W, n.H), e.restore();
1014
+ for (let r of a.anchors) e.beginPath(), e.arc(n.X(r.time), n.Y(r.price), 3.5, 0, Math.PI * 2), e.fillStyle = t.style.color, e.fill();
1015
+ }
1016
+ }
1017
+ let o = this.drag;
1018
+ o?.kind === "box" && o.pane === t.pane && (e.save(), e.strokeStyle = "#2962ff", e.fillStyle = "rgba(41,98,255,0.12)", e.lineWidth = 1, e.setLineDash([4, 3]), e.fillRect(Math.min(o.x0, o.x1), Math.min(o.y0, o.y1), Math.abs(o.x1 - o.x0), Math.abs(o.y1 - o.y0)), e.strokeRect(Math.min(o.x0, o.x1) + .5, Math.min(o.y0, o.y1) + .5, Math.abs(o.x1 - o.x0), Math.abs(o.y1 - o.y0)), e.restore());
1019
+ }
1020
+ previewDrawing(e) {
1021
+ let t = e.def, n = [...e.anchors];
1022
+ if (t.screen) {
1023
+ if (!e.screenPos) return null;
1024
+ } else {
1025
+ let r = e.pointer ?? n[n.length - 1];
1026
+ if (!r) return null;
1027
+ if (t.gesture === "freehand") {
1028
+ if (n.length < 2) return null;
1029
+ } else if (t.variable) {
1030
+ if (n.push(r), n.length < t.anchors) for (; n.length < t.anchors;) n.push(r);
1031
+ } else for (; n.length < t.anchors;) n.push(r);
1032
+ }
1033
+ let r = this.build({
1034
+ tool: t.id,
1035
+ pane: e.pane,
1036
+ id: "__preview__",
1037
+ ...e.screenPos ? { props: e.screenPos } : {}
1038
+ }, n, null);
1039
+ return this.constrainAll(r), r;
1040
+ }
1041
+ constrainAll(e) {
1042
+ let t = this.toolDef(e.tool);
1043
+ if (t.constrain) for (let n = 0; n < e.anchors.length; n++) t.constrain(e, n);
1044
+ }
1045
+ pointer(e) {
1046
+ if (this.options.readOnly) return !1;
1047
+ switch (this.last = {
1048
+ pane: e.pane,
1049
+ x: e.x,
1050
+ y: e.y,
1051
+ time: e.time,
1052
+ price: e.price,
1053
+ pointerType: e.pointerType
1054
+ }, e.type) {
1055
+ case "down": return this.onDown(e);
1056
+ case "move": return this.onMove(e);
1057
+ case "up": return this.onUp(e);
1058
+ case "click": return this.onClick(e);
1059
+ case "dblclick": return this.onDouble(e);
1060
+ case "leave": return this.hover && (this.hover = null, this.render()), !1;
1061
+ }
1062
+ }
1063
+ onDown(e) {
1064
+ if (this.creating) return !0;
1065
+ if (this.tool) return this.beginCreate(e);
1066
+ let t = this.hitTest(e.pane, e.x, e.y, this.tolerance(e.pointerType));
1067
+ if (!t) return e.shiftKey ? (this.drag = {
1068
+ kind: "box",
1069
+ pane: e.pane,
1070
+ x0: e.x,
1071
+ y0: e.y,
1072
+ x1: e.x,
1073
+ y1: e.y
1074
+ }, !0) : !1;
1075
+ let n = this.store.require(t.id);
1076
+ if (t.handle !== null) return this.drag = {
1077
+ kind: "handle",
1078
+ pane: e.pane,
1079
+ id: n.id,
1080
+ index: t.handle,
1081
+ before: v(n),
1082
+ moved: !1
1083
+ }, !0;
1084
+ let r = null;
1085
+ e.shiftKey ? this.selected.has(n.id) ? r = {
1086
+ id: n.id,
1087
+ shift: !0
1088
+ } : this.select([...this.selected, n.id]) : this.selected.has(n.id) ? this.selected.size > 1 && (r = {
1089
+ id: n.id,
1090
+ shift: !1
1091
+ }) : this.select([n.id]);
1092
+ let i = [...this.selected].map((e) => this.store.require(e)).filter((t) => !t.locked && t.pane === e.pane);
1093
+ return this.drag = {
1094
+ kind: "move",
1095
+ pane: e.pane,
1096
+ start: {
1097
+ x: e.x,
1098
+ y: e.y
1099
+ },
1100
+ before: i.map(v),
1101
+ startAnchors: new Map(i.map((e) => [e.id, v(e.anchors)])),
1102
+ startScreen: new Map(i.filter((e) => this.toolDef(e.tool).screen).map((e) => [e.id, {
1103
+ fx: e.props.fx,
1104
+ fy: e.props.fy
1105
+ }])),
1106
+ moved: !1,
1107
+ clickOnly: r
1108
+ }, !0;
1109
+ }
1110
+ beginCreate(e) {
1111
+ let t = this.toolDef(this.tool), n = this.snap(e), r = this.api.paneView(e.pane);
1112
+ return this.creating = {
1113
+ def: t,
1114
+ pane: e.pane,
1115
+ anchors: t.screen ? [] : [n],
1116
+ pointer: n,
1117
+ fresh: !0,
1118
+ downPx: {
1119
+ x: e.x,
1120
+ y: e.y
1121
+ },
1122
+ lastPx: {
1123
+ x: e.x,
1124
+ y: e.y
1125
+ },
1126
+ screenPos: t.screen ? {
1127
+ fx: e.x / r.width,
1128
+ fy: e.y / r.height
1129
+ } : null
1130
+ }, this.render(), !0;
1131
+ }
1132
+ onMove(e) {
1133
+ let t = this.creating;
1134
+ if (t) return e.pane === t.pane && (t.pointer = this.snap(e), t.screenPos &&= {
1135
+ fx: e.x / this.api.paneView(t.pane).width,
1136
+ fy: e.y / this.api.paneView(t.pane).height
1137
+ }, t.def.gesture === "freehand" && t.fresh && e.buttons & 1 && s(e.x, e.y, t.lastPx.x, t.lastPx.y) >= 3 && (t.anchors.push(t.pointer), t.lastPx = {
1138
+ x: e.x,
1139
+ y: e.y
1140
+ }), this.render()), !0;
1141
+ let n = this.drag;
1142
+ if (n) return n.kind === "box" ? (n.x1 = e.x, n.y1 = e.y) : n.kind === "move" ? this.dragMove(n, e) : this.dragHandle(n, e), this.render(), !0;
1143
+ if (this.tool) return !1;
1144
+ let r = this.hitTest(e.pane, e.x, e.y, this.tolerance(e.pointerType))?.id ?? null;
1145
+ return r !== this.hover && (this.hover = r, this.render()), !1;
1146
+ }
1147
+ dragMove(e, t) {
1148
+ let n = t.x - e.start.x, r = t.y - e.start.y;
1149
+ if (!e.moved && Math.hypot(n, r) < 4) return;
1150
+ e.moved = !0;
1151
+ let i = this.api.paneView(e.pane);
1152
+ for (let t of e.before) {
1153
+ let a = this.store.require(t.id);
1154
+ if (this.toolDef(t.tool).screen) {
1155
+ let o = e.startScreen.get(t.id);
1156
+ a.props.fx = o.fx + n / i.width, a.props.fy = o.fy + r / i.height;
1157
+ } else a.anchors = e.startAnchors.get(t.id).map((e) => ({
1158
+ time: i.xToTime(i.timeToX(e.time) + n),
1159
+ price: i.yToPrice(i.priceToY(e.price) + r)
1160
+ }));
1161
+ }
1162
+ }
1163
+ dragHandle(e, t) {
1164
+ let n = this.store.require(e.id), r = this.toolDef(n.tool);
1165
+ if (r.screen) return;
1166
+ e.moved = !0;
1167
+ let i = this.snap(t);
1168
+ n.anchors[e.index] = {
1169
+ time: i.time,
1170
+ price: i.price
1171
+ }, r.constrain?.(n, e.index);
1172
+ }
1173
+ onUp(e) {
1174
+ let t = this.creating;
1175
+ if (t) return this.upCreate(t, e);
1176
+ let n = this.drag;
1177
+ if (!n) return !1;
1178
+ if (this.drag = null, n.kind === "box") return this.finishBox(n), !0;
1179
+ if (n.kind === "handle") {
1180
+ let e = this.store.require(n.id);
1181
+ if (n.moved && JSON.stringify(e) !== JSON.stringify(n.before)) {
1182
+ try {
1183
+ this.validate(e);
1184
+ } catch (t) {
1185
+ return Object.assign(e, n.before), this.report(t, e), this.render(), !0;
1186
+ }
1187
+ this.history.record(new b("edit", [n.before], [v(e)])), this.events.emit("changed", v(e)), this.events.emit("history", {
1188
+ canUndo: !0,
1189
+ canRedo: !1
1190
+ });
1191
+ }
1192
+ return this.render(), !0;
1193
+ }
1194
+ if (n.moved) {
1195
+ let e = n.before.map((e) => v(this.store.require(e.id)));
1196
+ this.history.record(new b("move", n.before, e)), e.forEach((e) => this.events.emit("changed", e)), this.events.emit("history", {
1197
+ canUndo: !0,
1198
+ canRedo: !1
1199
+ });
1200
+ } else n.clickOnly && (n.clickOnly.shift ? this.select([...this.selected].filter((e) => e !== n.clickOnly.id)) : this.select([n.clickOnly.id]));
1201
+ return this.render(), !0;
1202
+ }
1203
+ finishBox(e) {
1204
+ let t = this.api.paneView(e.pane), n = this.ctxFor(t), r = [];
1205
+ for (let t of this.store.list) t.pane === e.pane && this.visible(t) && this.shapesOf(t, n).some((t) => ge(t, e.x0, e.y0, e.x1, e.y1, n.W, n.H)) && r.push(t.id);
1206
+ this.select(r);
1207
+ }
1208
+ selectInRect(e, t, n, r, i) {
1209
+ if (!this.api) throw Error("drawings: the plugin is not installed on a chart");
1210
+ return this.finishBox({
1211
+ kind: "box",
1212
+ pane: e,
1213
+ x0: t,
1214
+ y0: n,
1215
+ x1: r,
1216
+ y1: i
1217
+ }), this.selection();
1218
+ }
1219
+ upCreate(e, t) {
1220
+ if (t.pane !== e.pane) return !0;
1221
+ let n = this.snap(t);
1222
+ e.pointer = n;
1223
+ let r = e.def;
1224
+ return r.gesture === "single" ? (this.commit(e), !0) : r.gesture === "freehand" ? (e.anchors.length >= 2 ? this.commit(e) : this.cancelCreate(), !0) : (e.fresh ? (e.fresh = !1, s(e.downPx.x, e.downPx.y, t.x, t.y) > 4 && e.anchors.push(n)) : e.anchors.push(n), !r.variable && e.anchors.length >= r.anchors ? this.commit(e) : this.render(), !0);
1225
+ }
1226
+ onClick(e) {
1227
+ return this.creating || this.tool ? !0 : (this.selected.size > 0 && this.select([]), !1);
1228
+ }
1229
+ onDouble(e) {
1230
+ let t = this.creating;
1231
+ if (!t || !t.def.variable) return !1;
1232
+ let n = t.anchors.length;
1233
+ if (n >= 2) {
1234
+ let e = t.anchors[n - 1], r = t.anchors[n - 2], i = this.api.paneView(t.pane);
1235
+ s(i.timeToX(e.time), i.priceToY(e.price), i.timeToX(r.time), i.priceToY(r.price)) <= 4 && t.anchors.pop();
1236
+ }
1237
+ return this.finishVariable(t), !0;
1238
+ }
1239
+ finishVariable(e) {
1240
+ e.anchors.length >= e.def.anchors ? this.commit(e) : this.cancelCreate();
1241
+ }
1242
+ cancelCreate() {
1243
+ this.creating = null, this.render();
1244
+ }
1245
+ commit(e) {
1246
+ this.creating = null;
1247
+ let t = e.def, n = e.anchors;
1248
+ t.gesture === "single" && !t.screen && (n = [e.pointer ?? n[0]]);
1249
+ try {
1250
+ let r = this.api.paneView(e.pane), i = this.build({
1251
+ tool: t.id,
1252
+ pane: e.pane,
1253
+ ...e.screenPos ? { props: e.screenPos } : {}
1254
+ }, n, r);
1255
+ this.constrainAll(i), this.validate(i), this.exec(new y(i, this.store.list.length)), this.continuous || (this.tool = null, this.events.emit("tool", null)), this.select([i.id]);
1256
+ } catch (e) {
1257
+ this.report(e, null), this.render();
1258
+ }
1259
+ }
1260
+ cursor(e, t, n) {
1261
+ if (this.options.readOnly) return null;
1262
+ if (this.tool || this.creating) return "crosshair";
1263
+ if (this.drag) return this.drag.kind === "move" ? "move" : "pointer";
1264
+ if (!this.api) return null;
1265
+ let r = this.hitTest(e, t, n);
1266
+ return r ? r.handle === null ? this.store.require(r.id).locked ? "default" : "move" : "pointer" : null;
1267
+ }
1268
+ key(e) {
1269
+ if (this.options.readOnly) return !1;
1270
+ let t = e.metaKey || e.ctrlKey, n = e.key;
1271
+ if (n === "Escape") return this.drag ? (this.cancelDrag(), !0) : this.creating ? (this.cancelCreate(), !0) : this.tool ? (this.setTool(null), !0) : this.selected.size ? (this.select([]), !0) : !1;
1272
+ if (n === "Enter" && this.creating?.def.variable) return this.finishVariable(this.creating), !0;
1273
+ if (n === "Delete" || n === "Backspace") {
1274
+ let e = [...this.selected].filter((e) => !this.store.require(e).locked);
1275
+ return e.length !== 0 && (this.remove(e), !0);
1276
+ }
1277
+ return t && (n === "z" || n === "Z") ? e.shiftKey ? this.redo() : this.undo() : t && (n === "y" || n === "Y") ? this.redo() : t && (n === "c" || n === "C") ? this.selected.size !== 0 && (this.copy(), !0) : t && (n === "v" || n === "V") ? this.clipboard.length !== 0 && (this.paste(this.last ? {
1278
+ time: this.last.time,
1279
+ price: this.last.price
1280
+ } : void 0), !0) : t && (n === "d" || n === "D") ? this.selected.size !== 0 && (this.duplicate(), !0) : !1;
1281
+ }
1282
+ cancelDrag() {
1283
+ let e = this.drag;
1284
+ if (this.drag = null, !e || e.kind === "box") return this.render();
1285
+ if (e.kind === "handle") Object.assign(this.store.require(e.id), v(e.before));
1286
+ else for (let t of e.before) Object.assign(this.store.require(t.id), v(t));
1287
+ this.render();
1288
+ }
1289
+ }, Te = class e {
1290
+ t = [];
1291
+ o = [];
1292
+ h = [];
1293
+ l = [];
1294
+ c = [];
1295
+ v = [];
1296
+ ver = 0;
1297
+ cachedInterval = 0;
1298
+ constructor(e) {
1299
+ e && this.setData(e);
1300
+ }
1301
+ get version() {
1302
+ return this.ver;
1303
+ }
1304
+ get length() {
1305
+ return this.t.length;
1306
+ }
1307
+ setData(e) {
1308
+ let t = e.time.length;
1309
+ for (let n of [
1310
+ "open",
1311
+ "high",
1312
+ "low",
1313
+ "close"
1314
+ ]) if (e[n].length !== t) throw RangeError(`ArrayBarSource: ${n} has ${e[n].length} rows, time has ${t}`);
1315
+ if (e.volume && e.volume.length !== t) throw RangeError(`ArrayBarSource: volume has ${e.volume.length} rows, time has ${t}`);
1316
+ for (let n = 1; n < t; n++) if (!(e.time[n] > e.time[n - 1])) throw RangeError(`ArrayBarSource: times must be strictly increasing (row ${n})`);
1317
+ this.t = Array.from(e.time), this.o = Array.from(e.open), this.h = Array.from(e.high), this.l = Array.from(e.low), this.c = Array.from(e.close), this.v = e.volume ? Array.from(e.volume) : Array(t).fill(0), this.touch();
1318
+ }
1319
+ update(e) {
1320
+ let t = this.t.length;
1321
+ if (t > 0 && e.time < this.t[t - 1]) throw RangeError(`ArrayBarSource.update: time ${e.time} is before the last bar`);
1322
+ t > 0 && e.time === this.t[t - 1] ? (this.o[t - 1] = e.open, this.h[t - 1] = e.high, this.l[t - 1] = e.low, this.c[t - 1] = e.close, this.v[t - 1] = e.volume) : (this.t.push(e.time), this.o.push(e.open), this.h.push(e.high), this.l.push(e.low), this.c.push(e.close), this.v.push(e.volume)), this.touch();
1323
+ }
1324
+ prepend(t) {
1325
+ let n = t.time.length;
1326
+ if (n === 0) return;
1327
+ if (this.t.length && !(t.time[n - 1] < this.t[0])) throw RangeError("ArrayBarSource.prepend: bars must all be earlier than the first bar");
1328
+ let r = new e(t);
1329
+ this.t = [...r.t, ...this.t], this.o = [...r.o, ...this.o], this.h = [...r.h, ...this.h], this.l = [...r.l, ...this.l], this.c = [...r.c, ...this.c], this.v = [...r.v, ...this.v], this.touch();
1330
+ }
1331
+ touch() {
1332
+ this.ver++, this.cachedInterval = 0;
1333
+ }
1334
+ at(e) {
1335
+ if (!(e >= 0 && e < this.t.length) || !Number.isInteger(e)) throw RangeError(`ArrayBarSource.at: index ${e} outside 0..${this.t.length - 1}`);
1336
+ return {
1337
+ time: this.t[e],
1338
+ open: this.o[e],
1339
+ high: this.h[e],
1340
+ low: this.l[e],
1341
+ close: this.c[e],
1342
+ volume: this.v[e]
1343
+ };
1344
+ }
1345
+ lower(e) {
1346
+ let t = 0, n = this.t.length;
1347
+ for (; t < n;) {
1348
+ let r = t + n >> 1;
1349
+ this.t[r] < e ? t = r + 1 : n = r;
1350
+ }
1351
+ return t;
1352
+ }
1353
+ nearest(e) {
1354
+ let t = this.t.length;
1355
+ if (t === 0) return;
1356
+ let n = this.lower(e);
1357
+ return n === 0 ? this.at(0) : n === t ? this.at(t - 1) : e - this.t[n - 1] <= this.t[n] - e ? this.at(n - 1) : this.at(n);
1358
+ }
1359
+ get interval() {
1360
+ if (this.cachedInterval > 0) return this.cachedInterval;
1361
+ let e = this.t.length;
1362
+ if (e < 2) throw RangeError("ArrayBarSource.interval: needs at least two bars");
1363
+ let t = [];
1364
+ for (let n = e - 1; n > 0 && t.length < 15; n--) t.push(this.t[n] - this.t[n - 1]);
1365
+ return t.sort((e, t) => e - t), this.cachedInterval = t[t.length >> 1];
1366
+ }
1367
+ logical(e) {
1368
+ let t = this.t.length;
1369
+ if (t === 0) throw RangeError("ArrayBarSource.logical: no bars");
1370
+ if (t === 1) return 0;
1371
+ if (e <= this.t[0]) return (e - this.t[0]) / this.interval;
1372
+ if (e >= this.t[t - 1]) return t - 1 + (e - this.t[t - 1]) / this.interval;
1373
+ let n = this.lower(e), r = this.t[n];
1374
+ if (r === e) return n;
1375
+ let i = this.t[n - 1];
1376
+ return n - 1 + (e - i) / (r - i);
1377
+ }
1378
+ timeAtLogical(e) {
1379
+ let t = this.t.length;
1380
+ if (t === 0) throw RangeError("ArrayBarSource.timeAtLogical: no bars");
1381
+ if (e <= 0) return this.t[0] + e * this.interval;
1382
+ if (e >= t - 1) return this.t[t - 1] + (e - (t - 1)) * this.interval;
1383
+ let n = Math.floor(e);
1384
+ return this.t[n] + (e - n) * (this.t[n + 1] - this.t[n]);
1385
+ }
1386
+ range(e, t) {
1387
+ let n = this.lower(e), r = this.lower(t);
1388
+ return r < this.t.length && this.t[r] === t && r++, [n, Math.max(n, r)];
1389
+ }
1390
+ };
1391
+ //#endregion
1392
+ //#region src/tools/util.ts
1393
+ function E(e, t) {
1394
+ let n = e.anchors[t];
1395
+ if (!n) throw Error(`drawings: ${e.tool} "${e.id}" has no anchor ${t} (has ${e.anchors.length})`);
1396
+ return n;
1397
+ }
1398
+ var D = (e, t) => ({
1399
+ x: e.X(t.time),
1400
+ y: e.Y(t.price)
1401
+ }), O = (e, t) => t.anchors.map((t) => D(e, t));
1402
+ function Ee(e, t) {
1403
+ if (!(t in e.props)) throw Error(`drawings: ${e.tool} "${e.id}" is missing prop "${t}"`);
1404
+ return e.props[t];
1405
+ }
1406
+ function k(e) {
1407
+ let t = Ee(e, "levels");
1408
+ if (!Array.isArray(t) || t.some((e) => typeof e != "number" || !Number.isFinite(e))) throw TypeError(`drawings: ${e.tool} "${e.id}" prop "levels" must be an array of finite numbers`);
1409
+ return t;
1410
+ }
1411
+ function A(e, t, n = {}) {
1412
+ return {
1413
+ k: "line",
1414
+ x1: e.x,
1415
+ y1: e.y,
1416
+ x2: t.x,
1417
+ y2: t.y,
1418
+ ...n
1419
+ };
1420
+ }
1421
+ function j(e, t = {}) {
1422
+ let n = [];
1423
+ for (let t of e) n.push(t.x, t.y);
1424
+ return {
1425
+ k: "poly",
1426
+ pts: n,
1427
+ ...t
1428
+ };
1429
+ }
1430
+ function M(e, t) {
1431
+ return j(e, {
1432
+ close: !0,
1433
+ fill: t,
1434
+ width: 0,
1435
+ hit: !1
1436
+ });
1437
+ }
1438
+ function N(e, t, n, r = {}) {
1439
+ return {
1440
+ k: "text",
1441
+ x: e,
1442
+ y: t,
1443
+ text: n,
1444
+ ...r
1445
+ };
1446
+ }
1447
+ function P(e, t, n, r) {
1448
+ let i = Math.atan2(t.y - e.y, t.x - e.x), a = .45;
1449
+ return j([
1450
+ t,
1451
+ {
1452
+ x: t.x - n * Math.cos(i - a),
1453
+ y: t.y - n * Math.sin(i - a)
1454
+ },
1455
+ {
1456
+ x: t.x - n * Math.cos(i + a),
1457
+ y: t.y - n * Math.sin(i + a)
1458
+ }
1459
+ ], {
1460
+ close: !0,
1461
+ fill: r,
1462
+ color: r,
1463
+ width: 0,
1464
+ hit: !1
1465
+ });
1466
+ }
1467
+ function De(e, t, n) {
1468
+ let r = t.x <= n.x;
1469
+ return {
1470
+ extA: r ? e.extendLeft : e.extendRight,
1471
+ extB: r ? e.extendRight : e.extendLeft
1472
+ };
1473
+ }
1474
+ var Oe = (e, t, n) => ({
1475
+ x: e.x + (t.x - e.x) * n,
1476
+ y: e.y + (t.y - e.y) * n
1477
+ }), F = (e, t) => Oe(e, t, .5);
1478
+ function ke(e, t = .15) {
1479
+ return e.fill ?? S(e.color, t);
1480
+ }
1481
+ function I(e) {
1482
+ if (!Number.isFinite(e)) throw RangeError(`fmtTime: ${e}`);
1483
+ return new Date(e).toISOString().slice(0, 16).replace("T", " ");
1484
+ }
1485
+ function Ae(e) {
1486
+ let t = Math.round(Math.abs(e) / 1e3);
1487
+ if (t < 60) return `${t}s`;
1488
+ let n = Math.floor(t / 86400), r = Math.floor(t % 86400 / 3600), i = Math.floor(t % 3600 / 60);
1489
+ return [
1490
+ n ? `${n}d` : "",
1491
+ r ? `${r}h` : "",
1492
+ i ? `${i}m` : ""
1493
+ ].filter(Boolean).join(" ");
1494
+ }
1495
+ function L(e, t, n) {
1496
+ let r = t.price - e.price;
1497
+ return {
1498
+ dPrice: r,
1499
+ pct: e.price === 0 ? null : r / Math.abs(e.price) * 100,
1500
+ bars: n && n.length > 0 ? n.logical(t.time) - n.logical(e.time) : null,
1501
+ dTime: t.time - e.time
1502
+ };
1503
+ }
1504
+ var je = (e) => e < 0 ? "-" : e > 0 ? "+" : "";
1505
+ function Me(e) {
1506
+ let t = Math.round(e);
1507
+ return Math.abs(e - t) < 1e-9 ? `${t}` : e.toFixed(1);
1508
+ }
1509
+ function Ne(e, t) {
1510
+ let n = e.pct === null ? "" : ` (${je(e.pct)}${Math.abs(e.pct).toFixed(2)}%)`, r = [`${je(e.dPrice)}${t.fmt(Math.abs(e.dPrice))}${n}`], i = [e.bars === null ? "" : `${Me(e.bars)} bars`, Ae(e.dTime)].filter(Boolean).join(", ");
1511
+ return r.push(i), r;
1512
+ }
1513
+ function R(e, t) {
1514
+ return t === 0 ? null : e / t;
1515
+ }
1516
+ function Pe(e) {
1517
+ return e === null ? "n/a" : (Math.round(e * 1e3) / 1e3).toString();
1518
+ }
1519
+ var Fe = {
1520
+ 0: "#787b86",
1521
+ "0.236": "#f23645",
1522
+ "0.382": "#ff9800",
1523
+ "0.5": "#4caf50",
1524
+ "0.618": "#089981",
1525
+ "0.786": "#00bcd4",
1526
+ 1: "#787b86",
1527
+ "1.272": "#9c27b0",
1528
+ "1.618": "#2962ff",
1529
+ 2: "#e91e63",
1530
+ "2.618": "#f23645",
1531
+ "3.618": "#9c27b0",
1532
+ "4.236": "#e91e63"
1533
+ }, z = (e) => Fe[String(e)] ?? "#787b86", Ie = [
1534
+ 0,
1535
+ .236,
1536
+ .382,
1537
+ .5,
1538
+ .618,
1539
+ .786,
1540
+ 1,
1541
+ 1.618,
1542
+ 2.618,
1543
+ 3.618,
1544
+ 4.236
1545
+ ], Le = [
1546
+ 0,
1547
+ .236,
1548
+ .382,
1549
+ .5,
1550
+ .618,
1551
+ .786,
1552
+ 1
1553
+ ];
1554
+ function B(e) {
1555
+ return e;
1556
+ }
1557
+ function V(e, t, n) {
1558
+ if (E(e, t).time === E(e, n).time) throw RangeError(`drawings: ${e.tool} "${e.id}" needs anchors ${t} and ${n} at different times`);
1559
+ }
1560
+ function H(e) {
1561
+ e.anchors.forEach((t, n) => {
1562
+ if (!Number.isFinite(t.time) || !Number.isFinite(t.price)) throw TypeError(`drawings: ${e.tool} "${e.id}" anchor ${n} is not finite (${t.time}, ${t.price})`);
1563
+ });
1564
+ }
1565
+ //#endregion
1566
+ //#region src/tools/annotations.ts
1567
+ var U = {
1568
+ border: null,
1569
+ pad: 5
1570
+ };
1571
+ function W(e, t) {
1572
+ return e.style.text || t;
1573
+ }
1574
+ function Re(e, t) {
1575
+ let n = e.props.fx, r = e.props.fy;
1576
+ if (typeof n != "number" || typeof r != "number" || !Number.isFinite(n) || !Number.isFinite(r)) throw TypeError(`drawings: ${e.tool} "${e.id}" needs numeric props fx and fy`);
1577
+ return {
1578
+ x: n * t.W,
1579
+ y: r * t.H
1580
+ };
1581
+ }
1582
+ var ze = B({
1583
+ id: "text",
1584
+ label: "Text",
1585
+ family: "annotations",
1586
+ gesture: "single",
1587
+ anchors: 1,
1588
+ defaults: () => ({ style: { text: "Text" } }),
1589
+ validate: H,
1590
+ shapes(e, t) {
1591
+ let n = D(t, E(e, 0));
1592
+ return [N(n.x, n.y, W(e, "Text"), {
1593
+ align: "left",
1594
+ base: "middle",
1595
+ textColor: e.style.color
1596
+ })];
1597
+ }
1598
+ }), Be = B({
1599
+ id: "anchoredText",
1600
+ label: "Anchored text",
1601
+ family: "annotations",
1602
+ gesture: "single",
1603
+ anchors: 0,
1604
+ screen: !0,
1605
+ defaults: () => ({
1606
+ style: { text: "Text" },
1607
+ props: {
1608
+ fx: .5,
1609
+ fy: .5
1610
+ }
1611
+ }),
1612
+ shapes(e, t) {
1613
+ let n = Re(e, t);
1614
+ return [N(n.x, n.y, W(e, "Text"), {
1615
+ align: "left",
1616
+ base: "middle",
1617
+ textColor: e.style.color
1618
+ })];
1619
+ }
1620
+ });
1621
+ function Ve(e, t) {
1622
+ return [
1623
+ A(t, {
1624
+ x: t.x + 14,
1625
+ y: t.y - 14
1626
+ }, { width: 1 }),
1627
+ {
1628
+ k: "ellipse",
1629
+ cx: t.x,
1630
+ cy: t.y,
1631
+ rx: 3,
1632
+ ry: 3,
1633
+ fill: e.style.color,
1634
+ width: 1
1635
+ },
1636
+ N(t.x + 14, t.y - 14, W(e, "Note"), {
1637
+ align: "left",
1638
+ base: "bottom",
1639
+ bg: S(e.style.color, .9),
1640
+ textColor: "#ffffff",
1641
+ ...U
1642
+ })
1643
+ ];
1644
+ }
1645
+ var He = B({
1646
+ id: "note",
1647
+ label: "Note",
1648
+ family: "annotations",
1649
+ gesture: "single",
1650
+ anchors: 1,
1651
+ defaults: () => ({ style: { text: "Note" } }),
1652
+ validate: H,
1653
+ shapes: (e, t) => Ve(e, D(t, E(e, 0)))
1654
+ }), Ue = B({
1655
+ id: "anchoredNote",
1656
+ label: "Anchored note",
1657
+ family: "annotations",
1658
+ gesture: "single",
1659
+ anchors: 0,
1660
+ screen: !0,
1661
+ defaults: () => ({
1662
+ style: { text: "Note" },
1663
+ props: {
1664
+ fx: .5,
1665
+ fy: .5
1666
+ }
1667
+ }),
1668
+ shapes: (e, t) => Ve(e, Re(e, t))
1669
+ }), We = B({
1670
+ id: "callout",
1671
+ label: "Callout",
1672
+ family: "annotations",
1673
+ gesture: "drag",
1674
+ anchors: 2,
1675
+ defaults: () => ({ style: { text: "Callout" } }),
1676
+ validate: H,
1677
+ shapes(e, t) {
1678
+ let [n, r] = O(t, e);
1679
+ return [
1680
+ A(r, n, { width: 1 }),
1681
+ {
1682
+ k: "ellipse",
1683
+ cx: n.x,
1684
+ cy: n.y,
1685
+ rx: 3,
1686
+ ry: 3,
1687
+ fill: e.style.color,
1688
+ width: 1
1689
+ },
1690
+ N(r.x, r.y, W(e, "Callout"), {
1691
+ align: "center",
1692
+ base: "middle",
1693
+ bg: S(e.style.color, .9),
1694
+ textColor: "#ffffff",
1695
+ ...U
1696
+ })
1697
+ ];
1698
+ }
1699
+ }), Ge = B({
1700
+ id: "comment",
1701
+ label: "Comment",
1702
+ family: "annotations",
1703
+ gesture: "single",
1704
+ anchors: 1,
1705
+ defaults: () => ({ style: { text: "Comment" } }),
1706
+ validate: H,
1707
+ shapes(e, t) {
1708
+ let n = D(t, E(e, 0));
1709
+ return [j([
1710
+ n,
1711
+ {
1712
+ x: n.x - 6,
1713
+ y: n.y - 14
1714
+ },
1715
+ {
1716
+ x: n.x + 6,
1717
+ y: n.y - 14
1718
+ }
1719
+ ], {
1720
+ close: !0,
1721
+ fill: S(e.style.color, .9),
1722
+ width: 0,
1723
+ hit: !1
1724
+ }), N(n.x, n.y - 14, W(e, "Comment"), {
1725
+ align: "center",
1726
+ base: "bottom",
1727
+ bg: S(e.style.color, .9),
1728
+ textColor: "#ffffff",
1729
+ ...U
1730
+ })];
1731
+ }
1732
+ }), Ke = B({
1733
+ id: "priceLabel",
1734
+ label: "Price label",
1735
+ family: "annotations",
1736
+ gesture: "single",
1737
+ anchors: 1,
1738
+ defaults: () => ({}),
1739
+ validate: H,
1740
+ shapes(e, t) {
1741
+ let n = D(t, E(e, 0)), r = `${e.style.text ? e.style.text + " " : ""}${t.fmt(E(e, 0).price)}`;
1742
+ return [j([
1743
+ n,
1744
+ {
1745
+ x: n.x + 8,
1746
+ y: n.y - 9
1747
+ },
1748
+ {
1749
+ x: n.x + 8,
1750
+ y: n.y + 9
1751
+ }
1752
+ ], {
1753
+ close: !0,
1754
+ fill: e.style.color,
1755
+ width: 0,
1756
+ hit: !1
1757
+ }), N(n.x + 8, n.y, r, {
1758
+ align: "left",
1759
+ base: "middle",
1760
+ bg: e.style.color,
1761
+ textColor: "#ffffff",
1762
+ ...U
1763
+ })];
1764
+ }
1765
+ }), qe = B({
1766
+ id: "priceNote",
1767
+ label: "Price note",
1768
+ family: "annotations",
1769
+ gesture: "drag",
1770
+ anchors: 2,
1771
+ defaults: () => ({}),
1772
+ validate: H,
1773
+ shapes(e, t) {
1774
+ let n = D(t, E(e, 0)), r = D(t, E(e, 1)), i = `${e.style.text ? e.style.text + " " : ""}${t.fmt(E(e, 0).price)}`;
1775
+ return [
1776
+ A(n, {
1777
+ x: r.x,
1778
+ y: n.y
1779
+ }, {
1780
+ dash: "dashed",
1781
+ width: 1
1782
+ }),
1783
+ A({
1784
+ x: r.x,
1785
+ y: n.y
1786
+ }, r, { width: 1 }),
1787
+ {
1788
+ k: "ellipse",
1789
+ cx: n.x,
1790
+ cy: n.y,
1791
+ rx: 3,
1792
+ ry: 3,
1793
+ fill: e.style.color,
1794
+ width: 1
1795
+ },
1796
+ N(r.x, r.y, i, {
1797
+ align: "center",
1798
+ base: "middle",
1799
+ bg: e.style.color,
1800
+ textColor: "#ffffff",
1801
+ ...U
1802
+ })
1803
+ ];
1804
+ }
1805
+ }), Je = B({
1806
+ id: "signpost",
1807
+ label: "Signpost",
1808
+ family: "annotations",
1809
+ gesture: "single",
1810
+ anchors: 1,
1811
+ defaults: () => ({ style: { text: "Sign" } }),
1812
+ validate: H,
1813
+ shapes(e, t) {
1814
+ let n = D(t, E(e, 0)), r = {
1815
+ x: n.x,
1816
+ y: n.y - 44
1817
+ };
1818
+ return [
1819
+ A(n, r),
1820
+ {
1821
+ k: "ellipse",
1822
+ cx: n.x,
1823
+ cy: n.y,
1824
+ rx: 3,
1825
+ ry: 3,
1826
+ fill: e.style.color,
1827
+ width: 1
1828
+ },
1829
+ N(r.x, r.y, W(e, "Sign"), {
1830
+ align: "left",
1831
+ base: "bottom",
1832
+ bg: e.style.color,
1833
+ textColor: "#ffffff",
1834
+ ...U
1835
+ })
1836
+ ];
1837
+ }
1838
+ }), Ye = B({
1839
+ id: "flagMark",
1840
+ label: "Flag mark",
1841
+ family: "annotations",
1842
+ gesture: "single",
1843
+ anchors: 1,
1844
+ defaults: () => ({}),
1845
+ validate: H,
1846
+ shapes(e, t) {
1847
+ let n = D(t, E(e, 0));
1848
+ return [A(n, {
1849
+ x: n.x,
1850
+ y: n.y - 28
1851
+ }), j([
1852
+ {
1853
+ x: n.x,
1854
+ y: n.y - 28
1855
+ },
1856
+ {
1857
+ x: n.x + 16,
1858
+ y: n.y - 22
1859
+ },
1860
+ {
1861
+ x: n.x,
1862
+ y: n.y - 16
1863
+ }
1864
+ ], {
1865
+ close: !0,
1866
+ fill: e.style.color
1867
+ })];
1868
+ }
1869
+ }), Xe = B({
1870
+ id: "arrow",
1871
+ label: "Arrow",
1872
+ family: "annotations",
1873
+ gesture: "drag",
1874
+ anchors: 2,
1875
+ defaults: () => ({}),
1876
+ validate: H,
1877
+ shapes(e, t) {
1878
+ let [n, r] = O(t, e);
1879
+ return [A(n, r), P(n, r, 6 + e.style.width * 2, e.style.color)];
1880
+ }
1881
+ }), Ze = B({
1882
+ id: "arrowMarker",
1883
+ label: "Arrow marker",
1884
+ family: "annotations",
1885
+ gesture: "drag",
1886
+ anchors: 2,
1887
+ defaults: () => ({ style: { fill: "#2962ff" } }),
1888
+ validate: H,
1889
+ shapes(e, t) {
1890
+ let [n, r] = O(t, e), i = Math.hypot(r.x - n.x, r.y - n.y);
1891
+ if (i === 0) return [A(n, r)];
1892
+ let a = (r.x - n.x) / i, o = (r.y - n.y) / i, s = -o, c = a, l = Math.min(i * .45, 20), u = (e, t) => ({
1893
+ x: n.x + a * e + s * t,
1894
+ y: n.y + o * e + c * t
1895
+ });
1896
+ return [j([
1897
+ u(0, 4),
1898
+ u(i - l, 4),
1899
+ u(i - l, 10),
1900
+ u(i, 0),
1901
+ u(i - l, -10),
1902
+ u(i - l, -4),
1903
+ u(0, -4)
1904
+ ], {
1905
+ close: !0,
1906
+ fill: e.style.fill ?? e.style.color
1907
+ })];
1908
+ }
1909
+ });
1910
+ function Qe(e, t, n) {
1911
+ let r = n ? 1 : -1;
1912
+ return [j([
1913
+ t,
1914
+ {
1915
+ x: t.x - 9,
1916
+ y: t.y + r * 11
1917
+ },
1918
+ {
1919
+ x: t.x - 4,
1920
+ y: t.y + r * 11
1921
+ },
1922
+ {
1923
+ x: t.x - 4,
1924
+ y: t.y + r * 28
1925
+ },
1926
+ {
1927
+ x: t.x + 4,
1928
+ y: t.y + r * 28
1929
+ },
1930
+ {
1931
+ x: t.x + 4,
1932
+ y: t.y + r * 11
1933
+ },
1934
+ {
1935
+ x: t.x + 9,
1936
+ y: t.y + r * 11
1937
+ }
1938
+ ], {
1939
+ close: !0,
1940
+ fill: e.style.color,
1941
+ width: 1
1942
+ })];
1943
+ }
1944
+ var $e = B({
1945
+ id: "arrowMarkUp",
1946
+ label: "Arrow mark up",
1947
+ family: "annotations",
1948
+ gesture: "single",
1949
+ anchors: 1,
1950
+ defaults: () => ({ style: { color: "#26a69a" } }),
1951
+ validate: H,
1952
+ shapes: (e, t) => Qe(e, D(t, E(e, 0)), !0)
1953
+ }), et = B({
1954
+ id: "arrowMarkDown",
1955
+ label: "Arrow mark down",
1956
+ family: "annotations",
1957
+ gesture: "single",
1958
+ anchors: 1,
1959
+ defaults: () => ({ style: { color: "#ef5350" } }),
1960
+ validate: H,
1961
+ shapes: (e, t) => Qe(e, D(t, E(e, 0)), !1)
1962
+ }), tt = [
1963
+ ze,
1964
+ Be,
1965
+ He,
1966
+ Ue,
1967
+ We,
1968
+ Ge,
1969
+ Ke,
1970
+ qe,
1971
+ Je,
1972
+ Ye,
1973
+ Xe,
1974
+ Ze,
1975
+ $e,
1976
+ et
1977
+ ], nt = (e, t, n) => e.y + (t.y - e.y) * (n - e.x) / (t.x - e.x);
1978
+ function rt(e, t, n, r) {
1979
+ let i = Math.min(t.x, n.x), a = Math.max(t.x, n.x);
1980
+ return [e.style.extendLeft ? -10 : i, e.style.extendRight ? r.W + 10 : a];
1981
+ }
1982
+ var it = B({
1983
+ id: "parallelChannel",
1984
+ label: "Parallel channel",
1985
+ family: "channels",
1986
+ gesture: "clicks",
1987
+ anchors: 3,
1988
+ defaults: () => ({
1989
+ style: { fill: null },
1990
+ props: { midline: !0 }
1991
+ }),
1992
+ validate(e) {
1993
+ H(e), V(e, 0, 1);
1994
+ },
1995
+ shapes(e, t) {
1996
+ let [n, r, i] = O(t, e), a = i.y - nt(n, r, i.x), [o, s] = rt(e, n, r, t), c = (e) => [{
1997
+ x: o,
1998
+ y: nt(n, r, o) + e
1999
+ }, {
2000
+ x: s,
2001
+ y: nt(n, r, s) + e
2002
+ }], [l, u] = c(0), [d, f] = c(a), p = [
2003
+ M([
2004
+ l,
2005
+ u,
2006
+ f,
2007
+ d
2008
+ ], ke(e.style, .12)),
2009
+ A(l, u),
2010
+ A(d, f)
2011
+ ];
2012
+ if (e.props.midline !== !1) {
2013
+ let [t, n] = c(a / 2);
2014
+ p.push(A(t, n, {
2015
+ dash: "dashed",
2016
+ width: Math.max(1, e.style.width * .66)
2017
+ }));
2018
+ }
2019
+ return p;
2020
+ }
2021
+ });
2022
+ function at(e) {
2023
+ let t = e.length;
2024
+ if (t < 2) throw RangeError(`regression: needs at least 2 values, got ${t}`);
2025
+ let n = (t - 1) / 2, r = 0;
2026
+ for (let t of e) r += t;
2027
+ r /= t;
2028
+ let i = 0, a = 0;
2029
+ for (let o = 0; o < t; o++) i += (o - n) * (e[o] - r), a += (o - n) * (o - n);
2030
+ let o = i / a, s = r - o * n, c = 0;
2031
+ for (let n = 0; n < t; n++) {
2032
+ let t = e[n] - (s + o * n);
2033
+ c += t * t;
2034
+ }
2035
+ return {
2036
+ slope: o,
2037
+ intercept: s,
2038
+ sigma: Math.sqrt(c / t),
2039
+ n: t
2040
+ };
2041
+ }
2042
+ function ot(e, t, n) {
2043
+ let [r, i] = e.range(Math.min(t, n), Math.max(t, n));
2044
+ if (i - r < 2) throw RangeError(`regression channel: only ${i - r} bar(s) between the anchors`);
2045
+ let a = [];
2046
+ for (let t = r; t < i; t++) a.push(e.at(t).close);
2047
+ return {
2048
+ reg: at(a),
2049
+ lo: r,
2050
+ hi: i
2051
+ };
2052
+ }
2053
+ var st = B({
2054
+ id: "regressionTrendChannel",
2055
+ label: "Regression trend channel",
2056
+ family: "channels",
2057
+ gesture: "drag",
2058
+ anchors: 2,
2059
+ needsSource: !0,
2060
+ defaults: () => ({ props: { deviations: 2 } }),
2061
+ validate(e) {
2062
+ H(e), V(e, 0, 1);
2063
+ let t = e.props.deviations;
2064
+ if (typeof t != "number" || !(t > 0)) throw RangeError(`drawings: regressionTrendChannel "${e.id}" prop "deviations" must be > 0`);
2065
+ },
2066
+ shapes(e, t) {
2067
+ if (!t.source) throw Error("regressionTrendChannel needs a BarSource");
2068
+ let { reg: n, lo: r, hi: i } = ot(t.source, E(e, 0).time, E(e, 1).time), a = e.props.deviations, o = t.source.at(r).time, s = t.source.at(i - 1).time, c = (e, r) => ({
2069
+ x: 0,
2070
+ y: t.Y(n.intercept + n.slope * e + r * n.sigma)
2071
+ }), l = t.X(o), u = t.X(s), d = (e) => [{
2072
+ x: l,
2073
+ y: c(0, e).y
2074
+ }, {
2075
+ x: u,
2076
+ y: c(i - r - 1, e).y
2077
+ }], [f, p] = d(a), [m, h] = d(0), [g, _] = d(-a);
2078
+ return [
2079
+ M([
2080
+ f,
2081
+ p,
2082
+ _,
2083
+ g
2084
+ ], ke(e.style, .1)),
2085
+ A(f, p),
2086
+ A(g, _),
2087
+ A(m, h, { dash: "dashed" })
2088
+ ];
2089
+ }
2090
+ }), ct = B({
2091
+ id: "flatTopBottom",
2092
+ label: "Flat top/bottom",
2093
+ family: "channels",
2094
+ gesture: "clicks",
2095
+ anchors: 3,
2096
+ defaults: () => ({}),
2097
+ validate(e) {
2098
+ H(e), V(e, 0, 1);
2099
+ },
2100
+ shapes(e, t) {
2101
+ let [n, r, i] = O(t, e), a = i.y;
2102
+ return [
2103
+ M([
2104
+ n,
2105
+ r,
2106
+ {
2107
+ x: r.x,
2108
+ y: a
2109
+ },
2110
+ {
2111
+ x: n.x,
2112
+ y: a
2113
+ }
2114
+ ], ke(e.style, .12)),
2115
+ A(n, r),
2116
+ A({
2117
+ x: n.x,
2118
+ y: a
2119
+ }, {
2120
+ x: r.x,
2121
+ y: a
2122
+ })
2123
+ ];
2124
+ }
2125
+ }), lt = B({
2126
+ id: "disjointChannel",
2127
+ label: "Disjoint channel",
2128
+ family: "channels",
2129
+ gesture: "clicks",
2130
+ anchors: 4,
2131
+ defaults: () => ({}),
2132
+ validate(e) {
2133
+ H(e), V(e, 0, 1);
2134
+ },
2135
+ shapes(e, t) {
2136
+ let [n, r, i, a] = O(t, e);
2137
+ return [
2138
+ M([
2139
+ n,
2140
+ r,
2141
+ a,
2142
+ i
2143
+ ], ke(e.style, .12)),
2144
+ A(n, r),
2145
+ A(i, a)
2146
+ ];
2147
+ }
2148
+ });
2149
+ function ut(e, t, n, r) {
2150
+ let i = F(n, r);
2151
+ switch (e) {
2152
+ case "standard": return {
2153
+ origin: t,
2154
+ m: i,
2155
+ t1: n,
2156
+ t2: r
2157
+ };
2158
+ case "schiff": return {
2159
+ origin: {
2160
+ x: t.x,
2161
+ y: (t.y + n.y) / 2
2162
+ },
2163
+ m: i,
2164
+ t1: n,
2165
+ t2: r
2166
+ };
2167
+ case "modifiedSchiff": return {
2168
+ origin: F(t, n),
2169
+ m: i,
2170
+ t1: n,
2171
+ t2: r
2172
+ };
2173
+ case "inside": return {
2174
+ origin: t,
2175
+ m: i,
2176
+ t1: F(t, n),
2177
+ t2: F(t, r)
2178
+ };
2179
+ }
2180
+ }
2181
+ function G(e, t, n) {
2182
+ return B({
2183
+ id: e,
2184
+ label: t,
2185
+ family: "pitchforks",
2186
+ gesture: "clicks",
2187
+ anchors: 3,
2188
+ defaults: () => ({}),
2189
+ validate: H,
2190
+ shapes(t, r) {
2191
+ let [i, a, o] = O(r, t), s = ut(n, i, a, o), c = {
2192
+ x: s.m.x - s.origin.x,
2193
+ y: s.m.y - s.origin.y
2194
+ };
2195
+ if (c.x === 0 && c.y === 0) throw RangeError(`drawings: ${e} "${t.id}" has a zero-length median`);
2196
+ let l = (e) => ({
2197
+ x: e.x + c.x,
2198
+ y: e.y + c.y
2199
+ }), u = (e) => {
2200
+ let t = c.x > 0 ? (r.W + 50 - e.x) / c.x : c.x < 0 ? (-50 - e.x) / c.x : 1e4;
2201
+ return {
2202
+ x: e.x + c.x * t,
2203
+ y: e.y + c.y * t
2204
+ };
2205
+ }, d = u(s.origin);
2206
+ return [
2207
+ M([
2208
+ s.origin,
2209
+ s.t1,
2210
+ u(s.t1),
2211
+ d
2212
+ ], S(t.style.color, .08)),
2213
+ M([
2214
+ s.origin,
2215
+ s.t2,
2216
+ u(s.t2),
2217
+ d
2218
+ ], S(t.style.color, .08)),
2219
+ A(s.origin, l(s.origin), { extB: !0 }),
2220
+ A(s.t1, l(s.t1), { extB: !0 }),
2221
+ A(s.t2, l(s.t2), { extB: !0 }),
2222
+ A(a, o, {
2223
+ dash: "dashed",
2224
+ width: 1
2225
+ }),
2226
+ A(i, a, {
2227
+ dash: "dotted",
2228
+ width: 1,
2229
+ hit: !1
2230
+ })
2231
+ ];
2232
+ }
2233
+ });
2234
+ }
2235
+ var dt = G("pitchfork", "Pitchfork", "standard"), ft = G("schiffPitchfork", "Schiff pitchfork", "schiff"), pt = G("modifiedSchiffPitchfork", "Modified Schiff pitchfork", "modifiedSchiff"), mt = G("insidePitchfork", "Inside pitchfork", "inside"), ht = B({
2236
+ id: "pitchfan",
2237
+ label: "Pitchfan",
2238
+ family: "pitchforks",
2239
+ gesture: "clicks",
2240
+ anchors: 3,
2241
+ defaults: () => ({ props: { levels: Le } }),
2242
+ validate: H,
2243
+ shapes(e, t) {
2244
+ let [n, r, i] = O(t, e), a = e.props.levels, o = [A(r, i, {
2245
+ dash: "dashed",
2246
+ width: 1
2247
+ })], s = a.map((e) => ({
2248
+ r: e,
2249
+ p: Oe(r, i, e)
2250
+ }));
2251
+ for (let e = 0; e + 1 < s.length; e++) {
2252
+ let r = s[e].p, i = s[e + 1].p, a = (e) => {
2253
+ let r = e.x - n.x, i = e.y - n.y, a = r > 0 ? (t.W + 50 - n.x) / r : r < 0 ? (-50 - n.x) / r : 1e4;
2254
+ return {
2255
+ x: n.x + r * a,
2256
+ y: n.y + i * a
2257
+ };
2258
+ };
2259
+ o.push(M([
2260
+ n,
2261
+ a(r),
2262
+ a(i)
2263
+ ], S(z(s[e].r), .07)));
2264
+ }
2265
+ for (let { r: t, p: r } of s) o.push(A(n, r, {
2266
+ extB: !0,
2267
+ color: z(t),
2268
+ width: t === .5 ? e.style.width : 1
2269
+ }), N(r.x, r.y, String(t), {
2270
+ textColor: z(t),
2271
+ size: 10,
2272
+ hit: !1
2273
+ }));
2274
+ return o;
2275
+ }
2276
+ }), gt = [
2277
+ it,
2278
+ st,
2279
+ ct,
2280
+ lt,
2281
+ dt,
2282
+ ft,
2283
+ pt,
2284
+ mt,
2285
+ ht
2286
+ ], _t = 600, vt = 2;
2287
+ function yt(e, t) {
2288
+ return Math.abs(t.x - e.x);
2289
+ }
2290
+ var bt = B({
2291
+ id: "cyclicLines",
2292
+ label: "Cyclic lines",
2293
+ family: "cycles",
2294
+ gesture: "drag",
2295
+ anchors: 2,
2296
+ defaults: () => ({}),
2297
+ validate: (e) => {
2298
+ H(e), V(e, 0, 1);
2299
+ },
2300
+ shapes(e, t) {
2301
+ let [n, r] = O(t, e), i = yt(n, r);
2302
+ if (i < vt) return [A(n, r)];
2303
+ let a = Math.ceil((-50 - n.x) / i), o = Math.floor((t.W + 50 - n.x) / i), s = [];
2304
+ for (let e = a; e <= o && s.length < _t; e++) {
2305
+ let r = n.x + e * i;
2306
+ s.push(A({
2307
+ x: r,
2308
+ y: 0
2309
+ }, {
2310
+ x: r,
2311
+ y: t.H
2312
+ }, {
2313
+ extA: !0,
2314
+ extB: !0
2315
+ }));
2316
+ }
2317
+ return s;
2318
+ }
2319
+ }), xt = B({
2320
+ id: "timeCycles",
2321
+ label: "Time cycles",
2322
+ family: "cycles",
2323
+ gesture: "drag",
2324
+ anchors: 2,
2325
+ defaults: () => ({ style: { fill: "rgba(41,98,255,0.1)" } }),
2326
+ validate: (e) => {
2327
+ H(e), V(e, 0, 1);
2328
+ },
2329
+ shapes(e, t) {
2330
+ let [n, r] = O(t, e), i = yt(n, r);
2331
+ if (i < vt) return [A(n, r)];
2332
+ let a = [], o = r.x >= n.x ? 1 : -1;
2333
+ for (let r = 0; r < _t; r++) {
2334
+ let s = n.x + o * r * i;
2335
+ if (o > 0 ? s > t.W + 50 : s < -50) break;
2336
+ a.push({
2337
+ k: "arc",
2338
+ cx: s + o * i / 2,
2339
+ cy: n.y,
2340
+ r: i / 2,
2341
+ a0: Math.PI,
2342
+ a1: 2 * Math.PI,
2343
+ fill: e.style.fill
2344
+ });
2345
+ }
2346
+ return a;
2347
+ }
2348
+ });
2349
+ function St(e, t, n, r, i) {
2350
+ let a = (t + r) / 2;
2351
+ return a + (t - a) * Math.cos(Math.PI * (i - e) / (n - e));
2352
+ }
2353
+ var Ct = B({
2354
+ id: "sineLine",
2355
+ label: "Sine line",
2356
+ family: "cycles",
2357
+ gesture: "drag",
2358
+ anchors: 2,
2359
+ defaults: () => ({}),
2360
+ validate: (e) => {
2361
+ H(e), V(e, 0, 1);
2362
+ },
2363
+ shapes(e, t) {
2364
+ let [n, r] = O(t, e);
2365
+ if (Math.abs(r.x - n.x) < vt) return [A(n, r)];
2366
+ let i = [];
2367
+ for (let e = -4; e <= t.W + 4; e += 2) i.push(e, St(n.x, n.y, r.x, r.y, e));
2368
+ return [{
2369
+ k: "poly",
2370
+ pts: i
2371
+ }];
2372
+ }
2373
+ }), wt = [
2374
+ bt,
2375
+ xt,
2376
+ Ct
2377
+ ], Tt = (e, t, n) => t.price + (e.price - t.price) * n, Et = (e, t, n, r) => n.price + (t.price - e.price) * r, Dt = [
2378
+ 0,
2379
+ 1,
2380
+ 2,
2381
+ 3,
2382
+ 5,
2383
+ 8,
2384
+ 13,
2385
+ 21,
2386
+ 34,
2387
+ 55,
2388
+ 89
2389
+ ], Ot = (1 + Math.sqrt(5)) / 2, K = (e) => ({ props: { levels: e } }), kt = B({
2390
+ id: "fibRetracement",
2391
+ label: "Fib retracement",
2392
+ family: "fibonacci",
2393
+ gesture: "drag",
2394
+ anchors: 2,
2395
+ defaults: () => K(Ie),
2396
+ validate: (e) => {
2397
+ H(e), k(e);
2398
+ },
2399
+ shapes(e, t) {
2400
+ let n = E(e, 0), r = E(e, 1), i = D(t, n), a = D(t, r), o = Math.min(i.x, a.x), s = e.style.extendRight ? t.W + 10 : Math.max(i.x, a.x), c = [A(i, a, {
2401
+ dash: "dashed",
2402
+ width: 1,
2403
+ color: "#787b86"
2404
+ })], l = k(e), u = l.map((e) => t.Y(Tt(n, r, e)));
2405
+ for (let e = 0; e + 1 < l.length; e++) c.push(M([
2406
+ {
2407
+ x: o,
2408
+ y: u[e]
2409
+ },
2410
+ {
2411
+ x: s,
2412
+ y: u[e]
2413
+ },
2414
+ {
2415
+ x: s,
2416
+ y: u[e + 1]
2417
+ },
2418
+ {
2419
+ x: o,
2420
+ y: u[e + 1]
2421
+ }
2422
+ ], S(z(l[e + 1]), .07)));
2423
+ return l.forEach((e, i) => {
2424
+ let a = u[i];
2425
+ c.push(A({
2426
+ x: o,
2427
+ y: a
2428
+ }, {
2429
+ x: s,
2430
+ y: a
2431
+ }, {
2432
+ color: z(e),
2433
+ width: 1
2434
+ })), c.push(N(o - 4, a, `${e} (${t.fmt(Tt(n, r, e))})`, {
2435
+ align: "right",
2436
+ base: "middle",
2437
+ textColor: z(e),
2438
+ size: 10,
2439
+ hit: !1
2440
+ }));
2441
+ }), c;
2442
+ }
2443
+ }), At = B({
2444
+ id: "fibExtension",
2445
+ label: "Trend-based Fib extension",
2446
+ family: "fibonacci",
2447
+ gesture: "clicks",
2448
+ anchors: 3,
2449
+ defaults: () => K([
2450
+ 0,
2451
+ .236,
2452
+ .382,
2453
+ .5,
2454
+ .618,
2455
+ .786,
2456
+ 1,
2457
+ 1.272,
2458
+ 1.618,
2459
+ 2,
2460
+ 2.618,
2461
+ 3.618,
2462
+ 4.236
2463
+ ]),
2464
+ validate: (e) => {
2465
+ H(e), k(e);
2466
+ },
2467
+ shapes(e, t) {
2468
+ let [n, r, i] = [
2469
+ E(e, 0),
2470
+ E(e, 1),
2471
+ E(e, 2)
2472
+ ], [a, o, s] = [
2473
+ D(t, n),
2474
+ D(t, r),
2475
+ D(t, i)
2476
+ ], c = s.x, l = e.style.extendRight ? t.W + 10 : Math.max(s.x, o.x) + 40, u = [A(a, o, {
2477
+ dash: "dashed",
2478
+ width: 1,
2479
+ color: "#787b86"
2480
+ }), A(o, s, {
2481
+ dash: "dashed",
2482
+ width: 1,
2483
+ color: "#787b86"
2484
+ })], d = k(e), f = d.map((e) => t.Y(Et(n, r, i, e)));
2485
+ for (let e = 0; e + 1 < d.length; e++) u.push(M([
2486
+ {
2487
+ x: c,
2488
+ y: f[e]
2489
+ },
2490
+ {
2491
+ x: l,
2492
+ y: f[e]
2493
+ },
2494
+ {
2495
+ x: l,
2496
+ y: f[e + 1]
2497
+ },
2498
+ {
2499
+ x: c,
2500
+ y: f[e + 1]
2501
+ }
2502
+ ], S(z(d[e + 1]), .07)));
2503
+ return d.forEach((e, a) => {
2504
+ let o = f[a];
2505
+ u.push(A({
2506
+ x: c,
2507
+ y: o
2508
+ }, {
2509
+ x: l,
2510
+ y: o
2511
+ }, {
2512
+ color: z(e),
2513
+ width: 1
2514
+ })), u.push(N(c - 4, o, `${e} (${t.fmt(Et(n, r, i, e))})`, {
2515
+ align: "right",
2516
+ base: "middle",
2517
+ textColor: z(e),
2518
+ size: 10,
2519
+ hit: !1
2520
+ }));
2521
+ }), u;
2522
+ }
2523
+ }), jt = B({
2524
+ id: "fibChannel",
2525
+ label: "Fib channel",
2526
+ family: "fibonacci",
2527
+ gesture: "clicks",
2528
+ anchors: 3,
2529
+ defaults: () => K([
2530
+ 0,
2531
+ .236,
2532
+ .382,
2533
+ .5,
2534
+ .618,
2535
+ .786,
2536
+ 1,
2537
+ 1.618,
2538
+ 2.618
2539
+ ]),
2540
+ validate(e) {
2541
+ H(e), k(e), V(e, 0, 1);
2542
+ },
2543
+ shapes(e, t) {
2544
+ let [n, r, i] = O(t, e), a = n.y + (r.y - n.y) * (i.x - n.x) / (r.x - n.x), o = i.y - a, s = k(e), c = (e) => [{
2545
+ x: n.x,
2546
+ y: n.y + e * o
2547
+ }, {
2548
+ x: r.x,
2549
+ y: r.y + e * o
2550
+ }], l = [];
2551
+ for (let e = 0; e + 1 < s.length; e++) {
2552
+ let [t, n] = c(s[e]), [r, i] = c(s[e + 1]);
2553
+ l.push(M([
2554
+ t,
2555
+ n,
2556
+ i,
2557
+ r
2558
+ ], S(z(s[e + 1]), .07)));
2559
+ }
2560
+ for (let t of s) {
2561
+ let [n, r] = c(t);
2562
+ l.push(A(n, r, {
2563
+ extB: e.style.extendRight,
2564
+ extA: e.style.extendLeft,
2565
+ color: z(t),
2566
+ width: 1
2567
+ }), N(r.x + 4, r.y, String(t), {
2568
+ base: "middle",
2569
+ textColor: z(t),
2570
+ size: 10,
2571
+ hit: !1
2572
+ }));
2573
+ }
2574
+ return l;
2575
+ }
2576
+ }), Mt = B({
2577
+ id: "fibTimeZone",
2578
+ label: "Fib time zone",
2579
+ family: "fibonacci",
2580
+ gesture: "drag",
2581
+ anchors: 2,
2582
+ defaults: () => K(Dt),
2583
+ validate(e) {
2584
+ H(e), k(e), V(e, 0, 1);
2585
+ },
2586
+ shapes(e, t) {
2587
+ let [n, r] = O(t, e), i = r.x - n.x, a = [];
2588
+ for (let r of k(e)) {
2589
+ let e = n.x + r * i;
2590
+ e < -50 || e > t.W + 50 || a.push(A({
2591
+ x: e,
2592
+ y: 0
2593
+ }, {
2594
+ x: e,
2595
+ y: t.H
2596
+ }, {
2597
+ extA: !0,
2598
+ extB: !0,
2599
+ color: r === 0 || r === 1 ? "#787b86" : "#2962ff",
2600
+ width: 1
2601
+ }), N(e + 3, 3, String(r), {
2602
+ base: "top",
2603
+ size: 10,
2604
+ textColor: "#787b86",
2605
+ hit: !1
2606
+ }));
2607
+ }
2608
+ return a.push(A(n, r, {
2609
+ dash: "dashed",
2610
+ width: 1
2611
+ })), a;
2612
+ }
2613
+ }), Nt = [
2614
+ .25,
2615
+ .382,
2616
+ .5,
2617
+ .618,
2618
+ .75,
2619
+ 1
2620
+ ], Pt = B({
2621
+ id: "fibSpeedFan",
2622
+ label: "Fib speed resistance fan",
2623
+ family: "fibonacci",
2624
+ gesture: "drag",
2625
+ anchors: 2,
2626
+ defaults: () => K(Nt),
2627
+ validate(e) {
2628
+ if (H(e), k(e), V(e, 0, 1), E(e, 0).price === E(e, 1).price) throw RangeError(`drawings: fibSpeedFan "${e.id}" needs anchors at different prices`);
2629
+ },
2630
+ shapes(e, t) {
2631
+ let [n, r] = O(t, e), i = [
2632
+ M([
2633
+ n,
2634
+ {
2635
+ x: r.x,
2636
+ y: n.y
2637
+ },
2638
+ r,
2639
+ {
2640
+ x: n.x,
2641
+ y: r.y
2642
+ }
2643
+ ], S(e.style.color, .05)),
2644
+ A(n, {
2645
+ x: r.x,
2646
+ y: n.y
2647
+ }, {
2648
+ dash: "dashed",
2649
+ width: 1,
2650
+ hit: !1
2651
+ }),
2652
+ A({
2653
+ x: r.x,
2654
+ y: n.y
2655
+ }, r, {
2656
+ dash: "dashed",
2657
+ width: 1,
2658
+ hit: !1
2659
+ }),
2660
+ A(r, {
2661
+ x: n.x,
2662
+ y: r.y
2663
+ }, {
2664
+ dash: "dashed",
2665
+ width: 1,
2666
+ hit: !1
2667
+ }),
2668
+ A({
2669
+ x: n.x,
2670
+ y: r.y
2671
+ }, n, {
2672
+ dash: "dashed",
2673
+ width: 1,
2674
+ hit: !1
2675
+ })
2676
+ ];
2677
+ for (let t of k(e)) {
2678
+ let e = z(t === .25 ? .5 : t), a = {
2679
+ x: r.x,
2680
+ y: n.y + t * (r.y - n.y)
2681
+ }, o = {
2682
+ x: n.x + t * (r.x - n.x),
2683
+ y: r.y
2684
+ };
2685
+ i.push(A(n, a, {
2686
+ extB: !0,
2687
+ color: e,
2688
+ width: 1
2689
+ }), A(n, o, {
2690
+ extB: !0,
2691
+ color: e,
2692
+ width: 1
2693
+ }), N(a.x + 3, a.y, String(t), {
2694
+ base: "middle",
2695
+ size: 10,
2696
+ textColor: e,
2697
+ hit: !1
2698
+ }));
2699
+ }
2700
+ return i;
2701
+ }
2702
+ }), Ft = B({
2703
+ id: "fibTrendTime",
2704
+ label: "Trend-based Fib time",
2705
+ family: "fibonacci",
2706
+ gesture: "clicks",
2707
+ anchors: 3,
2708
+ defaults: () => K([
2709
+ 0,
2710
+ .382,
2711
+ .5,
2712
+ .618,
2713
+ 1,
2714
+ 1.382,
2715
+ 1.618,
2716
+ 2,
2717
+ 2.382,
2718
+ 2.618,
2719
+ 3,
2720
+ 4.236
2721
+ ]),
2722
+ validate(e) {
2723
+ H(e), k(e), V(e, 0, 1);
2724
+ },
2725
+ shapes(e, t) {
2726
+ let [n, r, i] = O(t, e), a = r.x - n.x, o = [A(n, r, {
2727
+ dash: "dashed",
2728
+ width: 1,
2729
+ color: "#787b86"
2730
+ })];
2731
+ for (let n of k(e)) {
2732
+ let e = i.x + n * a;
2733
+ e < -50 || e > t.W + 50 || o.push(A({
2734
+ x: e,
2735
+ y: 0
2736
+ }, {
2737
+ x: e,
2738
+ y: t.H
2739
+ }, {
2740
+ extA: !0,
2741
+ extB: !0,
2742
+ color: z(n),
2743
+ width: 1
2744
+ }), N(e + 3, 3, String(n), {
2745
+ base: "top",
2746
+ size: 10,
2747
+ textColor: z(n),
2748
+ hit: !1
2749
+ }));
2750
+ }
2751
+ return o;
2752
+ }
2753
+ }), It = B({
2754
+ id: "fibCircles",
2755
+ label: "Fib circles",
2756
+ family: "fibonacci",
2757
+ gesture: "drag",
2758
+ anchors: 2,
2759
+ defaults: () => K([
2760
+ .236,
2761
+ .382,
2762
+ .5,
2763
+ .618,
2764
+ .786,
2765
+ 1,
2766
+ 1.618,
2767
+ 2.618
2768
+ ]),
2769
+ validate(e) {
2770
+ H(e), k(e);
2771
+ },
2772
+ shapes(e, t) {
2773
+ let [n, r] = O(t, e), i = s(n.x, n.y, r.x, r.y), a = [A(n, r, {
2774
+ dash: "dashed",
2775
+ width: 1,
2776
+ color: "#787b86"
2777
+ })];
2778
+ for (let t of k(e)) a.push({
2779
+ k: "ellipse",
2780
+ cx: n.x,
2781
+ cy: n.y,
2782
+ rx: i * t,
2783
+ ry: i * t,
2784
+ color: z(t),
2785
+ width: 1
2786
+ }, N(n.x + i * t, n.y, String(t), {
2787
+ size: 10,
2788
+ base: "bottom",
2789
+ textColor: z(t),
2790
+ hit: !1
2791
+ }));
2792
+ return a;
2793
+ }
2794
+ }), Lt = B({
2795
+ id: "fibSpiral",
2796
+ label: "Fib spiral",
2797
+ family: "fibonacci",
2798
+ gesture: "drag",
2799
+ anchors: 2,
2800
+ defaults: () => ({ props: { clockwise: !1 } }),
2801
+ validate: H,
2802
+ shapes(e, t) {
2803
+ let [n, r] = O(t, e), i = s(n.x, n.y, r.x, r.y);
2804
+ if (i === 0) return [A(n, r)];
2805
+ let a = Math.atan2(r.y - n.y, r.x - n.x), o = e.props.clockwise === !0 ? 1 : -1, c = 2 * Math.hypot(t.W, t.H), l = Math.min(8 * Math.PI, Math.log(c / i) * Math.PI / (2 * Math.log(Ot))), u = [];
2806
+ for (let e = -3 * Math.PI; e <= l; e += .08) {
2807
+ let t = i * Ot ** (2 * e / Math.PI);
2808
+ u.push({
2809
+ x: n.x + t * Math.cos(a + o * e),
2810
+ y: n.y + t * Math.sin(a + o * e)
2811
+ });
2812
+ }
2813
+ return [A(n, r, {
2814
+ dash: "dashed",
2815
+ width: 1
2816
+ }), {
2817
+ k: "poly",
2818
+ pts: u.flatMap((e) => [e.x, e.y])
2819
+ }];
2820
+ }
2821
+ }), Rt = [
2822
+ .382,
2823
+ .5,
2824
+ .618,
2825
+ 1,
2826
+ 1.382,
2827
+ 1.618
2828
+ ], zt = B({
2829
+ id: "fibSpeedArcs",
2830
+ label: "Fib speed resistance arcs",
2831
+ family: "fibonacci",
2832
+ gesture: "drag",
2833
+ anchors: 2,
2834
+ defaults: () => K(Rt),
2835
+ validate: (e) => {
2836
+ H(e), k(e);
2837
+ },
2838
+ shapes(e, t) {
2839
+ let [n, r] = O(t, e), i = s(n.x, n.y, r.x, r.y), a = Math.atan2(r.y - n.y, r.x - n.x), o = [A(n, r, {
2840
+ dash: "dashed",
2841
+ width: 1,
2842
+ color: "#787b86"
2843
+ })];
2844
+ for (let t of k(e)) o.push({
2845
+ k: "arc",
2846
+ cx: r.x,
2847
+ cy: r.y,
2848
+ r: i * t,
2849
+ a0: a - Math.PI / 2,
2850
+ a1: a + Math.PI / 2,
2851
+ color: z(t),
2852
+ width: 1
2853
+ }), o.push(N(r.x + i * t * Math.cos(a), r.y + i * t * Math.sin(a), String(t), {
2854
+ size: 10,
2855
+ base: "middle",
2856
+ textColor: z(t),
2857
+ hit: !1
2858
+ }));
2859
+ return o;
2860
+ }
2861
+ }), Bt = B({
2862
+ id: "fibWedge",
2863
+ label: "Fib wedge",
2864
+ family: "fibonacci",
2865
+ gesture: "clicks",
2866
+ anchors: 3,
2867
+ defaults: () => K([
2868
+ .236,
2869
+ .382,
2870
+ .5,
2871
+ .618,
2872
+ .786,
2873
+ 1,
2874
+ 1.618
2875
+ ]),
2876
+ validate: (e) => {
2877
+ H(e), k(e);
2878
+ },
2879
+ shapes(e, t) {
2880
+ let [n, r, i] = O(t, e), a = s(n.x, n.y, r.x, r.y), o = Math.atan2(r.y - n.y, r.x - n.x), c = ((Math.atan2(i.y - n.y, i.x - n.x) - o + Math.PI) % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI) - Math.PI, l = [A(n, r, { extB: !0 }), A(n, i, { extB: !0 })];
2881
+ for (let t of k(e)) l.push({
2882
+ k: "arc",
2883
+ cx: n.x,
2884
+ cy: n.y,
2885
+ r: a * t,
2886
+ a0: o,
2887
+ a1: o + c,
2888
+ color: z(t),
2889
+ width: 1
2890
+ });
2891
+ return l;
2892
+ }
2893
+ }), Vt = [
2894
+ kt,
2895
+ At,
2896
+ jt,
2897
+ Mt,
2898
+ Pt,
2899
+ Ft,
2900
+ It,
2901
+ Lt,
2902
+ zt,
2903
+ Bt
2904
+ ], q = "rgba(41,98,255,0.15)";
2905
+ function Ht(e, t) {
2906
+ return e ? [N(t.x, t.y, e, {
2907
+ align: "center",
2908
+ base: "middle",
2909
+ hit: !1
2910
+ })] : [];
2911
+ }
2912
+ var Ut = B({
2913
+ id: "rectangle",
2914
+ label: "Rectangle",
2915
+ family: "shapes",
2916
+ gesture: "drag",
2917
+ anchors: 2,
2918
+ defaults: () => ({ style: { fill: q } }),
2919
+ validate: H,
2920
+ shapes(e, t) {
2921
+ let [n, r] = O(t, e);
2922
+ return [j([
2923
+ n,
2924
+ {
2925
+ x: r.x,
2926
+ y: n.y
2927
+ },
2928
+ r,
2929
+ {
2930
+ x: n.x,
2931
+ y: r.y
2932
+ }
2933
+ ], {
2934
+ close: !0,
2935
+ fill: e.style.fill
2936
+ }), ...Ht(e.style.text, F(n, r))];
2937
+ }
2938
+ });
2939
+ function Wt(e, t, n) {
2940
+ let r = t.x - e.x, i = t.y - e.y, a = Math.hypot(r, i);
2941
+ if (a === 0) throw RangeError("rotated rectangle: its first two anchors coincide");
2942
+ let o = -i / a, s = r / a, c = (n.x - e.x) * o + (n.y - e.y) * s;
2943
+ return [
2944
+ e,
2945
+ t,
2946
+ {
2947
+ x: t.x + o * c,
2948
+ y: t.y + s * c
2949
+ },
2950
+ {
2951
+ x: e.x + o * c,
2952
+ y: e.y + s * c
2953
+ }
2954
+ ];
2955
+ }
2956
+ var Gt = B({
2957
+ id: "rotatedRectangle",
2958
+ label: "Rotated rectangle",
2959
+ family: "shapes",
2960
+ gesture: "clicks",
2961
+ anchors: 3,
2962
+ defaults: () => ({ style: { fill: q } }),
2963
+ validate: H,
2964
+ shapes(e, t) {
2965
+ let [n, r, i] = O(t, e), a = Wt(n, r, i);
2966
+ return [j(a, {
2967
+ close: !0,
2968
+ fill: e.style.fill
2969
+ }), ...Ht(e.style.text, F(a[0], a[2]))];
2970
+ }
2971
+ }), Kt = B({
2972
+ id: "ellipse",
2973
+ label: "Ellipse",
2974
+ family: "shapes",
2975
+ gesture: "drag",
2976
+ anchors: 2,
2977
+ defaults: () => ({ style: { fill: q } }),
2978
+ validate: H,
2979
+ shapes(e, t) {
2980
+ let [n, r] = O(t, e), i = F(n, r);
2981
+ return [{
2982
+ k: "ellipse",
2983
+ cx: i.x,
2984
+ cy: i.y,
2985
+ rx: Math.abs(r.x - n.x) / 2,
2986
+ ry: Math.abs(r.y - n.y) / 2,
2987
+ fill: e.style.fill
2988
+ }, ...Ht(e.style.text, i)];
2989
+ }
2990
+ }), qt = B({
2991
+ id: "circle",
2992
+ label: "Circle",
2993
+ family: "shapes",
2994
+ gesture: "drag",
2995
+ anchors: 2,
2996
+ defaults: () => ({ style: { fill: q } }),
2997
+ validate: H,
2998
+ shapes(e, t) {
2999
+ let [n, r] = O(t, e), i = s(n.x, n.y, r.x, r.y);
3000
+ return [
3001
+ {
3002
+ k: "ellipse",
3003
+ cx: n.x,
3004
+ cy: n.y,
3005
+ rx: i,
3006
+ ry: i,
3007
+ fill: e.style.fill
3008
+ },
3009
+ A(n, r, {
3010
+ dash: "dotted",
3011
+ width: 1,
3012
+ hit: !1
3013
+ }),
3014
+ ...Ht(e.style.text, n)
3015
+ ];
3016
+ }
3017
+ }), Jt = B({
3018
+ id: "triangle",
3019
+ label: "Triangle",
3020
+ family: "shapes",
3021
+ gesture: "clicks",
3022
+ anchors: 3,
3023
+ defaults: () => ({ style: { fill: q } }),
3024
+ validate: H,
3025
+ shapes(e, t) {
3026
+ return [j(O(t, e), {
3027
+ close: !0,
3028
+ fill: e.style.fill
3029
+ })];
3030
+ }
3031
+ });
3032
+ function Yt(e, t, n) {
3033
+ let r = m(e, t, n);
3034
+ if (!r) return null;
3035
+ let i = (e) => Math.atan2(e.y - r.cy, e.x - r.cx), a = (e) => (e % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI), o = i(e), s = a(i(t) - o), c = a(i(n) - o);
3036
+ return {
3037
+ ...r,
3038
+ a0: o,
3039
+ a1: c < s ? o + s : o - (2 * Math.PI - s)
3040
+ };
3041
+ }
3042
+ var Xt = B({
3043
+ id: "arc",
3044
+ label: "Arc",
3045
+ family: "shapes",
3046
+ gesture: "clicks",
3047
+ anchors: 3,
3048
+ defaults: () => ({}),
3049
+ validate: H,
3050
+ shapes(e, t) {
3051
+ let [n, r, i] = O(t, e), a = Yt(n, r, i);
3052
+ return a ? [{
3053
+ k: "arc",
3054
+ cx: a.cx,
3055
+ cy: a.cy,
3056
+ r: a.r,
3057
+ a0: a.a0,
3058
+ a1: a.a1,
3059
+ fill: e.style.fill
3060
+ }] : [A(n, r)];
3061
+ }
3062
+ }), Zt = B({
3063
+ id: "curve",
3064
+ label: "Curve",
3065
+ family: "shapes",
3066
+ gesture: "clicks",
3067
+ anchors: 3,
3068
+ defaults: () => ({}),
3069
+ validate: H,
3070
+ shapes(e, t) {
3071
+ let [n, r, i] = O(t, e);
3072
+ return [{
3073
+ k: "poly",
3074
+ pts: f(n, p(n, i, r), r)
3075
+ }];
3076
+ }
3077
+ }), Qt = B({
3078
+ id: "doubleCurve",
3079
+ label: "Double curve",
3080
+ family: "shapes",
3081
+ gesture: "clicks",
3082
+ anchors: 4,
3083
+ defaults: () => ({}),
3084
+ validate: H,
3085
+ shapes(e, t) {
3086
+ let [n, r, i, a] = O(t, e), o = F(n, r);
3087
+ return [{
3088
+ k: "poly",
3089
+ pts: [...f(n, p(n, i, o), o), ...f(o, p(o, a, r), r)]
3090
+ }];
3091
+ }
3092
+ }), $t = B({
3093
+ id: "polyline",
3094
+ label: "Polyline",
3095
+ family: "shapes",
3096
+ gesture: "clicks",
3097
+ anchors: 2,
3098
+ variable: !0,
3099
+ defaults: () => ({}),
3100
+ validate: H,
3101
+ shapes(e, t) {
3102
+ return [j(O(t, e), {
3103
+ close: e.style.fill !== null,
3104
+ fill: e.style.fill
3105
+ })];
3106
+ }
3107
+ }), en = B({
3108
+ id: "path",
3109
+ label: "Path",
3110
+ family: "shapes",
3111
+ gesture: "clicks",
3112
+ anchors: 2,
3113
+ variable: !0,
3114
+ defaults: () => ({}),
3115
+ validate: H,
3116
+ shapes(e, t) {
3117
+ let n = O(t, e);
3118
+ return [j(n), P(n[n.length - 2], n[n.length - 1], 6 + e.style.width * 2, e.style.color)];
3119
+ }
3120
+ }), tn = B({
3121
+ id: "brush",
3122
+ label: "Brush",
3123
+ family: "shapes",
3124
+ gesture: "freehand",
3125
+ anchors: 2,
3126
+ variable: !0,
3127
+ noHandles: !0,
3128
+ defaults: () => ({ style: { width: 2 } }),
3129
+ validate: H,
3130
+ shapes: (e, t) => [j(O(t, e))]
3131
+ }), nn = B({
3132
+ id: "highlighter",
3133
+ label: "Highlighter",
3134
+ family: "shapes",
3135
+ gesture: "freehand",
3136
+ anchors: 2,
3137
+ variable: !0,
3138
+ noHandles: !0,
3139
+ defaults: () => ({ style: {
3140
+ width: 14,
3141
+ color: "rgba(255,235,59,0.4)"
3142
+ } }),
3143
+ validate: H,
3144
+ shapes: (e, t) => [j(O(t, e))]
3145
+ }), rn = [
3146
+ Ut,
3147
+ Gt,
3148
+ Kt,
3149
+ qt,
3150
+ Jt,
3151
+ Xt,
3152
+ Zt,
3153
+ Qt,
3154
+ $t,
3155
+ en,
3156
+ tn,
3157
+ nn
3158
+ ], an = [
3159
+ 0,
3160
+ .25,
3161
+ .382,
3162
+ .5,
3163
+ .618,
3164
+ .75,
3165
+ 1
3166
+ ], on = (e, t, n) => e.price + (t.price - e.price) * n, sn = (e, t, n, r) => e.price + (t.price - e.price) * n / r, cn = [
3167
+ [8, 1],
3168
+ [4, 1],
3169
+ [3, 1],
3170
+ [2, 1],
3171
+ [1, 1],
3172
+ [1, 2],
3173
+ [1, 3],
3174
+ [1, 4],
3175
+ [1, 8]
3176
+ ];
3177
+ function ln(e, t, n, r, i) {
3178
+ let a = [];
3179
+ for (let r of n) a.push(A({
3180
+ x: e.x + r * (t.x - e.x),
3181
+ y: e.y
3182
+ }, {
3183
+ x: e.x + r * (t.x - e.x),
3184
+ y: t.y
3185
+ }, {
3186
+ width: 1,
3187
+ color: S(i, .7)
3188
+ }));
3189
+ for (let n of r) a.push(A({
3190
+ x: e.x,
3191
+ y: e.y + n * (t.y - e.y)
3192
+ }, {
3193
+ x: t.x,
3194
+ y: e.y + n * (t.y - e.y)
3195
+ }, {
3196
+ width: 1,
3197
+ color: S(i, .7)
3198
+ }));
3199
+ return a;
3200
+ }
3201
+ var un = B({
3202
+ id: "gannBox",
3203
+ label: "Gann box",
3204
+ family: "gann",
3205
+ gesture: "drag",
3206
+ anchors: 2,
3207
+ defaults: () => ({ props: { levels: an } }),
3208
+ validate: (e) => {
3209
+ H(e), V(e, 0, 1), k(e);
3210
+ },
3211
+ shapes(e, t) {
3212
+ let n = E(e, 0), r = E(e, 1), [i, a] = O(t, e), o = k(e), s = (e) => t.Y(on(n, r, e)), c = [];
3213
+ for (let t = 0; t + 1 < o.length; t += 2) {
3214
+ let n = s(o[t]), r = s(o[t + 1]);
3215
+ c.push(M([
3216
+ {
3217
+ x: i.x,
3218
+ y: n
3219
+ },
3220
+ {
3221
+ x: a.x,
3222
+ y: n
3223
+ },
3224
+ {
3225
+ x: a.x,
3226
+ y: r
3227
+ },
3228
+ {
3229
+ x: i.x,
3230
+ y: r
3231
+ }
3232
+ ], S(e.style.color, .06)));
3233
+ }
3234
+ c.push(...ln(i, a, o, [], e.style.color));
3235
+ for (let t of o) c.push(A({
3236
+ x: i.x,
3237
+ y: s(t)
3238
+ }, {
3239
+ x: a.x,
3240
+ y: s(t)
3241
+ }, {
3242
+ width: 1,
3243
+ color: S(e.style.color, .7)
3244
+ }));
3245
+ c.push(A(i, a), A({
3246
+ x: i.x,
3247
+ y: a.y
3248
+ }, {
3249
+ x: a.x,
3250
+ y: i.y
3251
+ })), c.push(A(i, {
3252
+ x: a.x,
3253
+ y: i.y
3254
+ }), A({
3255
+ x: a.x,
3256
+ y: i.y
3257
+ }, a), A(a, {
3258
+ x: i.x,
3259
+ y: a.y
3260
+ }), A({
3261
+ x: i.x,
3262
+ y: a.y
3263
+ }, i));
3264
+ for (let l of o) {
3265
+ c.push(N(Math.min(i.x, a.x) - 4, s(l), t.fmt(on(n, r, l)), {
3266
+ align: "right",
3267
+ base: "middle",
3268
+ size: 10,
3269
+ textColor: e.style.color,
3270
+ hit: !1
3271
+ }));
3272
+ let o = i.x + l * (a.x - i.x);
3273
+ c.push(N(o, Math.min(i.y, a.y) - 4, I(t.T(o)), {
3274
+ align: "center",
3275
+ base: "bottom",
3276
+ size: 9,
3277
+ textColor: e.style.color,
3278
+ hit: !1
3279
+ }));
3280
+ }
3281
+ return c;
3282
+ }
3283
+ }), dn = [
3284
+ 0,
3285
+ 1 / 8,
3286
+ 2 / 8,
3287
+ 3 / 8,
3288
+ 4 / 8,
3289
+ 5 / 8,
3290
+ 6 / 8,
3291
+ 7 / 8,
3292
+ 1
3293
+ ];
3294
+ function fn(e, t, n) {
3295
+ let r = ln(e, t, dn, dn, n), i = {
3296
+ x: (e.x + t.x) / 2,
3297
+ y: (e.y + t.y) / 2
3298
+ };
3299
+ return r.push(A(e, t, { extB: !0 }), A({
3300
+ x: e.x,
3301
+ y: t.y
3302
+ }, {
3303
+ x: t.x,
3304
+ y: e.y
3305
+ }, { extB: !0 })), r.push(A({
3306
+ x: i.x,
3307
+ y: e.y
3308
+ }, {
3309
+ x: t.x,
3310
+ y: i.y
3311
+ }, { width: 1 }), A({
3312
+ x: t.x,
3313
+ y: i.y
3314
+ }, {
3315
+ x: i.x,
3316
+ y: t.y
3317
+ }, { width: 1 }), A({
3318
+ x: i.x,
3319
+ y: t.y
3320
+ }, {
3321
+ x: e.x,
3322
+ y: i.y
3323
+ }, { width: 1 }), A({
3324
+ x: e.x,
3325
+ y: i.y
3326
+ }, {
3327
+ x: i.x,
3328
+ y: e.y
3329
+ }, { width: 1 })), r;
3330
+ }
3331
+ var pn = B({
3332
+ id: "gannSquare",
3333
+ label: "Gann square",
3334
+ family: "gann",
3335
+ gesture: "drag",
3336
+ anchors: 2,
3337
+ defaults: () => ({}),
3338
+ validate: (e) => {
3339
+ H(e), V(e, 0, 1);
3340
+ },
3341
+ shapes: (e, t) => {
3342
+ let [n, r] = O(t, e);
3343
+ return fn(n, r, e.style.color);
3344
+ }
3345
+ });
3346
+ function mn(e, t) {
3347
+ let n = D(t, e.anchors[0]), r = D(t, e.anchors[1]), i = Math.abs(r.x - n.x);
3348
+ return {
3349
+ x: r.x,
3350
+ y: n.y + (r.y >= n.y ? i : -i)
3351
+ };
3352
+ }
3353
+ var hn = B({
3354
+ id: "gannSquareFixed",
3355
+ label: "Gann square fixed",
3356
+ family: "gann",
3357
+ gesture: "drag",
3358
+ anchors: 2,
3359
+ defaults: () => ({}),
3360
+ validate: (e) => {
3361
+ H(e), V(e, 0, 1);
3362
+ },
3363
+ handlePoints: (e, t) => [D(t, E(e, 0)), mn(e, t)],
3364
+ shapes: (e, t) => fn(D(t, E(e, 0)), mn(e, t), e.style.color)
3365
+ }), gn = B({
3366
+ id: "gannFan",
3367
+ label: "Gann fan",
3368
+ family: "gann",
3369
+ gesture: "drag",
3370
+ anchors: 2,
3371
+ defaults: () => ({}),
3372
+ validate(e) {
3373
+ if (H(e), V(e, 0, 1), E(e, 0).price === E(e, 1).price) throw RangeError(`drawings: gannFan "${e.id}" needs anchors at different prices (its 1×1 line would be flat)`);
3374
+ },
3375
+ shapes(e, t) {
3376
+ let n = E(e, 0), r = E(e, 1), i = D(t, n), a = t.X(r.time), o = [], s = cn.map(([e, i]) => ({
3377
+ n: e,
3378
+ m: i,
3379
+ e: {
3380
+ x: a,
3381
+ y: t.Y(sn(n, r, e, i))
3382
+ }
3383
+ }));
3384
+ for (let n = 0; n + 1 < s.length; n++) {
3385
+ let r = (e) => {
3386
+ let n = e.x - i.x, r = e.y - i.y, a = n === 0 ? 1e4 : (t.W + 50 - i.x) / n;
3387
+ return {
3388
+ x: i.x + n * a,
3389
+ y: i.y + r * a
3390
+ };
3391
+ };
3392
+ a > i.x && o.push(M([
3393
+ i,
3394
+ r(s[n].e),
3395
+ r(s[n + 1].e)
3396
+ ], S(e.style.color, n % 2 ? .04 : .09)));
3397
+ }
3398
+ for (let { n: t, m: n, e: r } of s) o.push(A(i, r, {
3399
+ extB: !0,
3400
+ extA: !1,
3401
+ width: t === n ? e.style.width : 1
3402
+ }), N(r.x + 3, r.y, `${t}x${n}`, {
3403
+ base: "middle",
3404
+ size: 10,
3405
+ textColor: e.style.color,
3406
+ hit: !1
3407
+ }));
3408
+ return o;
3409
+ }
3410
+ }), _n = [
3411
+ un,
3412
+ hn,
3413
+ pn,
3414
+ gn
3415
+ ], J = (e) => {
3416
+ H(e);
3417
+ }, vn = B({
3418
+ id: "trendLine",
3419
+ label: "Trend line",
3420
+ family: "lines",
3421
+ gesture: "drag",
3422
+ anchors: 2,
3423
+ defaults: () => ({}),
3424
+ validate: J,
3425
+ shapes: (e, t) => {
3426
+ let n = D(t, E(e, 0)), r = D(t, E(e, 1));
3427
+ return [A(n, r, De(e.style, n, r))];
3428
+ }
3429
+ }), yn = B({
3430
+ id: "ray",
3431
+ label: "Ray",
3432
+ family: "lines",
3433
+ gesture: "drag",
3434
+ anchors: 2,
3435
+ defaults: () => ({ style: { extendRight: !0 } }),
3436
+ validate: J,
3437
+ shapes: (e, t) => [A(D(t, E(e, 0)), D(t, E(e, 1)), {
3438
+ extA: !1,
3439
+ extB: !0
3440
+ })]
3441
+ }), bn = B({
3442
+ id: "extendedLine",
3443
+ label: "Extended line",
3444
+ family: "lines",
3445
+ gesture: "drag",
3446
+ anchors: 2,
3447
+ defaults: () => ({ style: {
3448
+ extendLeft: !0,
3449
+ extendRight: !0
3450
+ } }),
3451
+ validate: J,
3452
+ shapes: (e, t) => [A(D(t, E(e, 0)), D(t, E(e, 1)), {
3453
+ extA: !0,
3454
+ extB: !0
3455
+ })]
3456
+ }), xn = B({
3457
+ id: "infoLine",
3458
+ label: "Info line",
3459
+ family: "lines",
3460
+ gesture: "drag",
3461
+ anchors: 2,
3462
+ defaults: () => ({}),
3463
+ validate: J,
3464
+ shapes(e, t) {
3465
+ let n = E(e, 0), r = E(e, 1), i = D(t, n), a = D(t, r), o = L(n, r, t.source);
3466
+ return [A(i, a, De(e.style, i, a)), N((i.x + a.x) / 2, (i.y + a.y) / 2 - 8, [...Ne(o, t), `${I(n.time)} → ${I(r.time)}`].join("\n"), {
3467
+ align: "center",
3468
+ base: "bottom",
3469
+ bg: e.style.color,
3470
+ border: null,
3471
+ textColor: "#ffffff",
3472
+ pad: 4
3473
+ })];
3474
+ }
3475
+ }), Sn = B({
3476
+ id: "horizontalLine",
3477
+ label: "Horizontal line",
3478
+ family: "lines",
3479
+ gesture: "single",
3480
+ anchors: 1,
3481
+ defaults: () => ({}),
3482
+ validate: J,
3483
+ shapes(t, n) {
3484
+ let r = D(n, E(t, 0)), i = e(r.y, n.dpr, t.style.width);
3485
+ return [A({
3486
+ x: 0,
3487
+ y: i
3488
+ }, {
3489
+ x: n.W,
3490
+ y: i
3491
+ }, {
3492
+ extA: !0,
3493
+ extB: !0
3494
+ }), N(n.W - 6, i - 2, n.fmt(E(t, 0).price), {
3495
+ align: "right",
3496
+ base: "bottom",
3497
+ textColor: t.style.color,
3498
+ hit: !1,
3499
+ stack: !0
3500
+ })];
3501
+ }
3502
+ }), Cn = 72, wn = B({
3503
+ id: "horizontalRay",
3504
+ label: "Horizontal ray",
3505
+ family: "lines",
3506
+ gesture: "single",
3507
+ anchors: 1,
3508
+ defaults: () => ({}),
3509
+ validate: J,
3510
+ shapes(t, n) {
3511
+ let r = D(n, E(t, 0)), i = e(r.y, n.dpr, t.style.width), a = r.x >= Cn ? N(r.x - 4, i, n.fmt(E(t, 0).price), {
3512
+ align: "right",
3513
+ base: "middle",
3514
+ textColor: t.style.color,
3515
+ hit: !1,
3516
+ stack: !0
3517
+ }) : N(Math.max(r.x, 0) + 4, i - 2, n.fmt(E(t, 0).price), {
3518
+ align: "left",
3519
+ base: "bottom",
3520
+ textColor: t.style.color,
3521
+ hit: !1,
3522
+ stack: !0
3523
+ });
3524
+ return [A({
3525
+ x: r.x,
3526
+ y: i
3527
+ }, {
3528
+ x: r.x + 1,
3529
+ y: i
3530
+ }, { extB: !0 }), a];
3531
+ }
3532
+ }), Tn = B({
3533
+ id: "verticalLine",
3534
+ label: "Vertical line",
3535
+ family: "lines",
3536
+ gesture: "single",
3537
+ anchors: 1,
3538
+ defaults: () => ({}),
3539
+ validate: J,
3540
+ shapes(t, n) {
3541
+ let r = D(n, E(t, 0)), i = e(r.x, n.dpr, t.style.width);
3542
+ return [A({
3543
+ x: i,
3544
+ y: 0
3545
+ }, {
3546
+ x: i,
3547
+ y: n.H
3548
+ }, {
3549
+ extA: !0,
3550
+ extB: !0
3551
+ }), N(i + 4, 4, I(E(t, 0).time), {
3552
+ base: "top",
3553
+ textColor: t.style.color,
3554
+ hit: !1
3555
+ })];
3556
+ }
3557
+ }), En = B({
3558
+ id: "crossLine",
3559
+ label: "Cross line",
3560
+ family: "lines",
3561
+ gesture: "single",
3562
+ anchors: 1,
3563
+ defaults: () => ({}),
3564
+ validate: J,
3565
+ shapes(t, n) {
3566
+ let r = D(n, E(t, 0)), i = e(r.x, n.dpr, t.style.width), a = e(r.y, n.dpr, t.style.width);
3567
+ return [A({
3568
+ x: 0,
3569
+ y: a
3570
+ }, {
3571
+ x: n.W,
3572
+ y: a
3573
+ }, {
3574
+ extA: !0,
3575
+ extB: !0
3576
+ }), A({
3577
+ x: i,
3578
+ y: 0
3579
+ }, {
3580
+ x: i,
3581
+ y: n.H
3582
+ }, {
3583
+ extA: !0,
3584
+ extB: !0
3585
+ })];
3586
+ }
3587
+ }), Dn = [
3588
+ vn,
3589
+ yn,
3590
+ xn,
3591
+ bn,
3592
+ Sn,
3593
+ wn,
3594
+ Tn,
3595
+ En
3596
+ ];
3597
+ //#endregion
3598
+ //#region src/tools/measure.ts
3599
+ function On(e, t) {
3600
+ return t < 0 ? "#ef5350" : e.style.color;
3601
+ }
3602
+ var kn = (e, t, n, r) => N(e, t, n, {
3603
+ align: "center",
3604
+ base: "middle",
3605
+ bg: S(r, .9),
3606
+ textColor: "#ffffff",
3607
+ pad: 4,
3608
+ hit: !1
3609
+ });
3610
+ function An(e, t) {
3611
+ let n = L(E(e, 0), E(e, 1), t.source), r = n.dPrice < 0 ? "-" : n.dPrice > 0 ? "+" : "";
3612
+ return `${r}${t.fmt(Math.abs(n.dPrice))}${n.pct === null ? "" : ` (${r}${Math.abs(n.pct).toFixed(2)}%)`}`;
3613
+ }
3614
+ function jn(e, t) {
3615
+ let n = L(E(e, 0), E(e, 1), t.source);
3616
+ return [n.bars === null ? "" : `${Me(n.bars)} bars`, Ae(n.dTime)].filter(Boolean).join(", ");
3617
+ }
3618
+ var Mn = B({
3619
+ id: "dateRange",
3620
+ label: "Date range",
3621
+ family: "measure",
3622
+ gesture: "drag",
3623
+ anchors: 2,
3624
+ defaults: () => ({}),
3625
+ validate: H,
3626
+ shapes(e, t) {
3627
+ let [n, r] = O(t, e), i = (n.y + r.y) / 2, a = e.style.color;
3628
+ return [
3629
+ j([
3630
+ {
3631
+ x: n.x,
3632
+ y: 0
3633
+ },
3634
+ {
3635
+ x: r.x,
3636
+ y: 0
3637
+ },
3638
+ {
3639
+ x: r.x,
3640
+ y: t.H
3641
+ },
3642
+ {
3643
+ x: n.x,
3644
+ y: t.H
3645
+ }
3646
+ ], {
3647
+ close: !0,
3648
+ fill: S(a, .1),
3649
+ width: 0
3650
+ }),
3651
+ A({
3652
+ x: n.x,
3653
+ y: 0
3654
+ }, {
3655
+ x: n.x,
3656
+ y: t.H
3657
+ }, {
3658
+ width: 1,
3659
+ color: a
3660
+ }),
3661
+ A({
3662
+ x: r.x,
3663
+ y: 0
3664
+ }, {
3665
+ x: r.x,
3666
+ y: t.H
3667
+ }, {
3668
+ width: 1,
3669
+ color: a
3670
+ }),
3671
+ A({
3672
+ x: n.x,
3673
+ y: i
3674
+ }, {
3675
+ x: r.x,
3676
+ y: i
3677
+ }, {
3678
+ width: 1,
3679
+ color: a
3680
+ }),
3681
+ P({
3682
+ x: n.x,
3683
+ y: i
3684
+ }, {
3685
+ x: r.x,
3686
+ y: i
3687
+ }, 8, a),
3688
+ kn((n.x + r.x) / 2, i - 14, jn(e, t), a)
3689
+ ];
3690
+ }
3691
+ }), Nn = B({
3692
+ id: "priceRange",
3693
+ label: "Price range",
3694
+ family: "measure",
3695
+ gesture: "drag",
3696
+ anchors: 2,
3697
+ defaults: () => ({}),
3698
+ validate: H,
3699
+ shapes(e, t) {
3700
+ let [n, r] = O(t, e), i = (n.x + r.x) / 2, a = On(e, E(e, 1).price - E(e, 0).price);
3701
+ return [
3702
+ j([
3703
+ {
3704
+ x: 0,
3705
+ y: n.y
3706
+ },
3707
+ {
3708
+ x: t.W,
3709
+ y: n.y
3710
+ },
3711
+ {
3712
+ x: t.W,
3713
+ y: r.y
3714
+ },
3715
+ {
3716
+ x: 0,
3717
+ y: r.y
3718
+ }
3719
+ ], {
3720
+ close: !0,
3721
+ fill: S(a, .1),
3722
+ width: 0
3723
+ }),
3724
+ A({
3725
+ x: 0,
3726
+ y: n.y
3727
+ }, {
3728
+ x: t.W,
3729
+ y: n.y
3730
+ }, {
3731
+ width: 1,
3732
+ color: a,
3733
+ extA: !0,
3734
+ extB: !0
3735
+ }),
3736
+ A({
3737
+ x: 0,
3738
+ y: r.y
3739
+ }, {
3740
+ x: t.W,
3741
+ y: r.y
3742
+ }, {
3743
+ width: 1,
3744
+ color: a,
3745
+ extA: !0,
3746
+ extB: !0
3747
+ }),
3748
+ A({
3749
+ x: i,
3750
+ y: n.y
3751
+ }, {
3752
+ x: i,
3753
+ y: r.y
3754
+ }, {
3755
+ width: 1,
3756
+ color: a
3757
+ }),
3758
+ P({
3759
+ x: i,
3760
+ y: n.y
3761
+ }, {
3762
+ x: i,
3763
+ y: r.y
3764
+ }, 8, a),
3765
+ kn(i, (n.y + r.y) / 2, An(e, t), a)
3766
+ ];
3767
+ }
3768
+ }), Pn = B({
3769
+ id: "dateAndPriceRange",
3770
+ label: "Date and price range",
3771
+ family: "measure",
3772
+ gesture: "drag",
3773
+ anchors: 2,
3774
+ defaults: () => ({}),
3775
+ validate: H,
3776
+ shapes(e, t) {
3777
+ let [n, r] = O(t, e), i = On(e, E(e, 1).price - E(e, 0).price), a = (n.x + r.x) / 2, o = (n.y + r.y) / 2;
3778
+ return [
3779
+ j([
3780
+ n,
3781
+ {
3782
+ x: r.x,
3783
+ y: n.y
3784
+ },
3785
+ r,
3786
+ {
3787
+ x: n.x,
3788
+ y: r.y
3789
+ }
3790
+ ], {
3791
+ close: !0,
3792
+ fill: S(i, .12),
3793
+ color: i,
3794
+ width: 1
3795
+ }),
3796
+ A({
3797
+ x: a,
3798
+ y: n.y
3799
+ }, {
3800
+ x: a,
3801
+ y: r.y
3802
+ }, {
3803
+ width: 1,
3804
+ color: i,
3805
+ hit: !1
3806
+ }),
3807
+ P({
3808
+ x: a,
3809
+ y: n.y
3810
+ }, {
3811
+ x: a,
3812
+ y: r.y
3813
+ }, 8, i),
3814
+ A({
3815
+ x: n.x,
3816
+ y: o
3817
+ }, {
3818
+ x: r.x,
3819
+ y: o
3820
+ }, {
3821
+ width: 1,
3822
+ color: i,
3823
+ hit: !1
3824
+ }),
3825
+ P({
3826
+ x: n.x,
3827
+ y: o
3828
+ }, {
3829
+ x: r.x,
3830
+ y: o
3831
+ }, 8, i),
3832
+ kn(a, Math.min(n.y, r.y) - 14, `${An(e, t)}\n${jn(e, t)}`, i)
3833
+ ];
3834
+ }
3835
+ }), Fn = [
3836
+ Mn,
3837
+ Nn,
3838
+ Pn
3839
+ ], Y = (e, t) => Math.abs(t.price - e.price);
3840
+ function In(e, t, n, r, i) {
3841
+ return {
3842
+ abXa: R(Y(t, n), Y(e, t)),
3843
+ bcAb: R(Y(n, r), Y(t, n)),
3844
+ cdBc: R(Y(r, i), Y(n, r)),
3845
+ adXa: R(Y(t, i), Y(e, t))
3846
+ };
3847
+ }
3848
+ function Ln(e, t, n, r, i) {
3849
+ return {
3850
+ abXa: R(Y(t, n), Y(e, t)),
3851
+ xcXa: R(Y(e, r), Y(e, t)),
3852
+ cdXc: R(Y(r, i), Y(e, r))
3853
+ };
3854
+ }
3855
+ function Rn(e, t, n, r) {
3856
+ return {
3857
+ bcAb: R(Y(t, n), Y(e, t)),
3858
+ cdBc: R(Y(n, r), Y(t, n))
3859
+ };
3860
+ }
3861
+ function zn(e) {
3862
+ if (e.length !== 7) throw RangeError(`three drives needs 7 anchors, got ${e.length}`);
3863
+ let t = e;
3864
+ return [
3865
+ R(Y(t[1], t[2]), Y(t[0], t[1])),
3866
+ R(Y(t[2], t[3]), Y(t[1], t[2])),
3867
+ R(Y(t[3], t[4]), Y(t[2], t[3])),
3868
+ R(Y(t[4], t[5]), Y(t[3], t[4])),
3869
+ R(Y(t[5], t[6]), Y(t[4], t[5]))
3870
+ ];
3871
+ }
3872
+ function X(e, t, n) {
3873
+ let r = [];
3874
+ return e.forEach((i, a) => {
3875
+ let o = t[a];
3876
+ if (!o) return;
3877
+ let s = e[a - 1], c = e[a + 1], l = (!s || i.y <= s.y) && (!c || i.y <= c.y);
3878
+ r.push(N(i.x, i.y + (l ? -6 : 6), o, {
3879
+ align: "center",
3880
+ base: l ? "bottom" : "top",
3881
+ textColor: n,
3882
+ hit: !1
3883
+ }));
3884
+ }), r;
3885
+ }
3886
+ var Z = {
3887
+ dash: "dashed",
3888
+ width: 1,
3889
+ hit: !1
3890
+ }, Q = (e, t, n, r) => {
3891
+ let i = F(e, t);
3892
+ return N(i.x, i.y, Pe(n), {
3893
+ align: "center",
3894
+ base: "middle",
3895
+ bg: S(r, .85),
3896
+ textColor: "#ffffff",
3897
+ pad: 2,
3898
+ size: 10,
3899
+ hit: !1
3900
+ });
3901
+ }, Bn = B({
3902
+ id: "xabcd",
3903
+ label: "XABCD pattern",
3904
+ family: "patterns",
3905
+ gesture: "clicks",
3906
+ anchors: 5,
3907
+ defaults: () => ({ style: { fill: "rgba(41,98,255,0.12)" } }),
3908
+ validate: H,
3909
+ shapes(e, t) {
3910
+ let [n, r, i, a, o] = O(t, e), s = In(E(e, 0), E(e, 1), E(e, 2), E(e, 3), E(e, 4)), c = e.style.color;
3911
+ return [
3912
+ M([
3913
+ n,
3914
+ r,
3915
+ i
3916
+ ], e.style.fill ?? S(c, .12)),
3917
+ M([
3918
+ i,
3919
+ a,
3920
+ o
3921
+ ], e.style.fill ?? S(c, .12)),
3922
+ j([
3923
+ n,
3924
+ r,
3925
+ i,
3926
+ a,
3927
+ o
3928
+ ]),
3929
+ A(n, i, Z),
3930
+ A(r, a, Z),
3931
+ A(i, o, Z),
3932
+ A(n, o, Z),
3933
+ Q(n, i, s.abXa, c),
3934
+ Q(r, a, s.bcAb, c),
3935
+ Q(i, o, s.cdBc, c),
3936
+ Q(n, o, s.adXa, c),
3937
+ ...X([
3938
+ n,
3939
+ r,
3940
+ i,
3941
+ a,
3942
+ o
3943
+ ], [
3944
+ "X",
3945
+ "A",
3946
+ "B",
3947
+ "C",
3948
+ "D"
3949
+ ], c)
3950
+ ];
3951
+ }
3952
+ }), Vn = B({
3953
+ id: "cypher",
3954
+ label: "Cypher pattern",
3955
+ family: "patterns",
3956
+ gesture: "clicks",
3957
+ anchors: 5,
3958
+ defaults: () => ({ style: {
3959
+ fill: "rgba(156,39,176,0.12)",
3960
+ color: "#9c27b0"
3961
+ } }),
3962
+ validate: H,
3963
+ shapes(e, t) {
3964
+ let [n, r, i, a, o] = O(t, e), s = Ln(E(e, 0), E(e, 1), E(e, 2), E(e, 3), E(e, 4)), c = e.style.color;
3965
+ return [
3966
+ M([
3967
+ n,
3968
+ r,
3969
+ i
3970
+ ], e.style.fill ?? S(c, .12)),
3971
+ M([
3972
+ i,
3973
+ a,
3974
+ o
3975
+ ], e.style.fill ?? S(c, .12)),
3976
+ j([
3977
+ n,
3978
+ r,
3979
+ i,
3980
+ a,
3981
+ o
3982
+ ]),
3983
+ A(n, i, Z),
3984
+ A(r, a, Z),
3985
+ A(n, a, Z),
3986
+ A(i, o, Z),
3987
+ Q(n, i, s.abXa, c),
3988
+ Q(n, a, s.xcXa, c),
3989
+ Q(i, o, s.cdXc, c),
3990
+ ...X([
3991
+ n,
3992
+ r,
3993
+ i,
3994
+ a,
3995
+ o
3996
+ ], [
3997
+ "X",
3998
+ "A",
3999
+ "B",
4000
+ "C",
4001
+ "D"
4002
+ ], c)
4003
+ ];
4004
+ }
4005
+ }), Hn = B({
4006
+ id: "abcd",
4007
+ label: "ABCD pattern",
4008
+ family: "patterns",
4009
+ gesture: "clicks",
4010
+ anchors: 4,
4011
+ defaults: () => ({}),
4012
+ validate: H,
4013
+ shapes(e, t) {
4014
+ let [n, r, i, a] = O(t, e), o = Rn(E(e, 0), E(e, 1), E(e, 2), E(e, 3)), s = e.style.color;
4015
+ return [
4016
+ j([
4017
+ n,
4018
+ r,
4019
+ i,
4020
+ a
4021
+ ]),
4022
+ A(n, i, Z),
4023
+ A(r, a, Z),
4024
+ Q(n, i, o.bcAb, s),
4025
+ Q(r, a, o.cdBc, s),
4026
+ ...X([
4027
+ n,
4028
+ r,
4029
+ i,
4030
+ a
4031
+ ], [
4032
+ "A",
4033
+ "B",
4034
+ "C",
4035
+ "D"
4036
+ ], s)
4037
+ ];
4038
+ }
4039
+ }), Un = B({
4040
+ id: "trianglePattern",
4041
+ label: "Triangle pattern",
4042
+ family: "patterns",
4043
+ gesture: "clicks",
4044
+ anchors: 4,
4045
+ defaults: () => ({ style: { fill: "rgba(41,98,255,0.1)" } }),
4046
+ validate: H,
4047
+ shapes(e, t) {
4048
+ let [n, r, i, a] = O(t, e), o = e.style.color, s = [
4049
+ j([
4050
+ n,
4051
+ r,
4052
+ i,
4053
+ a
4054
+ ]),
4055
+ A(n, i, {
4056
+ extB: !0,
4057
+ dash: "dashed",
4058
+ width: 1
4059
+ }),
4060
+ A(r, a, {
4061
+ extB: !0,
4062
+ dash: "dashed",
4063
+ width: 1
4064
+ })
4065
+ ], c = _(n, i, r, a);
4066
+ return c && c.x > Math.max(i.x, a.x) && s.unshift(M([
4067
+ n,
4068
+ r,
4069
+ c
4070
+ ], e.style.fill ?? S(o, .1))), [...s, ...X([
4071
+ n,
4072
+ r,
4073
+ i,
4074
+ a
4075
+ ], [
4076
+ "A",
4077
+ "B",
4078
+ "C",
4079
+ "D"
4080
+ ], o)];
4081
+ }
4082
+ }), Wn = B({
4083
+ id: "threeDrives",
4084
+ label: "Three drives pattern",
4085
+ family: "patterns",
4086
+ gesture: "clicks",
4087
+ anchors: 7,
4088
+ defaults: () => ({}),
4089
+ validate: H,
4090
+ shapes(e, t) {
4091
+ let n = O(t, e), r = e.style.color, i = zn(e.anchors), a = [j(n)];
4092
+ return i.forEach((e, t) => a.push(Q(n[t + 1], n[t + 2], e, r))), [...a, ...X(n, [
4093
+ "0",
4094
+ "1",
4095
+ "A",
4096
+ "2",
4097
+ "B",
4098
+ "3",
4099
+ "C"
4100
+ ], r)];
4101
+ }
4102
+ }), Gn = B({
4103
+ id: "headAndShoulders",
4104
+ label: "Head and shoulders",
4105
+ family: "patterns",
4106
+ gesture: "clicks",
4107
+ anchors: 7,
4108
+ defaults: () => ({ style: { fill: "rgba(239,83,80,0.12)" } }),
4109
+ validate: H,
4110
+ shapes(e, t) {
4111
+ let n = O(t, e), [, r, i, a, o, s] = n, c = e.style.color;
4112
+ return [
4113
+ M([
4114
+ i,
4115
+ r,
4116
+ a
4117
+ ], e.style.fill ?? S(c, .12)),
4118
+ M([
4119
+ i,
4120
+ a,
4121
+ o
4122
+ ], e.style.fill ?? S(c, .12)),
4123
+ M([
4124
+ o,
4125
+ a,
4126
+ s
4127
+ ], e.style.fill ?? S(c, .12)),
4128
+ j(n),
4129
+ A(i, o, {
4130
+ extB: !0,
4131
+ dash: "dashed",
4132
+ width: 1
4133
+ }),
4134
+ N(o.x + 6, o.y, "Neckline", {
4135
+ base: "top",
4136
+ size: 10,
4137
+ textColor: c,
4138
+ hit: !1
4139
+ }),
4140
+ ...X(n, [
4141
+ "",
4142
+ "Left shoulder",
4143
+ "",
4144
+ "Head",
4145
+ "",
4146
+ "Right shoulder",
4147
+ ""
4148
+ ], c)
4149
+ ];
4150
+ }
4151
+ });
4152
+ function Kn(e, t) {
4153
+ switch (e) {
4154
+ case "minuette": return `((${t}))`;
4155
+ case "minor": return t;
4156
+ case "intermediate": return `(${t})`;
4157
+ case "primary": return `[${t}]`;
4158
+ }
4159
+ }
4160
+ function $(e, t, n) {
4161
+ return B({
4162
+ id: e,
4163
+ label: t,
4164
+ family: "elliott",
4165
+ gesture: "clicks",
4166
+ anchors: n.length,
4167
+ defaults: () => ({ props: { degree: "intermediate" } }),
4168
+ validate(t) {
4169
+ if (H(t), ![
4170
+ "minuette",
4171
+ "minor",
4172
+ "intermediate",
4173
+ "primary"
4174
+ ].includes(t.props.degree)) throw RangeError(`drawings: ${e} "${t.id}" prop "degree" must be minuette, minor, intermediate or primary`);
4175
+ },
4176
+ shapes(e, t) {
4177
+ let r = O(t, e), i = e.props.degree;
4178
+ return [j(r), ...X(r, n.map((e) => e ? Kn(i, e) : ""), e.style.color)];
4179
+ }
4180
+ });
4181
+ }
4182
+ var qn = $("elliottImpulse", "Elliott impulse wave", [
4183
+ "",
4184
+ "1",
4185
+ "2",
4186
+ "3",
4187
+ "4",
4188
+ "5"
4189
+ ]), Jn = $("elliottCorrection", "Elliott correction wave", [
4190
+ "",
4191
+ "A",
4192
+ "B",
4193
+ "C"
4194
+ ]), Yn = $("elliottTriangle", "Elliott triangle wave", [
4195
+ "",
4196
+ "A",
4197
+ "B",
4198
+ "C",
4199
+ "D",
4200
+ "E"
4201
+ ]), Xn = $("elliottDoubleCombo", "Elliott double combo wave", [
4202
+ "",
4203
+ "W",
4204
+ "X",
4205
+ "Y"
4206
+ ]), Zn = $("elliottTripleCombo", "Elliott triple combo wave", [
4207
+ "",
4208
+ "W",
4209
+ "X",
4210
+ "Y",
4211
+ "X",
4212
+ "Z"
4213
+ ]), Qn = [
4214
+ Bn,
4215
+ Vn,
4216
+ Hn,
4217
+ Un,
4218
+ Wn,
4219
+ Gn,
4220
+ qn,
4221
+ Jn,
4222
+ Yn,
4223
+ Xn,
4224
+ Zn
4225
+ ];
4226
+ //#endregion
4227
+ //#region src/tools/position.ts
4228
+ function $n(e, t, n, r, i = {}) {
4229
+ if (!(e === "long" ? n >= t && t >= r : n <= t && t <= r)) throw RangeError(`position: a ${e} needs ${e === "long" ? "target ≥ entry ≥ stop" : "target ≤ entry ≤ stop"}, got target ${n}, entry ${t}, stop ${r}`);
4230
+ let a = Math.abs(t - r), o = Math.abs(n - t), s = null;
4231
+ if (t === 0) throw RangeError("position: entry price 0 has no percent risk");
4232
+ if (i.accountSize !== void 0 && i.accountSize !== null && a > 0) {
4233
+ let e = i.lotSize, t = i.riskPercent;
4234
+ if (e === void 0 || t === void 0) throw RangeError("position: riskPercent and lotSize are required with accountSize");
4235
+ if (!(i.accountSize > 0) || !(e > 0) || !Number.isInteger(e) || !(t > 0)) throw RangeError(`position: accountSize and riskPercent must be positive and lotSize a positive whole number, got ${i.accountSize}, ${t}, ${e}`);
4236
+ let n = i.accountSize * t / 100, r = Math.floor(n / a / e);
4237
+ (r + 1) * e * a <= n * 1.000000000001 && (r += 1), s = r * e;
4238
+ }
4239
+ return {
4240
+ risk: a,
4241
+ reward: o,
4242
+ rr: a === 0 ? null : o / a,
4243
+ riskPct: a / Math.abs(t) * 100,
4244
+ rewardPct: o / Math.abs(t) * 100,
4245
+ qty: s,
4246
+ profit: s === null ? null : s * o,
4247
+ loss: s === null ? null : s * a
4248
+ };
4249
+ }
4250
+ var er = (e, t, n) => {
4251
+ if (e == null) return null;
4252
+ if (typeof e != "number" || !Number.isFinite(e)) throw TypeError(`drawings: ${n.tool} "${n.id}" prop "${t}" must be a finite number or null`);
4253
+ return e;
4254
+ };
4255
+ function tr(e, t) {
4256
+ return $n(e, E(t, 0).price, E(t, 1).price, E(t, 2).price, {
4257
+ accountSize: er(t.props.accountSize, "accountSize", t),
4258
+ riskPercent: er(t.props.riskPercent, "riskPercent", t) ?? void 0,
4259
+ lotSize: er(t.props.lotSize, "lotSize", t) ?? void 0
4260
+ });
4261
+ }
4262
+ var nr = (e) => e.toFixed(2);
4263
+ function rr(e) {
4264
+ let t = e === "long";
4265
+ return B({
4266
+ id: t ? "longPosition" : "shortPosition",
4267
+ label: t ? "Long position" : "Short position",
4268
+ family: "position",
4269
+ gesture: "clicks",
4270
+ anchors: 3,
4271
+ defaults: () => ({ props: {
4272
+ accountSize: null,
4273
+ riskPercent: 1,
4274
+ lotSize: 1
4275
+ } }),
4276
+ validate(t) {
4277
+ H(t), tr(e, t);
4278
+ },
4279
+ constrain(e, n) {
4280
+ let [r, i, a] = [
4281
+ E(e, 0),
4282
+ E(e, 1),
4283
+ E(e, 2)
4284
+ ];
4285
+ if (n === 1 || n === 2) {
4286
+ let e = n === 1 ? i.time : a.time;
4287
+ i.time = e, a.time = e;
4288
+ }
4289
+ t ? (i.price < r.price && (i.price = r.price), a.price > r.price && (a.price = r.price)) : (i.price > r.price && (i.price = r.price), a.price < r.price && (a.price = r.price));
4290
+ },
4291
+ shapes(t, n) {
4292
+ let r = tr(e, t), [i, a, o] = O(n, t), s = Math.min(i.x, a.x), c = Math.max(i.x, a.x), l = "#26a69a", u = "#ef5350", d = [
4293
+ j([
4294
+ {
4295
+ x: s,
4296
+ y: i.y
4297
+ },
4298
+ {
4299
+ x: c,
4300
+ y: i.y
4301
+ },
4302
+ {
4303
+ x: c,
4304
+ y: a.y
4305
+ },
4306
+ {
4307
+ x: s,
4308
+ y: a.y
4309
+ }
4310
+ ], {
4311
+ close: !0,
4312
+ fill: S(l, .2),
4313
+ width: 0
4314
+ }),
4315
+ j([
4316
+ {
4317
+ x: s,
4318
+ y: i.y
4319
+ },
4320
+ {
4321
+ x: c,
4322
+ y: i.y
4323
+ },
4324
+ {
4325
+ x: c,
4326
+ y: o.y
4327
+ },
4328
+ {
4329
+ x: s,
4330
+ y: o.y
4331
+ }
4332
+ ], {
4333
+ close: !0,
4334
+ fill: S(u, .2),
4335
+ width: 0
4336
+ }),
4337
+ A({
4338
+ x: s,
4339
+ y: i.y
4340
+ }, {
4341
+ x: c,
4342
+ y: i.y
4343
+ }, { color: t.style.color }),
4344
+ A({
4345
+ x: s,
4346
+ y: a.y
4347
+ }, {
4348
+ x: c,
4349
+ y: a.y
4350
+ }, { color: l }),
4351
+ A({
4352
+ x: s,
4353
+ y: o.y
4354
+ }, {
4355
+ x: c,
4356
+ y: o.y
4357
+ }, { color: u })
4358
+ ], f = (e) => `${e < 0 ? "-" : e > 0 ? "+" : ""}${n.fmt(Math.abs(e))}`, p = E(t, 1).price - E(t, 0).price, m = E(t, 2).price - E(t, 0).price, h = [`Target ${n.fmt(E(t, 1).price)} (${f(p)}, ${r.rewardPct.toFixed(2)}%)`];
4359
+ r.profit !== null && h.push(`P&L ${nr(r.profit)}`);
4360
+ let g = [`Stop ${n.fmt(E(t, 2).price)} (${f(m)}, ${r.riskPct.toFixed(2)}%)`];
4361
+ r.loss !== null && g.push(`P&L -${nr(r.loss)}`);
4362
+ let _ = (s + c) / 2;
4363
+ d.push(N(_, (i.y + a.y) / 2, h.join("\n"), {
4364
+ align: "center",
4365
+ base: "middle",
4366
+ textColor: l,
4367
+ hit: !1
4368
+ })), d.push(N(_, (i.y + o.y) / 2, g.join("\n"), {
4369
+ align: "center",
4370
+ base: "middle",
4371
+ textColor: u,
4372
+ hit: !1
4373
+ }));
4374
+ let ee = [`Entry ${n.fmt(E(t, 0).price)}`, r.rr === null ? "R:R n/a" : `R:R ${r.rr.toFixed(2)}`];
4375
+ return r.qty !== null && ee.push(`Qty ${r.qty}`), d.push(N(_, i.y, ee.join(" "), {
4376
+ align: "center",
4377
+ base: "middle",
4378
+ bg: S(t.style.color, .9),
4379
+ textColor: "#ffffff",
4380
+ pad: 3,
4381
+ hit: !1
4382
+ })), d;
4383
+ }
4384
+ });
4385
+ }
4386
+ var ir = rr("long"), ar = rr("short"), or = B({
4387
+ id: "forecast",
4388
+ label: "Forecast",
4389
+ family: "position",
4390
+ gesture: "drag",
4391
+ anchors: 2,
4392
+ defaults: () => ({ style: { fill: "rgba(41,98,255,0.15)" } }),
4393
+ validate: H,
4394
+ shapes(e, t) {
4395
+ let [n, r] = [E(e, 0), E(e, 1)], [i, a] = [D(t, n), D(t, r)], o = L(n, r, t.source);
4396
+ return [
4397
+ M([
4398
+ i,
4399
+ {
4400
+ x: a.x,
4401
+ y: i.y
4402
+ },
4403
+ a
4404
+ ], e.style.fill ?? S(e.style.color, .15)),
4405
+ A(i, {
4406
+ x: a.x,
4407
+ y: i.y
4408
+ }, {
4409
+ dash: "dotted",
4410
+ width: 1,
4411
+ hit: !1
4412
+ }),
4413
+ A({
4414
+ x: a.x,
4415
+ y: i.y
4416
+ }, a, {
4417
+ dash: "dotted",
4418
+ width: 1,
4419
+ hit: !1
4420
+ }),
4421
+ A(i, a, { dash: "dashed" }),
4422
+ {
4423
+ k: "ellipse",
4424
+ cx: a.x,
4425
+ cy: a.y,
4426
+ rx: 4,
4427
+ ry: 4,
4428
+ fill: e.style.color,
4429
+ width: 1
4430
+ },
4431
+ N(a.x + 8, a.y, Ne(o, t).join("\n"), {
4432
+ align: "left",
4433
+ base: "middle",
4434
+ bg: e.style.color,
4435
+ textColor: "#ffffff",
4436
+ pad: 4,
4437
+ hit: !1
4438
+ })
4439
+ ];
4440
+ }
4441
+ });
4442
+ function sr(e, t, n) {
4443
+ return n.price + (t.price - e.price);
4444
+ }
4445
+ var cr = B({
4446
+ id: "projection",
4447
+ label: "Projection",
4448
+ family: "position",
4449
+ gesture: "clicks",
4450
+ anchors: 3,
4451
+ defaults: () => ({}),
4452
+ validate: H,
4453
+ shapes(e, t) {
4454
+ let [n, r, i] = [
4455
+ E(e, 0),
4456
+ E(e, 1),
4457
+ E(e, 2)
4458
+ ], [a, o, s] = O(t, e), c = {
4459
+ x: s.x + (o.x - a.x),
4460
+ y: t.Y(sr(n, r, i))
4461
+ };
4462
+ return [
4463
+ A(a, o),
4464
+ A(s, c, { dash: "dashed" }),
4465
+ A(a, s, {
4466
+ dash: "dotted",
4467
+ width: 1,
4468
+ hit: !1
4469
+ }),
4470
+ A(o, c, {
4471
+ dash: "dotted",
4472
+ width: 1,
4473
+ hit: !1
4474
+ }),
4475
+ {
4476
+ k: "ellipse",
4477
+ cx: c.x,
4478
+ cy: c.y,
4479
+ rx: 3,
4480
+ ry: 3,
4481
+ fill: e.style.color,
4482
+ width: 1
4483
+ },
4484
+ N(c.x + 6, c.y, t.fmt(sr(n, r, i)), {
4485
+ align: "left",
4486
+ base: "middle",
4487
+ textColor: e.style.color,
4488
+ hit: !1
4489
+ })
4490
+ ];
4491
+ }
4492
+ }), lr = "#26a69a", ur = "#ef5350";
4493
+ function dr(e, t, n, r, i, a, o) {
4494
+ let s = a >= n ? lr : ur;
4495
+ if (o) {
4496
+ let o = Math.min(n, a), c = Math.max(n, a);
4497
+ return [A({
4498
+ x: e,
4499
+ y: r
4500
+ }, {
4501
+ x: e,
4502
+ y: i
4503
+ }, {
4504
+ color: s,
4505
+ width: 1
4506
+ }), j([
4507
+ {
4508
+ x: e - t,
4509
+ y: o
4510
+ },
4511
+ {
4512
+ x: e + t,
4513
+ y: o
4514
+ },
4515
+ {
4516
+ x: e + t,
4517
+ y: Math.max(c, o + 1)
4518
+ },
4519
+ {
4520
+ x: e - t,
4521
+ y: Math.max(c, o + 1)
4522
+ }
4523
+ ], {
4524
+ close: !0,
4525
+ fill: s,
4526
+ color: s,
4527
+ width: 1
4528
+ })];
4529
+ }
4530
+ return [
4531
+ A({
4532
+ x: e,
4533
+ y: r
4534
+ }, {
4535
+ x: e,
4536
+ y: i
4537
+ }, {
4538
+ color: s,
4539
+ width: 1
4540
+ }),
4541
+ A({
4542
+ x: e - t,
4543
+ y: n
4544
+ }, {
4545
+ x: e,
4546
+ y: n
4547
+ }, {
4548
+ color: s,
4549
+ width: 1
4550
+ }),
4551
+ A({
4552
+ x: e,
4553
+ y: a
4554
+ }, {
4555
+ x: e + t,
4556
+ y: a
4557
+ }, {
4558
+ color: s,
4559
+ width: 1
4560
+ })
4561
+ ];
4562
+ }
4563
+ function fr(e, t) {
4564
+ if (!e.source) throw Error(`${t} needs a BarSource`);
4565
+ return e.source;
4566
+ }
4567
+ function pr(e, t, n) {
4568
+ let r = fr(e, n), i = E(t, 0).time, a = E(t, 1).time, [o, s] = r.range(Math.min(i, a), Math.max(i, a));
4569
+ if (s <= o) throw RangeError(`${n} "${t.id}": no bars between the first two anchors`);
4570
+ return {
4571
+ src: r,
4572
+ lo: o,
4573
+ hi: s
4574
+ };
4575
+ }
4576
+ function mr(e, t) {
4577
+ let n = e[0];
4578
+ if (!n) throw RangeError("patternBars: no bars");
4579
+ let r = t - n.close;
4580
+ return e.map((e) => ({
4581
+ offsetMs: e.time - n.time,
4582
+ open: e.open + r,
4583
+ high: e.high + r,
4584
+ low: e.low + r,
4585
+ close: e.close + r
4586
+ }));
4587
+ }
4588
+ var hr = B({
4589
+ id: "barsPattern",
4590
+ label: "Bars pattern",
4591
+ family: "position",
4592
+ gesture: "clicks",
4593
+ anchors: 3,
4594
+ needsSource: !0,
4595
+ defaults: () => ({}),
4596
+ validate: H,
4597
+ shapes(e, t) {
4598
+ let { src: n, lo: r, hi: i } = pr(t, e, "barsPattern"), a = [];
4599
+ for (let e = r; e < i; e++) a.push(n.at(e));
4600
+ let o = mr(a, E(e, 2).price), s = t.X(a[0].time), c = t.X(E(e, 2).time), l = Math.max(1, (a.length > 1 ? Math.abs(t.X(a[1].time) - s) : 6) * .35), u = [], d = t.X(E(e, 0).time), f = t.X(E(e, 1).time);
4601
+ u.push(A({
4602
+ x: d,
4603
+ y: 0
4604
+ }, {
4605
+ x: d,
4606
+ y: t.H
4607
+ }, {
4608
+ dash: "dotted",
4609
+ width: 1,
4610
+ extA: !0,
4611
+ extB: !0
4612
+ }), A({
4613
+ x: f,
4614
+ y: 0
4615
+ }, {
4616
+ x: f,
4617
+ y: t.H
4618
+ }, {
4619
+ dash: "dotted",
4620
+ width: 1,
4621
+ extA: !0,
4622
+ extB: !0
4623
+ }));
4624
+ for (let e = 0; e < o.length; e++) {
4625
+ let n = o[e], r = c + (t.X(a[e].time) - s);
4626
+ u.push(...dr(r, l, t.Y(n.open), t.Y(n.high), t.Y(n.low), t.Y(n.close), !1));
4627
+ }
4628
+ return u;
4629
+ }
4630
+ });
4631
+ function gr(e) {
4632
+ let t = e >>> 0;
4633
+ return () => {
4634
+ t = t + 1831565813 >>> 0;
4635
+ let e = t;
4636
+ return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296;
4637
+ };
4638
+ }
4639
+ function _r(e, t, n, r) {
4640
+ if (e.length === 0) throw RangeError("ghostBars: no history to sample");
4641
+ let i = gr(r), a = [], o = t;
4642
+ for (let t = 0; t < n; t++) {
4643
+ let t = e[Math.floor(i() * e.length)], n = o, r = n + (t.close - t.open);
4644
+ a.push({
4645
+ open: n,
4646
+ high: n + (t.high - t.open),
4647
+ low: n + (t.low - t.open),
4648
+ close: r
4649
+ }), o = r;
4650
+ }
4651
+ return a;
4652
+ }
4653
+ var vr = B({
4654
+ id: "ghostFeed",
4655
+ label: "Ghost feed (resampled bars)",
4656
+ family: "position",
4657
+ gesture: "clicks",
4658
+ anchors: 3,
4659
+ needsSource: !0,
4660
+ defaults: () => ({ props: {
4661
+ seed: 1,
4662
+ count: 30
4663
+ } }),
4664
+ validate(e) {
4665
+ H(e);
4666
+ let t = e.props.count, n = e.props.seed;
4667
+ if (typeof t != "number" || !Number.isInteger(t) || t < 1 || t > 5e3) throw RangeError(`drawings: ghostFeed "${e.id}" prop "count" must be an integer in 1..5000`);
4668
+ if (typeof n != "number" || !Number.isInteger(n)) throw RangeError(`drawings: ghostFeed "${e.id}" prop "seed" must be an integer`);
4669
+ },
4670
+ shapes(e, t) {
4671
+ let { src: n, lo: r, hi: i } = pr(t, e, "ghostFeed"), a = [];
4672
+ for (let e = r; e < i; e++) a.push(n.at(e));
4673
+ let o = _r(a, E(e, 2).price, e.props.count, e.props.seed), s = E(e, 2).time, c = Math.max(1, Math.abs(t.X(s + n.interval) - t.X(s)) * .35), l = [];
4674
+ o.forEach((e, r) => l.push(...dr(t.X(s + r * n.interval), c, t.Y(e.open), t.Y(e.high), t.Y(e.low), t.Y(e.close), !0)));
4675
+ let u = D(t, E(e, 2));
4676
+ return l.push(N(u.x, u.y - 6, "ghost feed", {
4677
+ base: "bottom",
4678
+ size: 10,
4679
+ textColor: e.style.color,
4680
+ hit: !1
4681
+ })), l;
4682
+ }
4683
+ }), yr = [
4684
+ ir,
4685
+ ar,
4686
+ or,
4687
+ cr,
4688
+ hr,
4689
+ vr
4690
+ ];
4691
+ //#endregion
4692
+ //#region src/tools/volume.ts
4693
+ function br(e, t) {
4694
+ if (!Number.isInteger(t) || t < 0 || t >= e.length) throw RangeError(`anchoredVwap: start ${t} outside 0..${e.length - 1}`);
4695
+ let n = e.length - t, r = new Float64Array(n), i = new Float64Array(n), a = 0, o = 0;
4696
+ for (let s = 0; s < n; s++) {
4697
+ let n = e.at(t + s);
4698
+ a += (n.high + n.low + n.close) / 3 * n.volume, o += n.volume, r[s] = n.time, i[s] = o === 0 ? NaN : a / o;
4699
+ }
4700
+ return {
4701
+ times: r,
4702
+ values: i
4703
+ };
4704
+ }
4705
+ function xr(e, t) {
4706
+ if (e.length === 0) return null;
4707
+ let [n, r] = e.range(t, t);
4708
+ return r > n ? n : n >= e.length ? null : Math.max(0, n - 1);
4709
+ }
4710
+ var Sr = /* @__PURE__ */ new WeakMap();
4711
+ function Cr(e, t) {
4712
+ let n = Sr.get(e);
4713
+ n || Sr.set(e, n = /* @__PURE__ */ new Map());
4714
+ let r = n.get(t);
4715
+ if (r && r.version === e.version) return r.series;
4716
+ let i = br(e, t);
4717
+ return n.size > 64 && n.clear(), n.set(t, {
4718
+ version: e.version,
4719
+ series: i
4720
+ }), i;
4721
+ }
4722
+ var wr = B({
4723
+ id: "anchoredVwap",
4724
+ label: "Anchored VWAP",
4725
+ family: "volume",
4726
+ gesture: "single",
4727
+ anchors: 1,
4728
+ needsSource: !0,
4729
+ defaults: () => ({ style: { color: "#ff9800" } }),
4730
+ validate: H,
4731
+ shapes(e, t) {
4732
+ if (!t.source) throw Error("anchoredVwap needs a BarSource");
4733
+ let n = D(t, E(e, 0)), r = [{
4734
+ k: "ellipse",
4735
+ cx: n.x,
4736
+ cy: n.y,
4737
+ rx: 4,
4738
+ ry: 4,
4739
+ fill: e.style.color,
4740
+ width: 1
4741
+ }], i = xr(t.source, E(e, 0).time);
4742
+ if (i === null) return r;
4743
+ let a = Cr(t.source, i), o = t.T(-2), s = t.T(t.W + 2), c = (e) => {
4744
+ let t = 0, n = a.times.length;
4745
+ for (; t < n;) {
4746
+ let r = t + n >> 1;
4747
+ a.times[r] < e ? t = r + 1 : n = r;
4748
+ }
4749
+ return t;
4750
+ }, l = Math.max(0, c(o) - 1), u = Math.min(a.times.length, c(s) + 1), d = Math.max(1, Math.floor((u - l) / (t.W + 4))), f = [];
4751
+ for (let e = l; e < u; e += d) Number.isNaN(a.values[e]) || f.push(t.X(a.times[e]), t.Y(a.values[e]));
4752
+ return f.length >= 4 && r.push({
4753
+ k: "poly",
4754
+ pts: f
4755
+ }), r;
4756
+ }
4757
+ });
4758
+ function Tr(e, t, n, r) {
4759
+ if (!Number.isInteger(r) || r < 1) throw RangeError(`volumeProfile: rows must be a positive integer, got ${r}`);
4760
+ if (n <= t) throw RangeError("volumeProfile: no bars in the range");
4761
+ let i = Infinity, a = -Infinity;
4762
+ for (let r = t; r < n; r++) {
4763
+ let t = e.at(r);
4764
+ t.low < i && (i = t.low), t.high > a && (a = t.high);
4765
+ }
4766
+ let o = a - i, s = o / r, c = Array(r).fill(0);
4767
+ for (let a = t; a < n; a++) {
4768
+ let t = e.at(a);
4769
+ if (o === 0 || t.high === t.low) {
4770
+ let e = o === 0 ? 0 : Math.min(r - 1, Math.floor((t.low - i) / s));
4771
+ c[e] += t.volume;
4772
+ continue;
4773
+ }
4774
+ let n = Math.min(r - 1, Math.floor((t.low - i) / s)), l = Math.min(r - 1, Math.floor((t.high - i) / s)), u = t.high - t.low;
4775
+ for (let e = n; e <= l; e++) {
4776
+ let n = Math.min(t.high, i + (e + 1) * s), r = Math.max(t.low, i + e * s);
4777
+ n > r && (c[e] += t.volume * (n - r) / u);
4778
+ }
4779
+ }
4780
+ let l = 0;
4781
+ return c.forEach((e, t) => {
4782
+ e > c[l] && (l = t);
4783
+ }), {
4784
+ low: i,
4785
+ high: a,
4786
+ rowHeight: s,
4787
+ volumes: c,
4788
+ poc: l
4789
+ };
4790
+ }
4791
+ function Er(e, t) {
4792
+ let [n, r] = t.range(Math.min(E(e, 0).time, E(e, 1).time), Math.max(E(e, 0).time, E(e, 1).time));
4793
+ if (r <= n) throw RangeError(`drawings: volumeProfile "${e.id}" has no bars between its anchors`);
4794
+ return [n, r];
4795
+ }
4796
+ var Dr = B({
4797
+ id: "volumeProfile",
4798
+ label: "Fixed range volume profile (bar-level approximation)",
4799
+ family: "volume",
4800
+ gesture: "drag",
4801
+ anchors: 2,
4802
+ needsSource: !0,
4803
+ defaults: () => ({ props: { rows: 24 } }),
4804
+ validate(e) {
4805
+ H(e), V(e, 0, 1);
4806
+ let t = e.props.rows;
4807
+ if (typeof t != "number" || !Number.isInteger(t) || t < 1 || t > 500) throw RangeError(`drawings: volumeProfile "${e.id}" prop "rows" must be an integer in 1..500`);
4808
+ },
4809
+ shapes(e, t) {
4810
+ if (!t.source) throw Error("volumeProfile needs a BarSource");
4811
+ let [n, r] = Er(e, t.source), i = e.props.rows, a = Tr(t.source, n, r, i), o = t.X(E(e, 0).time), s = t.X(E(e, 1).time), c = Math.min(o, s), l = Math.max(o, s), u = (l - c) * .6, d = a.volumes[a.poc], f = [A({
4812
+ x: c,
4813
+ y: 0
4814
+ }, {
4815
+ x: c,
4816
+ y: t.H
4817
+ }, {
4818
+ dash: "dotted",
4819
+ width: 1,
4820
+ extA: !0,
4821
+ extB: !0
4822
+ }), A({
4823
+ x: l,
4824
+ y: 0
4825
+ }, {
4826
+ x: l,
4827
+ y: t.H
4828
+ }, {
4829
+ dash: "dotted",
4830
+ width: 1,
4831
+ extA: !0,
4832
+ extB: !0
4833
+ })];
4834
+ return a.volumes.forEach((n, r) => {
4835
+ if (n === 0 || d === 0) return;
4836
+ let i = t.Y(a.low + (r + 1) * a.rowHeight), o = t.Y(a.low + r * a.rowHeight), s = n / d * u, l = [
4837
+ {
4838
+ x: c,
4839
+ y: i
4840
+ },
4841
+ {
4842
+ x: c + s,
4843
+ y: i
4844
+ },
4845
+ {
4846
+ x: c + s,
4847
+ y: o
4848
+ },
4849
+ {
4850
+ x: c,
4851
+ y: o
4852
+ }
4853
+ ];
4854
+ f.push(j(l, {
4855
+ close: !0,
4856
+ fill: S(r === a.poc ? "#ff9800" : e.style.color, r === a.poc ? .6 : .35),
4857
+ width: 0
4858
+ }));
4859
+ }), f.push(N(c + 4, 4, "Volume profile (bar-level approximation)", {
4860
+ base: "top",
4861
+ size: 10,
4862
+ textColor: e.style.color,
4863
+ hit: !1
4864
+ })), f;
4865
+ }
4866
+ }), Or = [wr, Dr], kr = [
4867
+ ...Dn,
4868
+ ...gt,
4869
+ ...Vt,
4870
+ ..._n,
4871
+ ...rn,
4872
+ ...tt,
4873
+ ...yr,
4874
+ ...Fn,
4875
+ ...Qn,
4876
+ ...wt,
4877
+ ...Or
4878
+ ];
4879
+ //#endregion
4880
+ export { y as AddCommand, Te as ArrayBarSource, ie as BatchCommand, T as DEFAULT_STYLE, be as DRAG_SLOP, Ce as DUPLICATE_BARS, te as DrawingStore, we as DrawingsPlugin, Dt as FIB_SEQUENCE, cn as GANN_RATIOS, ae as History, b as PatchCommand, ne as RemoveCommand, re as ReorderCommand, ye as SCHEMA_VERSION, xe as TOLERANCE, ve as TemplateStore, Se as WEAK_MAGNET_PX, Hn as abcd, Rn as abcdRatios, kr as allTools, Ue as anchoredNote, Be as anchoredText, br as anchoredVwap, wr as anchoredVwapTool, tt as annotationTools, Xt as arc, Yt as arcThrough, Xe as arrow, et as arrowMarkDown, $e as arrowMarkUp, Ze as arrowMarker, hr as barsPattern, tn as brush, We as callout, gt as channelTools, qt as circle, Ge as comment, En as crossLine, Zt as curve, wt as cycleTools, bt as cyclicLines, Vn as cypher, Ln as cypherRatios, Pn as dateAndPriceRange, Mn as dateRange, le as declutter, lt as disjointChannel, Qt as doubleCurve, pe as drawShapes, zn as driveRatios, Jn as elliottCorrection, Xn as elliottDoubleCombo, qn as elliottImpulse, Yn as elliottTriangle, Zn as elliottTripleCombo, Kt as ellipse, bn as extendedLine, jt as fibChannel, It as fibCircles, At as fibExtension, Et as fibExtensionPrice, kt as fibRetracement, Tt as fibRetracementPrice, zt as fibSpeedArcs, Pt as fibSpeedFan, Lt as fibSpiral, Mt as fibTimeZone, Vt as fibTools, Ft as fibTrendTime, Bt as fibWedge, rn as figureTools, Ye as flagMark, ct as flatTopBottom, Ae as fmtDuration, I as fmtTime, or as forecast, ut as forkGeometry, un as gannBox, on as gannBoxPrice, gn as gannFan, sn as gannFanPrice, pn as gannSquare, hn as gannSquareFixed, _n as gannTools, o as geometry, _r as ghostBars, vr as ghostFeed, Gn as headAndShoulders, nn as highlighter, Sn as horizontalLine, wn as horizontalRay, xn as infoLine, mt as insidePitchfork, Dn as lineTools, ir as longPosition, L as measure, Fn as measureTools, pt as modifiedSchiffPitchfork, He as note, it as parallelChannel, en as path, mr as patternBars, Qn as patternTools, ht as pitchfan, dt as pitchfork, $t as polyline, $n as positionStats, yr as positionTools, Ke as priceLabel, qe as priceNote, Nn as priceRange, cr as projection, sr as projectionTarget, yn as ray, Ut as rectangle, at as regression, ot as regressionOf, st as regressionTrendChannel, Wt as rotatedRectCorners, Gt as rotatedRectangle, ft as schiffPitchfork, gr as seeded, he as shapeDistance, ge as shapeInRect, ar as shortPosition, Je as signpost, Ct as sineLine, St as sineY, xr as startIndex, ze as textTool, Wn as threeDrives, xt as timeCycles, vn as trendLine, Jt as triangle, Un as trianglePattern, Tn as verticalLine, Tr as volumeProfile, Dr as volumeProfileTool, Or as volumeTools, Kn as waveLabel, S as withAlpha, Bn as xabcd, In as xabcdRatios };
4881
+
4882
+ //# sourceMappingURL=index.js.map