@alphacharts/drawings 0.0.0-stage → 0.1.0

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