@funnest/charts-ui 0.5.1 → 0.6.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/components/keep-in-view.d.ts +6 -0
- package/dist/context.d.ts +8 -2
- package/dist/i18n.d.ts +42 -0
- package/dist/icons.d.ts +14 -0
- package/dist/index.js +1046 -550
- package/dist/shell.d.ts +4 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -267,6 +267,160 @@ n = { __e: function(n2, t3, r3, u3) {
|
|
|
267
267
|
return n2.__v.__b - t3.__v.__b;
|
|
268
268
|
}, e = /* @__PURE__ */ Symbol(), l = /(PointerCapture)$|Capture$/i, c = 0, a = {}, s = 0;
|
|
269
269
|
|
|
270
|
+
// ../../node_modules/.pnpm/preact@11.2.0/node_modules/preact/hooks/dist/hooks.mjs
|
|
271
|
+
var t2;
|
|
272
|
+
var r2;
|
|
273
|
+
var u2;
|
|
274
|
+
var i2;
|
|
275
|
+
var o2 = Object.is;
|
|
276
|
+
var f2 = 0;
|
|
277
|
+
var c2 = [];
|
|
278
|
+
var e2 = [];
|
|
279
|
+
var a2 = n;
|
|
280
|
+
var v2 = a2.__b;
|
|
281
|
+
var l2 = a2.__r;
|
|
282
|
+
var m2 = a2.diffed;
|
|
283
|
+
var h2 = a2.__c;
|
|
284
|
+
var s2 = a2.unmount;
|
|
285
|
+
var p2 = a2.__;
|
|
286
|
+
function y2(n2, t3) {
|
|
287
|
+
a2.__h && a2.__h(r2, n2, f2 || t3), f2 = 0;
|
|
288
|
+
var u3 = r2.__H || (r2.__H = { __: [], __h: [] });
|
|
289
|
+
return n2 >= u3.__.length && u3.__.push({}), u3.__[n2];
|
|
290
|
+
}
|
|
291
|
+
function d2(n2) {
|
|
292
|
+
return f2 = 1, _2(G2, n2);
|
|
293
|
+
}
|
|
294
|
+
function _2(n2, u3, i3) {
|
|
295
|
+
var f4 = y2(t2++, 2);
|
|
296
|
+
if (f4.t = n2, !f4.__c && (f4.__ = [i3 ? i3(u3) : G2(void 0, u3), function(n3) {
|
|
297
|
+
var t3 = (f4.__N || f4.__)[0], r3 = f4.t(t3, n3);
|
|
298
|
+
o2(t3, r3) || (f4.__N = [r3, f4.__[1]], f4.__c.setState({}));
|
|
299
|
+
}], f4.__c = r2, !r2.__f)) {
|
|
300
|
+
r2.__f = true;
|
|
301
|
+
var c3 = r2.shouldComponentUpdate;
|
|
302
|
+
r2.shouldComponentUpdate = function(n3, t3, r3) {
|
|
303
|
+
var u4 = this.__H;
|
|
304
|
+
if (!u4) return true;
|
|
305
|
+
var i4 = false, f5 = this.props != n3;
|
|
306
|
+
if (u4.__.some(function(n4) {
|
|
307
|
+
n4.__N && (i4 = true, o2(n4.__[0], n4.__N[0]) || (f5 = true));
|
|
308
|
+
}), c3) {
|
|
309
|
+
var e3 = c3.call(this, n3, t3, r3);
|
|
310
|
+
return i4 ? e3 || f5 : e3;
|
|
311
|
+
}
|
|
312
|
+
return !i4 || f5;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return f4.__;
|
|
316
|
+
}
|
|
317
|
+
function A2(n2, u3) {
|
|
318
|
+
var i3 = y2(t2++, 3);
|
|
319
|
+
!a2.__s && E2(i3.__H, u3) && (i3.__P = true, i3.__ = n2, i3.u = u3, r2.__H.__h.push(i3));
|
|
320
|
+
}
|
|
321
|
+
function F2(n2, u3) {
|
|
322
|
+
var i3 = y2(t2++, 4);
|
|
323
|
+
!a2.__s && E2(i3.__H, u3) && (i3.__P = false, i3.__ = n2, i3.u = u3, r2.__h.push(i3));
|
|
324
|
+
}
|
|
325
|
+
function T2(n2) {
|
|
326
|
+
return f2 = 5, w2(function() {
|
|
327
|
+
return { current: n2 };
|
|
328
|
+
}, []);
|
|
329
|
+
}
|
|
330
|
+
function w2(n2, r3) {
|
|
331
|
+
var u3 = y2(t2++, 7);
|
|
332
|
+
return E2(u3.__H, r3) && (u3.__ = n2(), u3.__H = r3), u3.__;
|
|
333
|
+
}
|
|
334
|
+
function g2() {
|
|
335
|
+
var n2;
|
|
336
|
+
do {
|
|
337
|
+
for (; n2 = e2.shift(); ) try {
|
|
338
|
+
C2(n2);
|
|
339
|
+
} catch (t4) {
|
|
340
|
+
a2.__e(t4, { __: (n2 = n2.__P) && n2.__v });
|
|
341
|
+
}
|
|
342
|
+
for (; n2 = c2.shift(); ) {
|
|
343
|
+
var t3 = n2.__H;
|
|
344
|
+
if (n2.__P && t3) try {
|
|
345
|
+
t3.__h.some(C2), t3.__h.some(D2), t3.__h = [];
|
|
346
|
+
} catch (r3) {
|
|
347
|
+
t3.__h = [], a2.__e(r3, n2.__v);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
} while (e2.length);
|
|
351
|
+
}
|
|
352
|
+
a2.__b = function(n2) {
|
|
353
|
+
r2 = null, v2 && v2(n2);
|
|
354
|
+
}, a2.__ = function(n2, t3) {
|
|
355
|
+
n2 && t3.__k && t3.__k.__m && (n2.__m = t3.__k.__m), p2 && p2(n2, t3);
|
|
356
|
+
}, a2.__r = function(n2) {
|
|
357
|
+
l2 && l2(n2), t2 = 0;
|
|
358
|
+
var i3 = (r2 = n2.__c).__H;
|
|
359
|
+
i3 && (u2 == r2 ? r2.__h = [] : (i3.__h.some(C2), i3.__h.some(D2), t2 = 0), i3.__h = [], i3.__.some(function(n3) {
|
|
360
|
+
n3.__N && (n3.__ = n3.__N), n3.u = n3.__N = void 0;
|
|
361
|
+
})), u2 = r2;
|
|
362
|
+
}, a2.diffed = function(n2) {
|
|
363
|
+
m2 && m2(n2);
|
|
364
|
+
var t3 = n2.__c;
|
|
365
|
+
t3 && t3.__H && (t3.__H.__h.length && B2(c2.push(t3)), t3.__H.__.some(function(n3) {
|
|
366
|
+
n3.u && (n3.__H = n3.u);
|
|
367
|
+
})), u2 = r2 = null;
|
|
368
|
+
}, a2.__c = function(n2, t3) {
|
|
369
|
+
t3.some(function(n3) {
|
|
370
|
+
try {
|
|
371
|
+
n3.__h.some(C2), n3.__h = n3.__h.filter(function(n4) {
|
|
372
|
+
return !n4.__ || D2(n4);
|
|
373
|
+
});
|
|
374
|
+
} catch (t4) {
|
|
375
|
+
n3.__h = [function() {
|
|
376
|
+
throw t4;
|
|
377
|
+
}];
|
|
378
|
+
}
|
|
379
|
+
}), h2 && h2(n2, t3);
|
|
380
|
+
}, a2.unmount = function(n2) {
|
|
381
|
+
s2 && s2(n2);
|
|
382
|
+
var t3, r3, u3 = n2.__c;
|
|
383
|
+
u3 && u3.__H && (u3.__H.__.some(function(u4) {
|
|
384
|
+
try {
|
|
385
|
+
if (u4.__P && u4.__c) {
|
|
386
|
+
if (void 0 === r3) {
|
|
387
|
+
for (r3 = n2.__; r3 && (!r3.__c || !r3.__c.__P); ) r3 = r3.__;
|
|
388
|
+
r3 = r3 && r3.__c;
|
|
389
|
+
}
|
|
390
|
+
u4.__P = r3, B2(e2.push(u4));
|
|
391
|
+
} else C2(u4);
|
|
392
|
+
} catch (n3) {
|
|
393
|
+
t3 = n3;
|
|
394
|
+
}
|
|
395
|
+
}), u3.__H = void 0, t3 && a2.__e(t3, u3.__v));
|
|
396
|
+
};
|
|
397
|
+
var k = "function" == typeof requestAnimationFrame;
|
|
398
|
+
function z2(n2) {
|
|
399
|
+
var t3, r3 = function() {
|
|
400
|
+
clearTimeout(u3), k && cancelAnimationFrame(t3), setTimeout(n2);
|
|
401
|
+
}, u3 = setTimeout(r3, 35);
|
|
402
|
+
k && (t3 = requestAnimationFrame(r3));
|
|
403
|
+
}
|
|
404
|
+
function B2(n2) {
|
|
405
|
+
1 != n2 && i2 == a2.requestAnimationFrame || ((i2 = a2.requestAnimationFrame) || z2)(g2);
|
|
406
|
+
}
|
|
407
|
+
function C2(n2) {
|
|
408
|
+
var t3 = r2, u3 = n2.__c;
|
|
409
|
+
"function" == typeof u3 && (n2.__c = void 0, u3()), r2 = t3;
|
|
410
|
+
}
|
|
411
|
+
function D2(n2) {
|
|
412
|
+
var t3 = r2;
|
|
413
|
+
n2.__c = n2.__(), r2 = t3;
|
|
414
|
+
}
|
|
415
|
+
function E2(n2, t3) {
|
|
416
|
+
return !n2 || n2.length != t3.length || t3.some(function(t4, r3) {
|
|
417
|
+
return !o2(t4, n2[r3]);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
function G2(n2, t3) {
|
|
421
|
+
return "function" == typeof t3 ? t3(n2) : t3;
|
|
422
|
+
}
|
|
423
|
+
|
|
270
424
|
// src/i18n.ts
|
|
271
425
|
var STRINGS = {
|
|
272
426
|
ko: {
|
|
@@ -310,6 +464,27 @@ var STRINGS = {
|
|
|
310
464
|
settingLastPrice: "\uD604\uC7AC\uAC00 \uC120",
|
|
311
465
|
settingVolume: "\uAC70\uB798\uB7C9",
|
|
312
466
|
settingNavButtons: "\uD655\uB300\xB7\uC774\uB3D9 \uBC84\uD2BC",
|
|
467
|
+
settingCountdown: "\uBD09 \uB9C8\uAC10\uAE4C\uC9C0 \uB0A8\uC740 \uC2DC\uAC04",
|
|
468
|
+
settingsScale: "\uAC00\uACA9 \uCD95",
|
|
469
|
+
scaleNormal: "\uC77C\uBC18",
|
|
470
|
+
scaleLog: "\uB85C\uADF8",
|
|
471
|
+
scalePercent: "%",
|
|
472
|
+
undo: "\uB418\uB3CC\uB9AC\uAE30",
|
|
473
|
+
redo: "\uB2E4\uC2DC \uC2E4\uD589",
|
|
474
|
+
compare: "\uBE44\uAD50",
|
|
475
|
+
compareSymbol: "\uBE44\uAD50\uD560 \uC885\uBAA9 \uCD94\uAC00",
|
|
476
|
+
removeCompare: "\uBE44\uAD50 \uD574\uC81C",
|
|
477
|
+
replay: "\uB9AC\uD50C\uB808\uC774",
|
|
478
|
+
replayPick: "\uC2DC\uC791\uD560 \uBD09\uC744 \uB204\uB974\uC138\uC694",
|
|
479
|
+
replayPlay: "\uC7AC\uC0DD",
|
|
480
|
+
replayPause: "\uC77C\uC2DC\uC815\uC9C0",
|
|
481
|
+
replayStep: "\uD55C \uBD09 \uC55E\uC73C\uB85C",
|
|
482
|
+
replayExit: "\uB9AC\uD50C\uB808\uC774 \uC885\uB8CC",
|
|
483
|
+
replaySpeed: "\uC18D\uB3C4",
|
|
484
|
+
replayRestart: "\uC2DC\uC791 \uC9C0\uC810 \uB2E4\uC2DC \uACE0\uB974\uAE30",
|
|
485
|
+
replayDone: "\uB05D\uAE4C\uC9C0 \uC7AC\uC0DD\uD588\uC5B4\uC694",
|
|
486
|
+
searchIndicators: "\uC9C0\uD45C \uAC80\uC0C9",
|
|
487
|
+
moreTools: "\uB3C4\uAD6C \uB354 \uBCF4\uAE30",
|
|
313
488
|
settingGridH: "\uAC00\uB85C \uACA9\uC790",
|
|
314
489
|
settingGridV: "\uC138\uB85C \uACA9\uC790",
|
|
315
490
|
resetDefaults: "\uAE30\uBCF8\uAC12\uC73C\uB85C",
|
|
@@ -417,6 +592,27 @@ var STRINGS = {
|
|
|
417
592
|
settingLastPrice: "Last price line",
|
|
418
593
|
settingVolume: "Volume",
|
|
419
594
|
settingNavButtons: "Zoom & scroll buttons",
|
|
595
|
+
settingCountdown: "Time to bar close",
|
|
596
|
+
settingsScale: "Price scale",
|
|
597
|
+
scaleNormal: "Regular",
|
|
598
|
+
scaleLog: "Log",
|
|
599
|
+
scalePercent: "%",
|
|
600
|
+
undo: "Undo",
|
|
601
|
+
redo: "Redo",
|
|
602
|
+
compare: "Compare",
|
|
603
|
+
compareSymbol: "Add symbol to compare",
|
|
604
|
+
removeCompare: "Remove comparison",
|
|
605
|
+
replay: "Replay",
|
|
606
|
+
replayPick: "Click the bar to start from",
|
|
607
|
+
replayPlay: "Play",
|
|
608
|
+
replayPause: "Pause",
|
|
609
|
+
replayStep: "Step forward",
|
|
610
|
+
replayExit: "Exit replay",
|
|
611
|
+
replaySpeed: "Speed",
|
|
612
|
+
replayRestart: "Pick a new start",
|
|
613
|
+
replayDone: "Reached the end",
|
|
614
|
+
searchIndicators: "Search indicators",
|
|
615
|
+
moreTools: "More tools",
|
|
420
616
|
settingGridH: "Horizontal grid",
|
|
421
617
|
settingGridV: "Vertical grid",
|
|
422
618
|
resetDefaults: "Reset",
|
|
@@ -506,19 +702,19 @@ function resolutionLabel(resolution, locale, form = "short") {
|
|
|
506
702
|
}
|
|
507
703
|
|
|
508
704
|
// ../../node_modules/.pnpm/preact@11.2.0/node_modules/preact/jsx-runtime/dist/jsxRuntime.mjs
|
|
509
|
-
var
|
|
510
|
-
var
|
|
511
|
-
function
|
|
705
|
+
var f3 = /* @__PURE__ */ Symbol.for("pv");
|
|
706
|
+
var o3 = 0;
|
|
707
|
+
function a3(t3, e3, n2, u3, a4, i3) {
|
|
512
708
|
e3 || (e3 = {});
|
|
513
709
|
var c3, l3, p3 = e3;
|
|
514
710
|
if ("ref" in p3 && "function" != typeof t3) for (l3 in p3 = {}, e3) "ref" == l3 ? c3 = e3[l3] : p3[l3] = e3[l3];
|
|
515
|
-
var s3 = { type: t3, props: p3, key: n2, ref: c3, __k: null, __: null, __b: 0, __e: null, __c: null, constructor:
|
|
711
|
+
var s3 = { type: t3, props: p3, key: n2, ref: c3, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: f3, __v: --o3, __i: -1, __u: 0 };
|
|
516
712
|
return (a4 || i3) && (s3.__source = a4, s3.__self = i3), n.vnode && n.vnode(s3), s3;
|
|
517
713
|
}
|
|
518
714
|
|
|
519
715
|
// src/icons.tsx
|
|
520
716
|
function Icon({ children, size = 20 }) {
|
|
521
|
-
return /* @__PURE__ */
|
|
717
|
+
return /* @__PURE__ */ a3(
|
|
522
718
|
"svg",
|
|
523
719
|
{
|
|
524
720
|
width: size,
|
|
@@ -534,245 +730,129 @@ function Icon({ children, size = 20 }) {
|
|
|
534
730
|
}
|
|
535
731
|
);
|
|
536
732
|
}
|
|
537
|
-
var SearchIcon = () => /* @__PURE__ */
|
|
538
|
-
/* @__PURE__ */
|
|
539
|
-
/* @__PURE__ */
|
|
733
|
+
var SearchIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
734
|
+
/* @__PURE__ */ a3("circle", { cx: "9", cy: "9", r: "5.5" }),
|
|
735
|
+
/* @__PURE__ */ a3("path", { d: "M13 13l3.5 3.5" })
|
|
540
736
|
] });
|
|
541
|
-
var CloseIcon = () => /* @__PURE__ */
|
|
542
|
-
var CameraIcon = () => /* @__PURE__ */
|
|
543
|
-
/* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
737
|
+
var CloseIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M5.5 5.5l9 9M14.5 5.5l-9 9" }) });
|
|
738
|
+
var CameraIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
739
|
+
/* @__PURE__ */ a3("path", { d: "M3.5 7.2c0-.9.7-1.6 1.6-1.6h1.6l1.2-1.8h4.2l1.2 1.8h1.6c.9 0 1.6.7 1.6 1.6v6.6c0 .9-.7 1.6-1.6 1.6H5.1c-.9 0-1.6-.7-1.6-1.6z" }),
|
|
740
|
+
/* @__PURE__ */ a3("circle", { cx: "10", cy: "10.4", r: "2.6" })
|
|
545
741
|
] });
|
|
546
|
-
var ExpandIcon = () => /* @__PURE__ */
|
|
547
|
-
var CollapseIcon = () => /* @__PURE__ */
|
|
548
|
-
var MinusIcon = () => /* @__PURE__ */
|
|
549
|
-
var PlusIcon = () => /* @__PURE__ */
|
|
550
|
-
var ChevronLeftIcon = () => /* @__PURE__ */
|
|
551
|
-
var ChevronRightIcon = () => /* @__PURE__ */
|
|
552
|
-
var ResetIcon = () => /* @__PURE__ */
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
/* @__PURE__ */
|
|
742
|
+
var ExpandIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M4 8V4h4M16 8V4h-4M4 12v4h4M16 12v4h-4" }) });
|
|
743
|
+
var CollapseIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M8 4v4H4M12 4v4h4M8 16v-4H4M12 16v-4h4" }) });
|
|
744
|
+
var MinusIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M5 10h10" }) });
|
|
745
|
+
var PlusIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M5 10h10M10 5v10" }) });
|
|
746
|
+
var ChevronLeftIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M12 5l-5 5 5 5" }) });
|
|
747
|
+
var ChevronRightIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M8 5l5 5-5 5" }) });
|
|
748
|
+
var ResetIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
749
|
+
/* @__PURE__ */ a3("path", { d: "M4.5 10a5.5 5.5 0 1 0 1.7-4" }),
|
|
750
|
+
/* @__PURE__ */ a3("path", { d: "M4.5 3.5V7H8" })
|
|
555
751
|
] });
|
|
556
|
-
var ToRealtimeIcon = () => /* @__PURE__ */
|
|
557
|
-
var ChevronDownIcon = () => /* @__PURE__ */
|
|
558
|
-
var CursorIcon = () => /* @__PURE__ */
|
|
559
|
-
var TrendLineIcon = () => /* @__PURE__ */
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
562
|
-
/* @__PURE__ */
|
|
752
|
+
var ToRealtimeIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M5 5.5l4.5 4.5L5 14.5M10 5.5l4.5 4.5-4.5 4.5" }) });
|
|
753
|
+
var ChevronDownIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: /* @__PURE__ */ a3("path", { d: "M5 8l5 5 5-5" }) });
|
|
754
|
+
var CursorIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M5 3.5l10 6.2-4.4 1.1-2 4.2z" }) });
|
|
755
|
+
var TrendLineIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
756
|
+
/* @__PURE__ */ a3("path", { d: "M5 15L15 5" }),
|
|
757
|
+
/* @__PURE__ */ a3("circle", { cx: "5", cy: "15", r: "1.6", fill: "currentColor" }),
|
|
758
|
+
/* @__PURE__ */ a3("circle", { cx: "15", cy: "5", r: "1.6", fill: "currentColor" })
|
|
563
759
|
] });
|
|
564
|
-
var HorizontalLineIcon = () => /* @__PURE__ */
|
|
565
|
-
/* @__PURE__ */
|
|
566
|
-
/* @__PURE__ */
|
|
760
|
+
var HorizontalLineIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
761
|
+
/* @__PURE__ */ a3("path", { d: "M3 10h14" }),
|
|
762
|
+
/* @__PURE__ */ a3("circle", { cx: "10", cy: "10", r: "1.6", fill: "currentColor" })
|
|
567
763
|
] });
|
|
568
|
-
var FibonacciIcon = () => /* @__PURE__ */
|
|
569
|
-
var TrashIcon = () => /* @__PURE__ */
|
|
570
|
-
var PencilIcon = () => /* @__PURE__ */
|
|
571
|
-
var CandlesIcon = () => /* @__PURE__ */
|
|
572
|
-
/* @__PURE__ */
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
764
|
+
var FibonacciIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M3 4.5h14M3 8.2h14M3 11.8h14M3 15.5h14" }) });
|
|
765
|
+
var TrashIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M4.5 6h11M8 6V4.5h4V6M6 6l.7 9.5h6.6L14 6" }) });
|
|
766
|
+
var PencilIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M12.8 4.2l3 3L7.5 15.5 4 16l.5-3.5z" }) });
|
|
767
|
+
var CandlesIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
768
|
+
/* @__PURE__ */ a3("path", { d: "M6.5 3.5v13M13.5 3.5v13" }),
|
|
769
|
+
/* @__PURE__ */ a3("rect", { x: "4.5", y: "6", width: "4", height: "6", rx: "0.8", fill: "currentColor" }),
|
|
770
|
+
/* @__PURE__ */ a3("rect", { x: "11.5", y: "8", width: "4", height: "5", rx: "0.8" })
|
|
575
771
|
] });
|
|
576
|
-
var LineChartIcon = () => /* @__PURE__ */
|
|
577
|
-
var AreaChartIcon = () => /* @__PURE__ */
|
|
578
|
-
/* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
772
|
+
var LineChartIcon = () => /* @__PURE__ */ a3(Icon, { children: /* @__PURE__ */ a3("path", { d: "M3 14l4.5-5 3.5 3 6-7" }) });
|
|
773
|
+
var AreaChartIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
774
|
+
/* @__PURE__ */ a3("path", { d: "M3 14l4.5-5 3.5 3 6-7" }),
|
|
775
|
+
/* @__PURE__ */ a3("path", { d: "M3 14l4.5-5 3.5 3 6-7V17H3z", fill: "currentColor", "fill-opacity": "0.25", stroke: "none" })
|
|
580
776
|
] });
|
|
581
|
-
var IndicatorIcon = () => /* @__PURE__ */
|
|
582
|
-
/* @__PURE__ */
|
|
583
|
-
/* @__PURE__ */
|
|
777
|
+
var IndicatorIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
778
|
+
/* @__PURE__ */ a3("path", { d: "M3 15.5l4-5 3 2.5 3.5-5L17 11" }),
|
|
779
|
+
/* @__PURE__ */ a3("path", { d: "M3 4.5v11.5h14" })
|
|
584
780
|
] });
|
|
585
|
-
var GearIcon = () => /* @__PURE__ */
|
|
586
|
-
/* @__PURE__ */
|
|
587
|
-
/* @__PURE__ */
|
|
781
|
+
var GearIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: [
|
|
782
|
+
/* @__PURE__ */ a3("circle", { cx: "10", cy: "10", r: "2.4" }),
|
|
783
|
+
/* @__PURE__ */ a3("path", { d: "M10 3v2M10 15v2M3 10h2M15 10h2M5 5l1.4 1.4M13.6 13.6L15 15M5 15l1.4-1.4M13.6 6.4L15 5" })
|
|
588
784
|
] });
|
|
589
|
-
var SmallCloseIcon = () => /* @__PURE__ */
|
|
590
|
-
var EyeIcon = () => /* @__PURE__ */
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
785
|
+
var SmallCloseIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: /* @__PURE__ */ a3("path", { d: "M6 6l8 8M14 6l-8 8" }) });
|
|
786
|
+
var EyeIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: [
|
|
787
|
+
/* @__PURE__ */ a3("path", { d: "M2 10s3-5.5 8-5.5S18 10 18 10s-3 5.5-8 5.5S2 10 2 10z" }),
|
|
788
|
+
/* @__PURE__ */ a3("circle", { cx: "10", cy: "10", r: "2.3" })
|
|
593
789
|
] });
|
|
594
|
-
var EyeOffIcon = () => /* @__PURE__ */
|
|
595
|
-
var MagnetIcon = () => /* @__PURE__ */
|
|
596
|
-
/* @__PURE__ */
|
|
597
|
-
/* @__PURE__ */
|
|
790
|
+
var EyeOffIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: /* @__PURE__ */ a3("path", { d: "M3 3l14 14M8.2 5a8 8 0 0 1 1.8-.5c5 0 8 5.5 8 5.5a14 14 0 0 1-2.2 2.9M5.4 6.4A14 14 0 0 0 2 10s3 5.5 8 5.5a7.7 7.7 0 0 0 3.6-.9" }) });
|
|
791
|
+
var MagnetIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
792
|
+
/* @__PURE__ */ a3("path", { d: "M5 4h3v6.5a2 2 0 0 0 4 0V4h3v6.5a5 5 0 0 1-10 0z" }),
|
|
793
|
+
/* @__PURE__ */ a3("path", { d: "M5 7h3M12 7h3" })
|
|
598
794
|
] });
|
|
599
|
-
var StarIcon = ({ filled = false }) => /* @__PURE__ */
|
|
795
|
+
var StarIcon = ({ filled = false }) => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3(
|
|
600
796
|
"path",
|
|
601
797
|
{
|
|
602
798
|
d: "M10 3.2l2.1 4.3 4.7.7-3.4 3.3.8 4.7L10 14l-4.2 2.2.8-4.7-3.4-3.3 4.7-.7z",
|
|
603
799
|
fill: filled ? "currentColor" : "none"
|
|
604
800
|
}
|
|
605
801
|
) });
|
|
606
|
-
var CollapseLeftIcon = () => /* @__PURE__ */
|
|
607
|
-
var SettingsIcon = () => /* @__PURE__ */
|
|
608
|
-
/* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
802
|
+
var CollapseLeftIcon = () => /* @__PURE__ */ a3(Icon, { size: 14, children: /* @__PURE__ */ a3("path", { d: "M11 5l-5 5 5 5M15 5l-5 5 5 5" }) });
|
|
803
|
+
var SettingsIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
804
|
+
/* @__PURE__ */ a3("path", { d: "M10 12.6a2.6 2.6 0 1 0 0-5.2 2.6 2.6 0 0 0 0 5.2z" }),
|
|
805
|
+
/* @__PURE__ */ a3("path", { d: "M16.2 12a1.3 1.3 0 0 0 .26 1.43l.05.05a1.6 1.6 0 1 1-2.26 2.26l-.05-.05a1.3 1.3 0 0 0-1.43-.26 1.3 1.3 0 0 0-.79 1.19v.14a1.6 1.6 0 0 1-3.2 0v-.07a1.3 1.3 0 0 0-.85-1.19 1.3 1.3 0 0 0-1.43.26l-.05.05a1.6 1.6 0 1 1-2.26-2.26l.05-.05A1.3 1.3 0 0 0 4.5 12a1.3 1.3 0 0 0-1.19-.79h-.14a1.6 1.6 0 0 1 0-3.2h.07a1.3 1.3 0 0 0 1.19-.85 1.3 1.3 0 0 0-.26-1.43l-.05-.05a1.6 1.6 0 1 1 2.26-2.26l.05.05a1.3 1.3 0 0 0 1.43.26h.06a1.3 1.3 0 0 0 .79-1.19v-.14a1.6 1.6 0 0 1 3.2 0v.07a1.3 1.3 0 0 0 .79 1.19 1.3 1.3 0 0 0 1.43-.26l.05-.05a1.6 1.6 0 1 1 2.26 2.26l-.05.05a1.3 1.3 0 0 0-.26 1.43v.06a1.3 1.3 0 0 0 1.19.79h.14a1.6 1.6 0 0 1 0 3.2h-.07a1.3 1.3 0 0 0-1.19.79z" })
|
|
610
806
|
] });
|
|
611
|
-
var FunnestMark = () => /* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
/* @__PURE__ */
|
|
807
|
+
var FunnestMark = () => /* @__PURE__ */ a3("svg", { width: "20", height: "20", viewBox: "0 0 32 32", fill: "none", "aria-hidden": "true", children: [
|
|
808
|
+
/* @__PURE__ */ a3("rect", { width: "32", height: "32", rx: "9", fill: "#6C4DFF" }),
|
|
809
|
+
/* @__PURE__ */ a3("path", { d: "M7 13.5C9.5 21.5 17 23.5 23.4 11.2", stroke: "#fff", "stroke-width": "3.2", "stroke-linecap": "round" }),
|
|
810
|
+
/* @__PURE__ */ a3("circle", { cx: "24.6", cy: "8.6", r: "2.9", fill: "#FFD43B" })
|
|
615
811
|
] });
|
|
616
|
-
var LinkIcon = () => /* @__PURE__ */
|
|
617
|
-
/* @__PURE__ */
|
|
618
|
-
/* @__PURE__ */
|
|
812
|
+
var LinkIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
813
|
+
/* @__PURE__ */ a3("path", { d: "M8.5 11.5a3 3 0 0 0 4.2 0l2.6-2.6a3 3 0 0 0-4.2-4.2l-1 1" }),
|
|
814
|
+
/* @__PURE__ */ a3("path", { d: "M11.5 8.5a3 3 0 0 0-4.2 0l-2.6 2.6a3 3 0 0 0 4.2 4.2l1-1" })
|
|
619
815
|
] });
|
|
620
|
-
var MaximizeIcon = () => /* @__PURE__ */
|
|
621
|
-
var RestoreIcon = () => /* @__PURE__ */
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
var
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
var
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
var
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
var
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
if (!u4) return true;
|
|
658
|
-
var i4 = false, f5 = this.props != n3;
|
|
659
|
-
if (u4.__.some(function(n4) {
|
|
660
|
-
n4.__N && (i4 = true, o3(n4.__[0], n4.__N[0]) || (f5 = true));
|
|
661
|
-
}), c3) {
|
|
662
|
-
var e3 = c3.call(this, n3, t3, r3);
|
|
663
|
-
return i4 ? e3 || f5 : e3;
|
|
664
|
-
}
|
|
665
|
-
return !i4 || f5;
|
|
666
|
-
};
|
|
816
|
+
var MaximizeIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M11 4h5v5M9 16H4v-5M16 4l-5 5M4 16l5-5" }) });
|
|
817
|
+
var RestoreIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M15 9h-4V5M5 11h4v4M11 9l5-5M9 11l-5 5" }) });
|
|
818
|
+
var UndoIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
819
|
+
/* @__PURE__ */ a3("path", { d: "M7 5L3.5 8.5 7 12" }),
|
|
820
|
+
/* @__PURE__ */ a3("path", { d: "M3.5 8.5h8.5a4.5 4.5 0 0 1 0 9H9" })
|
|
821
|
+
] });
|
|
822
|
+
var RedoIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
823
|
+
/* @__PURE__ */ a3("path", { d: "M13 5l3.5 3.5L13 12" }),
|
|
824
|
+
/* @__PURE__ */ a3("path", { d: "M16.5 8.5H8a4.5 4.5 0 0 0 0 9h3" })
|
|
825
|
+
] });
|
|
826
|
+
var CompareIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
827
|
+
/* @__PURE__ */ a3("path", { d: "M3 14l4-4 3 2 7-7" }),
|
|
828
|
+
/* @__PURE__ */ a3("path", { d: "M3 9l4 2 3-3 7 5", opacity: "0.55" })
|
|
829
|
+
] });
|
|
830
|
+
var ReplayIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
831
|
+
/* @__PURE__ */ a3("path", { d: "M5 4v12" }),
|
|
832
|
+
/* @__PURE__ */ a3("path", { d: "M16 4.5v11L8 10z" })
|
|
833
|
+
] });
|
|
834
|
+
var PlayIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M6 4.5v11l9-5.5z", fill: "currentColor" }) });
|
|
835
|
+
var PauseIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: /* @__PURE__ */ a3("path", { d: "M7 4.5v11M13 4.5v11", "stroke-width": "2.4" }) });
|
|
836
|
+
var StepIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
837
|
+
/* @__PURE__ */ a3("path", { d: "M4.5 4.5v11l8-5.5z" }),
|
|
838
|
+
/* @__PURE__ */ a3("path", { d: "M15.5 4.5v11" })
|
|
839
|
+
] });
|
|
840
|
+
var SvgIcon = ({ markup }) => markup.trim().startsWith("<svg") ? /* @__PURE__ */ a3("span", { class: "fnc-svg-icon", dangerouslySetInnerHTML: { __html: markup } }) : /* @__PURE__ */ a3(
|
|
841
|
+
"svg",
|
|
842
|
+
{
|
|
843
|
+
width: 20,
|
|
844
|
+
height: 20,
|
|
845
|
+
viewBox: "0 0 20 20",
|
|
846
|
+
fill: "none",
|
|
847
|
+
stroke: "currentColor",
|
|
848
|
+
"stroke-width": "1.6",
|
|
849
|
+
"stroke-linecap": "round",
|
|
850
|
+
"stroke-linejoin": "round",
|
|
851
|
+
"aria-hidden": "true",
|
|
852
|
+
dangerouslySetInnerHTML: { __html: markup }
|
|
667
853
|
}
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
function A2(n2, u3) {
|
|
671
|
-
var i3 = y2(t2++, 3);
|
|
672
|
-
!a3.__s && E2(i3.__H, u3) && (i3.__P = true, i3.__ = n2, i3.u = u3, r2.__H.__h.push(i3));
|
|
673
|
-
}
|
|
674
|
-
function F2(n2, u3) {
|
|
675
|
-
var i3 = y2(t2++, 4);
|
|
676
|
-
!a3.__s && E2(i3.__H, u3) && (i3.__P = false, i3.__ = n2, i3.u = u3, r2.__h.push(i3));
|
|
677
|
-
}
|
|
678
|
-
function T2(n2) {
|
|
679
|
-
return f3 = 5, w2(function() {
|
|
680
|
-
return { current: n2 };
|
|
681
|
-
}, []);
|
|
682
|
-
}
|
|
683
|
-
function w2(n2, r3) {
|
|
684
|
-
var u3 = y2(t2++, 7);
|
|
685
|
-
return E2(u3.__H, r3) && (u3.__ = n2(), u3.__H = r3), u3.__;
|
|
686
|
-
}
|
|
687
|
-
function g2() {
|
|
688
|
-
var n2;
|
|
689
|
-
do {
|
|
690
|
-
for (; n2 = e2.shift(); ) try {
|
|
691
|
-
C2(n2);
|
|
692
|
-
} catch (t4) {
|
|
693
|
-
a3.__e(t4, { __: (n2 = n2.__P) && n2.__v });
|
|
694
|
-
}
|
|
695
|
-
for (; n2 = c2.shift(); ) {
|
|
696
|
-
var t3 = n2.__H;
|
|
697
|
-
if (n2.__P && t3) try {
|
|
698
|
-
t3.__h.some(C2), t3.__h.some(D2), t3.__h = [];
|
|
699
|
-
} catch (r3) {
|
|
700
|
-
t3.__h = [], a3.__e(r3, n2.__v);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
} while (e2.length);
|
|
704
|
-
}
|
|
705
|
-
a3.__b = function(n2) {
|
|
706
|
-
r2 = null, v2 && v2(n2);
|
|
707
|
-
}, a3.__ = function(n2, t3) {
|
|
708
|
-
n2 && t3.__k && t3.__k.__m && (n2.__m = t3.__k.__m), p2 && p2(n2, t3);
|
|
709
|
-
}, a3.__r = function(n2) {
|
|
710
|
-
l2 && l2(n2), t2 = 0;
|
|
711
|
-
var i3 = (r2 = n2.__c).__H;
|
|
712
|
-
i3 && (u2 == r2 ? r2.__h = [] : (i3.__h.some(C2), i3.__h.some(D2), t2 = 0), i3.__h = [], i3.__.some(function(n3) {
|
|
713
|
-
n3.__N && (n3.__ = n3.__N), n3.u = n3.__N = void 0;
|
|
714
|
-
})), u2 = r2;
|
|
715
|
-
}, a3.diffed = function(n2) {
|
|
716
|
-
m2 && m2(n2);
|
|
717
|
-
var t3 = n2.__c;
|
|
718
|
-
t3 && t3.__H && (t3.__H.__h.length && B2(c2.push(t3)), t3.__H.__.some(function(n3) {
|
|
719
|
-
n3.u && (n3.__H = n3.u);
|
|
720
|
-
})), u2 = r2 = null;
|
|
721
|
-
}, a3.__c = function(n2, t3) {
|
|
722
|
-
t3.some(function(n3) {
|
|
723
|
-
try {
|
|
724
|
-
n3.__h.some(C2), n3.__h = n3.__h.filter(function(n4) {
|
|
725
|
-
return !n4.__ || D2(n4);
|
|
726
|
-
});
|
|
727
|
-
} catch (t4) {
|
|
728
|
-
n3.__h = [function() {
|
|
729
|
-
throw t4;
|
|
730
|
-
}];
|
|
731
|
-
}
|
|
732
|
-
}), h2 && h2(n2, t3);
|
|
733
|
-
}, a3.unmount = function(n2) {
|
|
734
|
-
s2 && s2(n2);
|
|
735
|
-
var t3, r3, u3 = n2.__c;
|
|
736
|
-
u3 && u3.__H && (u3.__H.__.some(function(u4) {
|
|
737
|
-
try {
|
|
738
|
-
if (u4.__P && u4.__c) {
|
|
739
|
-
if (void 0 === r3) {
|
|
740
|
-
for (r3 = n2.__; r3 && (!r3.__c || !r3.__c.__P); ) r3 = r3.__;
|
|
741
|
-
r3 = r3 && r3.__c;
|
|
742
|
-
}
|
|
743
|
-
u4.__P = r3, B2(e2.push(u4));
|
|
744
|
-
} else C2(u4);
|
|
745
|
-
} catch (n3) {
|
|
746
|
-
t3 = n3;
|
|
747
|
-
}
|
|
748
|
-
}), u3.__H = void 0, t3 && a3.__e(t3, u3.__v));
|
|
749
|
-
};
|
|
750
|
-
var k = "function" == typeof requestAnimationFrame;
|
|
751
|
-
function z2(n2) {
|
|
752
|
-
var t3, r3 = function() {
|
|
753
|
-
clearTimeout(u3), k && cancelAnimationFrame(t3), setTimeout(n2);
|
|
754
|
-
}, u3 = setTimeout(r3, 35);
|
|
755
|
-
k && (t3 = requestAnimationFrame(r3));
|
|
756
|
-
}
|
|
757
|
-
function B2(n2) {
|
|
758
|
-
1 != n2 && i2 == a3.requestAnimationFrame || ((i2 = a3.requestAnimationFrame) || z2)(g2);
|
|
759
|
-
}
|
|
760
|
-
function C2(n2) {
|
|
761
|
-
var t3 = r2, u3 = n2.__c;
|
|
762
|
-
"function" == typeof u3 && (n2.__c = void 0, u3()), r2 = t3;
|
|
763
|
-
}
|
|
764
|
-
function D2(n2) {
|
|
765
|
-
var t3 = r2;
|
|
766
|
-
n2.__c = n2.__(), r2 = t3;
|
|
767
|
-
}
|
|
768
|
-
function E2(n2, t3) {
|
|
769
|
-
return !n2 || n2.length != t3.length || t3.some(function(t4, r3) {
|
|
770
|
-
return !o3(t4, n2[r3]);
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
function G2(n2, t3) {
|
|
774
|
-
return "function" == typeof t3 ? t3(n2) : t3;
|
|
775
|
-
}
|
|
854
|
+
);
|
|
855
|
+
var CornerIcon = () => /* @__PURE__ */ a3("svg", { width: "6", height: "6", viewBox: "0 0 6 6", "aria-hidden": "true", children: /* @__PURE__ */ a3("path", { d: "M6 0v6H0z", fill: "currentColor" }) });
|
|
776
856
|
|
|
777
857
|
// src/store.ts
|
|
778
858
|
var Store = class {
|
|
@@ -811,22 +891,71 @@ function useStore(store) {
|
|
|
811
891
|
}
|
|
812
892
|
|
|
813
893
|
// src/components/drawing-toolbar.tsx
|
|
814
|
-
var
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
894
|
+
var BUILTIN_ICONS = {
|
|
895
|
+
trendline: TrendLineIcon,
|
|
896
|
+
horizontal: HorizontalLineIcon,
|
|
897
|
+
fibonacci: FibonacciIcon
|
|
898
|
+
};
|
|
899
|
+
function ToolIcon({ def, locale }) {
|
|
900
|
+
const Builtin = BUILTIN_ICONS[def.type];
|
|
901
|
+
if (Builtin) return /* @__PURE__ */ a3(Builtin, {});
|
|
902
|
+
if (def.icon) return /* @__PURE__ */ a3(SvgIcon, { markup: def.icon });
|
|
903
|
+
return /* @__PURE__ */ a3("span", { class: "fnc-tool-letter", children: def.name[locale].slice(0, 1) });
|
|
904
|
+
}
|
|
905
|
+
function toolGroups(defs) {
|
|
906
|
+
const groups = /* @__PURE__ */ new Map();
|
|
907
|
+
for (const def of defs) {
|
|
908
|
+
const key = def.group ?? def.type;
|
|
909
|
+
groups.set(key, [...groups.get(key) ?? [], def]);
|
|
910
|
+
}
|
|
911
|
+
return [...groups];
|
|
912
|
+
}
|
|
913
|
+
function ToolGroup({
|
|
914
|
+
ctx,
|
|
915
|
+
tools,
|
|
916
|
+
open,
|
|
917
|
+
onOpen,
|
|
918
|
+
onPick
|
|
919
|
+
}) {
|
|
920
|
+
const s3 = useStore(ctx.store);
|
|
921
|
+
const t3 = STRINGS[s3.locale];
|
|
922
|
+
const [chosen, setChosen] = d2(tools[0].type);
|
|
923
|
+
const armed = tools.find((d3) => d3.type === s3.drawingTool);
|
|
924
|
+
const current = armed ?? tools.find((d3) => d3.type === chosen) ?? tools[0];
|
|
925
|
+
const name = current.name[s3.locale];
|
|
926
|
+
const ref = T2(null);
|
|
927
|
+
A2(() => {
|
|
928
|
+
if (!open) return;
|
|
929
|
+
const close = (e3) => !ref.current?.contains(e3.target) && onOpen(false);
|
|
930
|
+
document.addEventListener("pointerdown", close, true);
|
|
931
|
+
return () => document.removeEventListener("pointerdown", close, true);
|
|
932
|
+
}, [open]);
|
|
933
|
+
const pick = (def) => {
|
|
934
|
+
setChosen(def.type);
|
|
935
|
+
onOpen(false);
|
|
936
|
+
onPick(def.type);
|
|
937
|
+
};
|
|
938
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-tool-group", ref, "data-open": open, children: [
|
|
939
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn", "data-tip": name, "aria-label": name, "aria-pressed": !!armed, onClick: () => pick(current), children: /* @__PURE__ */ a3(ToolIcon, { def: current, locale: s3.locale }) }),
|
|
940
|
+
tools.length > 1 && /* @__PURE__ */ a3("button", { class: "fnc-tool-more", "aria-label": `${t3.moreTools}: ${name}`, "aria-haspopup": "menu", "aria-expanded": open, onClick: () => onOpen(!open), children: /* @__PURE__ */ a3(CornerIcon, {}) }),
|
|
941
|
+
open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-tool-menu", role: "menu", children: tools.map((def) => /* @__PURE__ */ a3("button", { class: "fnc-menu-item", role: "menuitemradio", "aria-checked": def.type === current.type, onClick: () => pick(def), children: [
|
|
942
|
+
/* @__PURE__ */ a3(ToolIcon, { def, locale: s3.locale }),
|
|
943
|
+
/* @__PURE__ */ a3("span", { children: def.name[s3.locale] })
|
|
944
|
+
] })) })
|
|
945
|
+
] });
|
|
946
|
+
}
|
|
820
947
|
function DrawingToolbar({ ctx }) {
|
|
821
948
|
const s3 = useStore(ctx.store);
|
|
822
949
|
const t3 = STRINGS[s3.locale];
|
|
950
|
+
const [openGroup, setOpenGroup] = d2(null);
|
|
951
|
+
const groups = toolGroups(ctx.chart.drawingDefinitions());
|
|
823
952
|
const pick = (tool) => {
|
|
824
953
|
ctx.chart.setDrawingTool(tool);
|
|
825
954
|
if (tool && ctx.store.get().drawbarOpen) ctx.store.set({ drawbarOpen: false });
|
|
826
955
|
};
|
|
827
|
-
return /* @__PURE__ */
|
|
828
|
-
s3.drawbarCollapsed && /* @__PURE__ */
|
|
829
|
-
/* @__PURE__ */
|
|
956
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
957
|
+
s3.drawbarCollapsed && /* @__PURE__ */ a3("button", { class: "fnc-drawbar-tab", "aria-label": t3.expandDrawbar, "data-tip": t3.expandDrawbar, onClick: () => ctx.setDrawbarCollapsed(false), children: /* @__PURE__ */ a3(ChevronRightIcon, {}) }),
|
|
958
|
+
/* @__PURE__ */ a3(
|
|
830
959
|
"div",
|
|
831
960
|
{
|
|
832
961
|
class: "fnc-drawbar",
|
|
@@ -836,49 +965,50 @@ function DrawingToolbar({ ctx }) {
|
|
|
836
965
|
"data-open": s3.drawbarOpen,
|
|
837
966
|
"data-collapsed": s3.drawbarCollapsed,
|
|
838
967
|
children: [
|
|
839
|
-
|
|
840
|
-
|
|
968
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn", "data-tip": t3.cursor, "aria-label": t3.cursor, "aria-pressed": s3.drawingTool === null, onClick: () => pick(null), children: /* @__PURE__ */ a3(CursorIcon, {}) }),
|
|
969
|
+
groups.map(([key, tools]) => /* @__PURE__ */ a3(
|
|
970
|
+
ToolGroup,
|
|
841
971
|
{
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
972
|
+
ctx,
|
|
973
|
+
tools,
|
|
974
|
+
open: openGroup === key,
|
|
975
|
+
onOpen: (open) => setOpenGroup(open ? key : null),
|
|
976
|
+
onPick: pick
|
|
977
|
+
},
|
|
978
|
+
key
|
|
849
979
|
)),
|
|
850
|
-
/* @__PURE__ */
|
|
851
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ a3("div", { class: "fnc-hsep" }),
|
|
981
|
+
/* @__PURE__ */ a3(
|
|
852
982
|
"button",
|
|
853
983
|
{
|
|
854
984
|
class: "fnc-btn",
|
|
855
|
-
|
|
985
|
+
"data-tip": t3.magnet,
|
|
856
986
|
"aria-label": t3.magnet,
|
|
857
987
|
"aria-pressed": s3.magnet,
|
|
858
988
|
onClick: () => ctx.chart.setMagnet(!s3.magnet),
|
|
859
|
-
children: /* @__PURE__ */
|
|
989
|
+
children: /* @__PURE__ */ a3(MagnetIcon, {})
|
|
860
990
|
}
|
|
861
991
|
),
|
|
862
|
-
/* @__PURE__ */
|
|
992
|
+
/* @__PURE__ */ a3(
|
|
863
993
|
"button",
|
|
864
994
|
{
|
|
865
995
|
class: "fnc-btn",
|
|
866
|
-
|
|
996
|
+
"data-tip": t3.removeAll,
|
|
867
997
|
"aria-label": t3.removeAll,
|
|
868
998
|
disabled: s3.drawingCount === 0,
|
|
869
999
|
onClick: () => ctx.chart.clearDrawings(),
|
|
870
|
-
children: /* @__PURE__ */
|
|
1000
|
+
children: /* @__PURE__ */ a3(TrashIcon, {})
|
|
871
1001
|
}
|
|
872
1002
|
),
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
1003
|
+
/* @__PURE__ */ a3("span", { class: "fnc-spacer" }),
|
|
1004
|
+
/* @__PURE__ */ a3(
|
|
875
1005
|
"button",
|
|
876
1006
|
{
|
|
877
1007
|
class: "fnc-btn fnc-drawbar-collapse",
|
|
878
|
-
|
|
1008
|
+
"data-tip": t3.collapseDrawbar,
|
|
879
1009
|
"aria-label": t3.collapseDrawbar,
|
|
880
1010
|
onClick: () => ctx.setDrawbarCollapsed(true),
|
|
881
|
-
children: /* @__PURE__ */
|
|
1011
|
+
children: /* @__PURE__ */ a3(ChevronLeftIcon, {})
|
|
882
1012
|
}
|
|
883
1013
|
)
|
|
884
1014
|
]
|
|
@@ -892,23 +1022,49 @@ function SelectionBar({ ctx }) {
|
|
|
892
1022
|
const t3 = STRINGS[s3.locale];
|
|
893
1023
|
const d3 = s3.selection;
|
|
894
1024
|
if (!d3 || s3.layout.plotWidth <= 0) return null;
|
|
895
|
-
return /* @__PURE__ */
|
|
896
|
-
SWATCHES.map((color) => /* @__PURE__ */
|
|
1025
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-selbar", role: "toolbar", style: { left: `${s3.layout.plotWidth / 2}px` }, children: [
|
|
1026
|
+
SWATCHES.map((color) => /* @__PURE__ */ a3(
|
|
897
1027
|
"button",
|
|
898
1028
|
{
|
|
899
1029
|
class: "fnc-swatch",
|
|
900
1030
|
style: { background: color },
|
|
901
|
-
|
|
1031
|
+
"data-tip": t3.color,
|
|
902
1032
|
"aria-label": `${t3.color} ${color}`,
|
|
903
1033
|
"aria-pressed": (d3.color ?? SWATCHES[0]) === color,
|
|
904
1034
|
onClick: () => ctx.chart.updateDrawing(d3.id, { color })
|
|
905
1035
|
}
|
|
906
1036
|
)),
|
|
907
|
-
/* @__PURE__ */
|
|
908
|
-
/* @__PURE__ */
|
|
1037
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sep" }),
|
|
1038
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn", "data-tip": t3.remove, "aria-label": t3.remove, onClick: () => ctx.chart.removeDrawing(d3.id), children: /* @__PURE__ */ a3(TrashIcon, {}) })
|
|
909
1039
|
] });
|
|
910
1040
|
}
|
|
911
1041
|
|
|
1042
|
+
// src/components/keep-in-view.ts
|
|
1043
|
+
var MARGIN = 8;
|
|
1044
|
+
function useKeepInView(open) {
|
|
1045
|
+
const ref = T2(null);
|
|
1046
|
+
F2(() => {
|
|
1047
|
+
const el = ref.current;
|
|
1048
|
+
if (!open || !el) return;
|
|
1049
|
+
el.style.translate = "";
|
|
1050
|
+
const fit = () => {
|
|
1051
|
+
el.style.translate = "";
|
|
1052
|
+
const r3 = el.getBoundingClientRect();
|
|
1053
|
+
const root = el.closest(".fnc-root")?.getBoundingClientRect();
|
|
1054
|
+
const minX = Math.max(0, root?.left ?? 0) + MARGIN;
|
|
1055
|
+
const maxX = Math.min(document.documentElement.clientWidth, root?.right ?? Infinity) - MARGIN;
|
|
1056
|
+
let dx = 0;
|
|
1057
|
+
if (r3.right > maxX) dx = maxX - r3.right;
|
|
1058
|
+
if (r3.left + dx < minX) dx = minX - r3.left;
|
|
1059
|
+
if (dx) el.style.translate = `${Math.round(dx)}px 0`;
|
|
1060
|
+
};
|
|
1061
|
+
fit();
|
|
1062
|
+
window.addEventListener("resize", fit);
|
|
1063
|
+
return () => window.removeEventListener("resize", fit);
|
|
1064
|
+
}, [open]);
|
|
1065
|
+
return ref;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
912
1068
|
// src/components/chart-type-menu.tsx
|
|
913
1069
|
var TYPES = [
|
|
914
1070
|
{ type: "candles", label: "candles", icon: CandlesIcon },
|
|
@@ -920,6 +1076,7 @@ function ChartTypeMenu({ ctx }) {
|
|
|
920
1076
|
const t3 = STRINGS[s3.locale];
|
|
921
1077
|
const [open, setOpen] = d2(false);
|
|
922
1078
|
const ref = T2(null);
|
|
1079
|
+
const menuRef = useKeepInView(open);
|
|
923
1080
|
const current = TYPES.find((x2) => x2.type === s3.chartType) ?? TYPES[0];
|
|
924
1081
|
A2(() => {
|
|
925
1082
|
if (!open) return;
|
|
@@ -937,23 +1094,23 @@ function ChartTypeMenu({ ctx }) {
|
|
|
937
1094
|
ctx.store.set({ chartType: type });
|
|
938
1095
|
setOpen(false);
|
|
939
1096
|
};
|
|
940
|
-
return /* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
1097
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-menu-wrap fnc-chart-type", ref, children: [
|
|
1098
|
+
/* @__PURE__ */ a3(
|
|
942
1099
|
"button",
|
|
943
1100
|
{
|
|
944
1101
|
class: "fnc-btn fnc-btn-wide",
|
|
945
|
-
|
|
1102
|
+
"data-tip": t3.chartType,
|
|
946
1103
|
"aria-label": t3.chartType,
|
|
947
1104
|
"aria-haspopup": "menu",
|
|
948
1105
|
"aria-expanded": open,
|
|
949
1106
|
onClick: () => setOpen(!open),
|
|
950
1107
|
children: [
|
|
951
|
-
/* @__PURE__ */
|
|
952
|
-
/* @__PURE__ */
|
|
1108
|
+
/* @__PURE__ */ a3(current.icon, {}),
|
|
1109
|
+
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
953
1110
|
]
|
|
954
1111
|
}
|
|
955
1112
|
),
|
|
956
|
-
open && /* @__PURE__ */
|
|
1113
|
+
open && /* @__PURE__ */ a3("div", { class: "fnc-menu", role: "menu", ref: menuRef, children: TYPES.map(({ type, label, icon: Icon2 }) => /* @__PURE__ */ a3(
|
|
957
1114
|
"button",
|
|
958
1115
|
{
|
|
959
1116
|
class: "fnc-menu-item",
|
|
@@ -961,8 +1118,8 @@ function ChartTypeMenu({ ctx }) {
|
|
|
961
1118
|
"aria-checked": type === s3.chartType,
|
|
962
1119
|
onClick: () => choose(type),
|
|
963
1120
|
children: [
|
|
964
|
-
/* @__PURE__ */
|
|
965
|
-
/* @__PURE__ */
|
|
1121
|
+
/* @__PURE__ */ a3(Icon2, {}),
|
|
1122
|
+
/* @__PURE__ */ a3("span", { children: t3[label] })
|
|
966
1123
|
]
|
|
967
1124
|
}
|
|
968
1125
|
)) })
|
|
@@ -971,7 +1128,6 @@ function ChartTypeMenu({ ctx }) {
|
|
|
971
1128
|
|
|
972
1129
|
// src/components/indicator-dialogs.tsx
|
|
973
1130
|
import {
|
|
974
|
-
INDICATORS,
|
|
975
1131
|
maLines,
|
|
976
1132
|
PRICE_SOURCES,
|
|
977
1133
|
SERIES_COLORS
|
|
@@ -992,6 +1148,7 @@ var SECTIONS = [
|
|
|
992
1148
|
toggles: [
|
|
993
1149
|
{ key: "highLowMarkers", label: "settingHighLow" },
|
|
994
1150
|
{ key: "lastPriceLine", label: "settingLastPrice" },
|
|
1151
|
+
{ key: "countdown", label: "settingCountdown" },
|
|
995
1152
|
{ key: "volume", label: "settingVolume" },
|
|
996
1153
|
{ key: "navigationButtons", label: "settingNavButtons" }
|
|
997
1154
|
]
|
|
@@ -1004,6 +1161,11 @@ var SECTIONS = [
|
|
|
1004
1161
|
]
|
|
1005
1162
|
}
|
|
1006
1163
|
];
|
|
1164
|
+
var SCALES = [
|
|
1165
|
+
{ mode: "normal", label: "scaleNormal" },
|
|
1166
|
+
{ mode: "log", label: "scaleLog" },
|
|
1167
|
+
{ mode: "percent", label: "scalePercent" }
|
|
1168
|
+
];
|
|
1007
1169
|
function SettingsDialog({ ctx }) {
|
|
1008
1170
|
const { locale } = useStore(ctx.store);
|
|
1009
1171
|
const t3 = STRINGS[locale];
|
|
@@ -1012,16 +1174,16 @@ function SettingsDialog({ ctx }) {
|
|
|
1012
1174
|
const close = () => ctx.store.set({ dialog: null });
|
|
1013
1175
|
const set = (patch) => ctx.chart.setSettings(patch);
|
|
1014
1176
|
const themeColor = (name) => toHex(getComputedStyle(ctx.root).getPropertyValue(name).trim());
|
|
1015
|
-
return /* @__PURE__ */
|
|
1016
|
-
/* @__PURE__ */
|
|
1017
|
-
/* @__PURE__ */
|
|
1018
|
-
/* @__PURE__ */
|
|
1177
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-backdrop", onPointerDown: (e3) => e3.target === e3.currentTarget && close(), children: /* @__PURE__ */ a3("div", { class: "fnc-dialog", role: "dialog", "aria-modal": "true", "aria-label": t3.chartSettings, onKeyDown: (e3) => e3.key === "Escape" && close(), children: [
|
|
1178
|
+
/* @__PURE__ */ a3("div", { class: "fnc-dialog-head", children: [
|
|
1179
|
+
/* @__PURE__ */ a3("b", { children: t3.chartSettings }),
|
|
1180
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn", "aria-label": t3.close, onClick: close, children: /* @__PURE__ */ a3(CloseIcon, {}) })
|
|
1019
1181
|
] }),
|
|
1020
|
-
/* @__PURE__ */
|
|
1021
|
-
/* @__PURE__ */
|
|
1022
|
-
["upColor", "downColor"].map((key) => /* @__PURE__ */
|
|
1023
|
-
/* @__PURE__ */
|
|
1024
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ a3("form", { class: "fnc-form", onSubmit: (e3) => (e3.preventDefault(), close()), children: [
|
|
1183
|
+
/* @__PURE__ */ a3("div", { class: "fnc-section", children: t3.settingsCandles }),
|
|
1184
|
+
["upColor", "downColor"].map((key) => /* @__PURE__ */ a3("label", { class: "fnc-row", children: [
|
|
1185
|
+
/* @__PURE__ */ a3("span", { class: "fnc-row-label fnc-row-label-wide", children: key === "upColor" ? t3.settingUpColor : t3.settingDownColor }),
|
|
1186
|
+
/* @__PURE__ */ a3(
|
|
1025
1187
|
"input",
|
|
1026
1188
|
{
|
|
1027
1189
|
type: "color",
|
|
@@ -1030,13 +1192,24 @@ function SettingsDialog({ ctx }) {
|
|
|
1030
1192
|
onInput: (e3) => set({ [key]: e3.currentTarget.value })
|
|
1031
1193
|
}
|
|
1032
1194
|
),
|
|
1033
|
-
settings[key] && /* @__PURE__ */
|
|
1195
|
+
settings[key] && /* @__PURE__ */ a3("button", { type: "button", class: "fnc-link", onClick: () => set({ [key]: null }), children: t3.followTheme })
|
|
1034
1196
|
] })),
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1197
|
+
/* @__PURE__ */ a3("div", { class: "fnc-section", children: t3.settingsScale }),
|
|
1198
|
+
/* @__PURE__ */ a3("div", { class: "fnc-row", children: /* @__PURE__ */ a3("div", { class: "fnc-seg", role: "radiogroup", "aria-label": t3.settingsScale, children: SCALES.map(({ mode, label }) => /* @__PURE__ */ a3(
|
|
1199
|
+
"button",
|
|
1200
|
+
{
|
|
1201
|
+
type: "button",
|
|
1202
|
+
role: "radio",
|
|
1203
|
+
"aria-checked": settings.priceScale === mode,
|
|
1204
|
+
onClick: () => set({ priceScale: mode }),
|
|
1205
|
+
children: t3[label]
|
|
1206
|
+
}
|
|
1207
|
+
)) }) }),
|
|
1208
|
+
SECTIONS.map((section) => /* @__PURE__ */ a3($, { children: [
|
|
1209
|
+
/* @__PURE__ */ a3("div", { class: "fnc-section", children: t3[section.title] }),
|
|
1210
|
+
section.toggles.map(({ key, label }) => /* @__PURE__ */ a3("label", { class: "fnc-row fnc-toggle-row", children: [
|
|
1211
|
+
/* @__PURE__ */ a3("span", { children: t3[label] }),
|
|
1212
|
+
/* @__PURE__ */ a3(
|
|
1040
1213
|
"input",
|
|
1041
1214
|
{
|
|
1042
1215
|
type: "checkbox",
|
|
@@ -1048,9 +1221,9 @@ function SettingsDialog({ ctx }) {
|
|
|
1048
1221
|
)
|
|
1049
1222
|
] }))
|
|
1050
1223
|
] })),
|
|
1051
|
-
/* @__PURE__ */
|
|
1052
|
-
/* @__PURE__ */
|
|
1053
|
-
/* @__PURE__ */
|
|
1224
|
+
/* @__PURE__ */ a3("div", { class: "fnc-form-actions", children: [
|
|
1225
|
+
/* @__PURE__ */ a3("button", { type: "button", class: "fnc-action fnc-action-danger", onClick: () => ctx.chart.setSettings(DEFAULT_CHART_SETTINGS), children: t3.resetDefaults }),
|
|
1226
|
+
/* @__PURE__ */ a3("button", { type: "submit", class: "fnc-action fnc-action-primary", children: t3.done })
|
|
1054
1227
|
] })
|
|
1055
1228
|
] })
|
|
1056
1229
|
] }) });
|
|
@@ -1062,7 +1235,7 @@ function Dialog({ title, onClose, children, wide }) {
|
|
|
1062
1235
|
A2(() => {
|
|
1063
1236
|
ref.current?.querySelector("input, button.fnc-sr-row")?.focus();
|
|
1064
1237
|
}, []);
|
|
1065
|
-
return /* @__PURE__ */
|
|
1238
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-backdrop", onPointerDown: (e3) => e3.target === e3.currentTarget && onClose(), children: /* @__PURE__ */ a3(
|
|
1066
1239
|
"div",
|
|
1067
1240
|
{
|
|
1068
1241
|
class: wide ? "fnc-dialog fnc-dialog-wide" : "fnc-dialog",
|
|
@@ -1072,49 +1245,71 @@ function Dialog({ title, onClose, children, wide }) {
|
|
|
1072
1245
|
ref,
|
|
1073
1246
|
onKeyDown: (e3) => e3.key === "Escape" && onClose(),
|
|
1074
1247
|
children: [
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1077
|
-
/* @__PURE__ */
|
|
1248
|
+
/* @__PURE__ */ a3("div", { class: "fnc-dialog-head", children: [
|
|
1249
|
+
/* @__PURE__ */ a3("b", { children: title }),
|
|
1250
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn", "aria-label": "close", onClick: onClose, children: /* @__PURE__ */ a3(CloseIcon, {}) })
|
|
1078
1251
|
] }),
|
|
1079
1252
|
children
|
|
1080
1253
|
]
|
|
1081
1254
|
}
|
|
1082
1255
|
) });
|
|
1083
1256
|
}
|
|
1257
|
+
var SEARCH_THRESHOLD = 8;
|
|
1084
1258
|
function IndicatorPicker({ ctx }) {
|
|
1085
1259
|
const { locale } = useStore(ctx.store);
|
|
1086
1260
|
const t3 = STRINGS[locale];
|
|
1261
|
+
const [query, setQuery] = d2("");
|
|
1087
1262
|
const close = () => ctx.store.set({ dialog: null });
|
|
1088
1263
|
const add = (type) => {
|
|
1089
1264
|
ctx.chart.addIndicator(type);
|
|
1090
1265
|
close();
|
|
1091
1266
|
};
|
|
1267
|
+
const all = ctx.chart.indicatorDefinitions();
|
|
1268
|
+
const q2 = query.trim().toLowerCase();
|
|
1269
|
+
const matches = (d3) => !q2 || [d3.type, d3.name.ko, d3.name.en, d3.description[locale]].some((s3) => s3.toLowerCase().includes(q2));
|
|
1092
1270
|
const groups = [
|
|
1093
|
-
[locale === "ko" ? "\uAC00\uACA9 \uCC28\uD2B8\uC5D0 \uD45C\uC2DC" : "On price",
|
|
1094
|
-
[locale === "ko" ? "\uC544\uB798 \uC601\uC5ED\uC5D0 \uD45C\uC2DC" : "Separate pane",
|
|
1095
|
-
];
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1271
|
+
[locale === "ko" ? "\uAC00\uACA9 \uCC28\uD2B8\uC5D0 \uD45C\uC2DC" : "On price", all.filter((d3) => d3.overlay && matches(d3))],
|
|
1272
|
+
[locale === "ko" ? "\uC544\uB798 \uC601\uC5ED\uC5D0 \uD45C\uC2DC" : "Separate pane", all.filter((d3) => !d3.overlay && matches(d3))]
|
|
1273
|
+
].filter(([, defs]) => defs.length > 0);
|
|
1274
|
+
const first = groups[0]?.[1][0];
|
|
1275
|
+
return /* @__PURE__ */ a3(Dialog, { title: t3.addIndicator, onClose: close, children: [
|
|
1276
|
+
all.length > SEARCH_THRESHOLD && /* @__PURE__ */ a3("div", { class: "fnc-search fnc-ind-search", children: /* @__PURE__ */ a3(
|
|
1277
|
+
"input",
|
|
1278
|
+
{
|
|
1279
|
+
value: query,
|
|
1280
|
+
placeholder: t3.searchIndicators,
|
|
1281
|
+
"aria-label": t3.searchIndicators,
|
|
1282
|
+
autocomplete: "off",
|
|
1283
|
+
onInput: (e3) => setQuery(e3.currentTarget.value),
|
|
1284
|
+
onKeyDown: (e3) => e3.key === "Enter" && first && add(first.type)
|
|
1285
|
+
}
|
|
1286
|
+
) }),
|
|
1287
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-list fnc-scroll", children: [
|
|
1288
|
+
groups.length === 0 && /* @__PURE__ */ a3("div", { class: "fnc-empty", children: t3.noResults }),
|
|
1289
|
+
groups.map(([label, defs]) => /* @__PURE__ */ a3($, { children: [
|
|
1290
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-section", children: label }),
|
|
1291
|
+
defs.map((def) => {
|
|
1292
|
+
const type = def.type;
|
|
1293
|
+
return /* @__PURE__ */ a3("button", { class: "fnc-sr-row", onClick: () => add(type), children: /* @__PURE__ */ a3("span", { class: "fnc-sr-main", children: [
|
|
1294
|
+
/* @__PURE__ */ a3("span", { class: "fnc-sr-name", children: def.name[locale] }),
|
|
1295
|
+
/* @__PURE__ */ a3("span", { class: "fnc-sr-meta", children: def.description[locale] })
|
|
1296
|
+
] }) });
|
|
1297
|
+
})
|
|
1298
|
+
] }))
|
|
1299
|
+
] })
|
|
1300
|
+
] });
|
|
1106
1301
|
}
|
|
1107
1302
|
var WIDTHS = [1, 2, 3, 4];
|
|
1108
|
-
function defaultSeries(
|
|
1109
|
-
return
|
|
1303
|
+
function defaultSeries(def, params) {
|
|
1304
|
+
return def.compute([], params).series.filter((s3) => s3.kind === "line");
|
|
1110
1305
|
}
|
|
1111
1306
|
function StyleControls({
|
|
1112
1307
|
t: t3,
|
|
1113
1308
|
row: row2,
|
|
1114
1309
|
onChange
|
|
1115
1310
|
}) {
|
|
1116
|
-
return /* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1311
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
1312
|
+
/* @__PURE__ */ a3(
|
|
1118
1313
|
"input",
|
|
1119
1314
|
{
|
|
1120
1315
|
type: "checkbox",
|
|
@@ -1124,7 +1319,7 @@ function StyleControls({
|
|
|
1124
1319
|
onChange: (e3) => onChange({ visible: e3.currentTarget.checked })
|
|
1125
1320
|
}
|
|
1126
1321
|
),
|
|
1127
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ a3(
|
|
1128
1323
|
"input",
|
|
1129
1324
|
{
|
|
1130
1325
|
type: "color",
|
|
@@ -1134,24 +1329,24 @@ function StyleControls({
|
|
|
1134
1329
|
onInput: (e3) => onChange({ color: e3.currentTarget.value })
|
|
1135
1330
|
}
|
|
1136
1331
|
),
|
|
1137
|
-
/* @__PURE__ */
|
|
1332
|
+
/* @__PURE__ */ a3("select", { class: "fnc-select fnc-select-width", value: row2.width, "aria-label": t3.lineWidth, onChange: (e3) => onChange({ width: Number(e3.currentTarget.value) }), children: WIDTHS.map((w3) => /* @__PURE__ */ a3("option", { value: w3, children: [
|
|
1138
1333
|
w3,
|
|
1139
1334
|
"px"
|
|
1140
1335
|
] })) })
|
|
1141
1336
|
] });
|
|
1142
1337
|
}
|
|
1143
1338
|
function SourceSelect({ value, locale, label, onChange }) {
|
|
1144
|
-
return /* @__PURE__ */
|
|
1339
|
+
return /* @__PURE__ */ a3("select", { class: "fnc-select fnc-select-source", value, "aria-label": label, onChange: (e3) => onChange(e3.currentTarget.value), children: PRICE_SOURCES.map((s3) => /* @__PURE__ */ a3("option", { value: s3.value, children: s3.label[locale] })) });
|
|
1145
1340
|
}
|
|
1146
1341
|
function IndicatorSettings({ ctx, id }) {
|
|
1147
1342
|
const { locale, indicators } = useStore(ctx.store);
|
|
1148
1343
|
const t3 = STRINGS[locale];
|
|
1149
1344
|
const config = indicators.find((c3) => c3.id === id);
|
|
1150
|
-
const def = config ?
|
|
1345
|
+
const def = config ? ctx.chart.indicatorDefinition(config.type) ?? null : null;
|
|
1151
1346
|
const hasLines = !!def?.params.some((p3) => p3.kind === "lines");
|
|
1152
1347
|
const [lines, setLines] = d2(() => {
|
|
1153
|
-
if (!config || !hasLines) return [];
|
|
1154
|
-
const defaults = defaultSeries(
|
|
1348
|
+
if (!config || !def || !hasLines) return [];
|
|
1349
|
+
const defaults = defaultSeries(def, config.params);
|
|
1155
1350
|
return maLines(config.params).map((l3, i3) => {
|
|
1156
1351
|
const style = config.styles?.[`l${i3}`];
|
|
1157
1352
|
return {
|
|
@@ -1167,8 +1362,8 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1167
1362
|
() => Object.fromEntries(Object.entries(config?.params ?? {}).filter(([, v3]) => !Array.isArray(v3)).map(([k2, v3]) => [k2, String(v3)]))
|
|
1168
1363
|
);
|
|
1169
1364
|
const [styles, setStyles] = d2(() => {
|
|
1170
|
-
if (!config || hasLines) return [];
|
|
1171
|
-
return defaultSeries(
|
|
1365
|
+
if (!config || !def || hasLines) return [];
|
|
1366
|
+
return defaultSeries(def, config.params).map((s3) => {
|
|
1172
1367
|
const style = config.styles?.[s3.key];
|
|
1173
1368
|
return { key: s3.key, label: s3.label, color: style?.color ?? s3.color, width: style?.width ?? s3.width, visible: style?.visible ?? true };
|
|
1174
1369
|
});
|
|
@@ -1211,16 +1406,16 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1211
1406
|
ctx.chart.updateIndicator(id, { params, styles: nextStyles });
|
|
1212
1407
|
close();
|
|
1213
1408
|
};
|
|
1214
|
-
return /* @__PURE__ */
|
|
1215
|
-
hasLines ? /* @__PURE__ */
|
|
1216
|
-
lines.map((l3, i3) => /* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1409
|
+
return /* @__PURE__ */ a3(Dialog, { title: `${def.name[locale]} \xB7 ${t3.indicatorSettings}`, onClose: close, wide: true, children: /* @__PURE__ */ a3("form", { class: "fnc-form", onSubmit: apply, children: [
|
|
1410
|
+
hasLines ? /* @__PURE__ */ a3("div", { class: "fnc-rows", children: [
|
|
1411
|
+
lines.map((l3, i3) => /* @__PURE__ */ a3("div", { class: "fnc-row", children: [
|
|
1412
|
+
/* @__PURE__ */ a3("span", { class: "fnc-row-label", children: [
|
|
1218
1413
|
t3.period,
|
|
1219
1414
|
i3 + 1
|
|
1220
1415
|
] }),
|
|
1221
|
-
/* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
/* @__PURE__ */
|
|
1416
|
+
/* @__PURE__ */ a3(StyleControls, { t: t3, row: l3, onChange: (p3) => updateLine(i3, p3) }),
|
|
1417
|
+
/* @__PURE__ */ a3(SourceSelect, { value: l3.source, locale, label: t3.source, onChange: (source) => updateLine(i3, { source }) }),
|
|
1418
|
+
/* @__PURE__ */ a3(
|
|
1224
1419
|
"input",
|
|
1225
1420
|
{
|
|
1226
1421
|
class: "fnc-input fnc-input-period",
|
|
@@ -1230,17 +1425,17 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1230
1425
|
onInput: (e3) => updateLine(i3, { period: e3.currentTarget.value.replace(/\D/g, "") })
|
|
1231
1426
|
}
|
|
1232
1427
|
),
|
|
1233
|
-
/* @__PURE__ */
|
|
1428
|
+
/* @__PURE__ */ a3("button", { type: "button", class: "fnc-ind-btn", "aria-label": t3.removePeriod, "data-tip": t3.removePeriod, onClick: () => setLines(lines.filter((_3, j2) => j2 !== i3)), children: /* @__PURE__ */ a3(SmallCloseIcon, {}) })
|
|
1234
1429
|
] })),
|
|
1235
|
-
/* @__PURE__ */
|
|
1430
|
+
/* @__PURE__ */ a3("button", { type: "button", class: "fnc-add-row", onClick: addLine, children: [
|
|
1236
1431
|
"+ ",
|
|
1237
1432
|
t3.addPeriod
|
|
1238
1433
|
] })
|
|
1239
|
-
] }) : /* @__PURE__ */
|
|
1240
|
-
/* @__PURE__ */
|
|
1241
|
-
def.params.map((spec) => /* @__PURE__ */
|
|
1242
|
-
/* @__PURE__ */
|
|
1243
|
-
spec.kind === "source" ? /* @__PURE__ */
|
|
1434
|
+
] }) : /* @__PURE__ */ a3($, { children: [
|
|
1435
|
+
/* @__PURE__ */ a3("div", { class: "fnc-section", children: t3.inputs }),
|
|
1436
|
+
def.params.map((spec) => /* @__PURE__ */ a3("div", { class: "fnc-row", children: [
|
|
1437
|
+
/* @__PURE__ */ a3("span", { class: "fnc-row-label fnc-row-label-wide", children: spec.label[locale] }),
|
|
1438
|
+
spec.kind === "source" ? /* @__PURE__ */ a3(
|
|
1244
1439
|
SourceSelect,
|
|
1245
1440
|
{
|
|
1246
1441
|
value: values[spec.key] ?? "close",
|
|
@@ -1248,7 +1443,7 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1248
1443
|
label: spec.label[locale],
|
|
1249
1444
|
onChange: (v3) => setValues({ ...values, [spec.key]: v3 })
|
|
1250
1445
|
}
|
|
1251
|
-
) : /* @__PURE__ */
|
|
1446
|
+
) : /* @__PURE__ */ a3(
|
|
1252
1447
|
"input",
|
|
1253
1448
|
{
|
|
1254
1449
|
class: "fnc-input",
|
|
@@ -1259,14 +1454,14 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1259
1454
|
}
|
|
1260
1455
|
)
|
|
1261
1456
|
] })),
|
|
1262
|
-
styles.length > 0 && /* @__PURE__ */
|
|
1263
|
-
styles.map((row2, i3) => /* @__PURE__ */
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1457
|
+
styles.length > 0 && /* @__PURE__ */ a3("div", { class: "fnc-section", children: t3.style }),
|
|
1458
|
+
styles.map((row2, i3) => /* @__PURE__ */ a3("div", { class: "fnc-row", children: [
|
|
1459
|
+
/* @__PURE__ */ a3("span", { class: "fnc-row-label fnc-row-label-wide", children: row2.label }),
|
|
1460
|
+
/* @__PURE__ */ a3(StyleControls, { t: t3, row: row2, onChange: (p3) => setStyles(styles.map((s3, j2) => j2 === i3 ? { ...s3, ...p3 } : s3)) })
|
|
1266
1461
|
] }))
|
|
1267
1462
|
] }),
|
|
1268
|
-
/* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1463
|
+
/* @__PURE__ */ a3("div", { class: "fnc-form-actions", children: [
|
|
1464
|
+
/* @__PURE__ */ a3(
|
|
1270
1465
|
"button",
|
|
1271
1466
|
{
|
|
1272
1467
|
type: "button",
|
|
@@ -1278,16 +1473,16 @@ function IndicatorSettings({ ctx, id }) {
|
|
|
1278
1473
|
children: t3.remove
|
|
1279
1474
|
}
|
|
1280
1475
|
),
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
/* @__PURE__ */
|
|
1476
|
+
/* @__PURE__ */ a3("button", { type: "button", class: "fnc-action", onClick: close, children: t3.cancel }),
|
|
1477
|
+
/* @__PURE__ */ a3("button", { type: "submit", class: "fnc-action fnc-action-primary", children: t3.apply })
|
|
1283
1478
|
] })
|
|
1284
1479
|
] }) });
|
|
1285
1480
|
}
|
|
1286
1481
|
function Dialogs({ ctx }) {
|
|
1287
1482
|
const { dialog } = useStore(ctx.store);
|
|
1288
|
-
if (dialog?.kind === "indicators") return /* @__PURE__ */
|
|
1289
|
-
if (dialog?.kind === "indicatorSettings") return /* @__PURE__ */
|
|
1290
|
-
if (dialog?.kind === "chartSettings") return /* @__PURE__ */
|
|
1483
|
+
if (dialog?.kind === "indicators") return /* @__PURE__ */ a3(IndicatorPicker, { ctx });
|
|
1484
|
+
if (dialog?.kind === "indicatorSettings") return /* @__PURE__ */ a3(IndicatorSettings, { ctx, id: dialog.id });
|
|
1485
|
+
if (dialog?.kind === "chartSettings") return /* @__PURE__ */ a3(SettingsDialog, { ctx });
|
|
1291
1486
|
return null;
|
|
1292
1487
|
}
|
|
1293
1488
|
|
|
@@ -1302,6 +1497,7 @@ function IntervalPicker({ ctx }) {
|
|
|
1302
1497
|
const t3 = STRINGS[s3.locale];
|
|
1303
1498
|
const [open, setOpen] = d2(false);
|
|
1304
1499
|
const ref = T2(null);
|
|
1500
|
+
const menuRef = useKeepInView(open);
|
|
1305
1501
|
A2(() => {
|
|
1306
1502
|
if (!open) return;
|
|
1307
1503
|
const onDown = (e3) => !ref.current?.contains(e3.target) && setOpen(false);
|
|
@@ -1321,60 +1517,60 @@ function IntervalPicker({ ctx }) {
|
|
|
1321
1517
|
setOpen(false);
|
|
1322
1518
|
ctx.selectResolution(r3);
|
|
1323
1519
|
};
|
|
1324
|
-
return /* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1520
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-interval-picker", ref, children: [
|
|
1521
|
+
/* @__PURE__ */ a3("div", { class: "fnc-intervals", children: favorites.map((r3) => /* @__PURE__ */ a3(
|
|
1326
1522
|
"button",
|
|
1327
1523
|
{
|
|
1328
1524
|
class: "fnc-chip",
|
|
1329
1525
|
"aria-pressed": r3 === s3.resolution,
|
|
1330
1526
|
disabled: !isSupported(r3),
|
|
1331
|
-
|
|
1527
|
+
"data-tip": isSupported(r3) ? resolutionLabel(r3, s3.locale, "long") : t3.unsupportedInterval,
|
|
1332
1528
|
onClick: () => select(r3),
|
|
1333
1529
|
children: resolutionLabel(r3, s3.locale)
|
|
1334
1530
|
}
|
|
1335
1531
|
)) }),
|
|
1336
|
-
/* @__PURE__ */
|
|
1532
|
+
/* @__PURE__ */ a3(
|
|
1337
1533
|
"button",
|
|
1338
1534
|
{
|
|
1339
1535
|
class: `fnc-btn fnc-btn-wide fnc-interval-trigger${favorites.includes(s3.resolution) ? "" : " fnc-interval-trigger-active"}`,
|
|
1340
|
-
|
|
1536
|
+
"data-tip": t3.moreIntervals,
|
|
1341
1537
|
"aria-label": t3.moreIntervals,
|
|
1342
1538
|
"aria-haspopup": "menu",
|
|
1343
1539
|
"aria-expanded": open,
|
|
1344
1540
|
onClick: () => setOpen(!open),
|
|
1345
1541
|
children: [
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1542
|
+
/* @__PURE__ */ a3("b", { class: "fnc-interval-current", children: resolutionLabel(s3.resolution, s3.locale) }),
|
|
1543
|
+
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
1348
1544
|
]
|
|
1349
1545
|
}
|
|
1350
1546
|
),
|
|
1351
|
-
open && /* @__PURE__ */
|
|
1352
|
-
/* @__PURE__ */
|
|
1547
|
+
open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-interval-menu", role: "menu", ref: menuRef, children: ctx.intervalGroups.map((group) => /* @__PURE__ */ a3("div", { class: "fnc-menu-group", role: "group", "aria-label": t3[GROUP_LABEL[group.id]], children: [
|
|
1548
|
+
/* @__PURE__ */ a3("div", { class: "fnc-menu-title", children: t3[GROUP_LABEL[group.id]] }),
|
|
1353
1549
|
group.intervals.map((r3) => {
|
|
1354
1550
|
const favorite = s3.favoriteIntervals.includes(r3);
|
|
1355
1551
|
const ok = isSupported(r3);
|
|
1356
|
-
return /* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1552
|
+
return /* @__PURE__ */ a3("div", { class: `fnc-menu-row${favorite ? " is-favorite" : ""}`, children: [
|
|
1553
|
+
/* @__PURE__ */ a3(
|
|
1358
1554
|
"button",
|
|
1359
1555
|
{
|
|
1360
1556
|
class: "fnc-menu-item",
|
|
1361
1557
|
role: "menuitemradio",
|
|
1362
1558
|
"aria-checked": r3 === s3.resolution,
|
|
1363
1559
|
disabled: !ok,
|
|
1364
|
-
|
|
1560
|
+
"data-tip": ok ? void 0 : t3.unsupportedInterval,
|
|
1365
1561
|
onClick: () => select(r3),
|
|
1366
1562
|
children: resolutionLabel(r3, s3.locale, "long")
|
|
1367
1563
|
}
|
|
1368
1564
|
),
|
|
1369
|
-
/* @__PURE__ */
|
|
1565
|
+
/* @__PURE__ */ a3(
|
|
1370
1566
|
"button",
|
|
1371
1567
|
{
|
|
1372
1568
|
class: "fnc-star",
|
|
1373
1569
|
"aria-pressed": favorite,
|
|
1374
1570
|
"aria-label": `${resolutionLabel(r3, s3.locale, "long")} ${favorite ? t3.removeFavorite : t3.addFavorite}`,
|
|
1375
|
-
|
|
1571
|
+
"data-tip": favorite ? t3.removeFavorite : t3.addFavorite,
|
|
1376
1572
|
onClick: () => ctx.toggleFavoriteInterval(r3),
|
|
1377
|
-
children: /* @__PURE__ */
|
|
1573
|
+
children: /* @__PURE__ */ a3(StarIcon, { filled: favorite })
|
|
1378
1574
|
}
|
|
1379
1575
|
)
|
|
1380
1576
|
] });
|
|
@@ -1452,7 +1648,7 @@ function layoutRects(node, x2 = 0, y3 = 0, w3 = 20, h3 = 16, gap = 1.6) {
|
|
|
1452
1648
|
// src/components/layout-menu.tsx
|
|
1453
1649
|
var LAYOUT_PANES = (id) => paneCount(LAYOUTS[id]);
|
|
1454
1650
|
function LayoutGlyph({ id }) {
|
|
1455
|
-
return /* @__PURE__ */
|
|
1651
|
+
return /* @__PURE__ */ a3("svg", { width: "20", height: "16", viewBox: "0 0 20 16", "aria-hidden": "true", children: layoutRects(LAYOUTS[id]).map((r3) => /* @__PURE__ */ a3("rect", { x: r3.x + 0.5, y: r3.y + 0.5, width: Math.max(0, r3.w - 1), height: Math.max(0, r3.h - 1), rx: "1.5", fill: "none", stroke: "currentColor", "stroke-width": "1.2" })) });
|
|
1456
1652
|
}
|
|
1457
1653
|
function usePopover() {
|
|
1458
1654
|
const [open, setOpen] = d2(false);
|
|
@@ -1482,63 +1678,65 @@ function LayoutMenu({ ctx, multi }) {
|
|
|
1482
1678
|
const t3 = STRINGS[s3.locale];
|
|
1483
1679
|
const layout = usePopover();
|
|
1484
1680
|
const sync = usePopover();
|
|
1681
|
+
const layoutMenuRef = useKeepInView(layout.open);
|
|
1682
|
+
const syncMenuRef = useKeepInView(sync.open);
|
|
1485
1683
|
const anySync = Object.values(m3.sync).some(Boolean);
|
|
1486
|
-
return /* @__PURE__ */
|
|
1487
|
-
/* @__PURE__ */
|
|
1488
|
-
/* @__PURE__ */
|
|
1684
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
1685
|
+
/* @__PURE__ */ a3("div", { class: "fnc-menu-wrap", ref: layout.ref, children: [
|
|
1686
|
+
/* @__PURE__ */ a3(
|
|
1489
1687
|
"button",
|
|
1490
1688
|
{
|
|
1491
1689
|
class: "fnc-btn fnc-btn-wide fnc-btn-layout",
|
|
1492
|
-
|
|
1690
|
+
"data-tip": t3.layout,
|
|
1493
1691
|
"aria-label": t3.layout,
|
|
1494
1692
|
"aria-haspopup": "menu",
|
|
1495
1693
|
"aria-expanded": layout.open,
|
|
1496
1694
|
onClick: () => layout.setOpen(!layout.open),
|
|
1497
1695
|
children: [
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
/* @__PURE__ */
|
|
1696
|
+
/* @__PURE__ */ a3(LayoutGlyph, { id: m3.layout }),
|
|
1697
|
+
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
1500
1698
|
]
|
|
1501
1699
|
}
|
|
1502
1700
|
),
|
|
1503
|
-
layout.open && /* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1505
|
-
group.map((id) => /* @__PURE__ */
|
|
1701
|
+
layout.open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-layout-menu", role: "menu", "aria-label": t3.layout, ref: layoutMenuRef, children: LAYOUT_GROUPS.map((group) => /* @__PURE__ */ a3("div", { class: "fnc-layout-row", children: [
|
|
1702
|
+
/* @__PURE__ */ a3("span", { class: "fnc-layout-count", children: group[0].split("-")[0] }),
|
|
1703
|
+
group.map((id) => /* @__PURE__ */ a3(
|
|
1506
1704
|
"button",
|
|
1507
1705
|
{
|
|
1508
1706
|
class: "fnc-layout-opt",
|
|
1509
1707
|
role: "menuitemradio",
|
|
1510
1708
|
"aria-checked": id === m3.layout,
|
|
1511
1709
|
"aria-label": `${t3.layout} ${id}`,
|
|
1512
|
-
|
|
1710
|
+
"data-layout": id,
|
|
1513
1711
|
onClick: () => {
|
|
1514
1712
|
multi.setLayout(id);
|
|
1515
1713
|
layout.setOpen(false);
|
|
1516
1714
|
},
|
|
1517
|
-
children: /* @__PURE__ */
|
|
1715
|
+
children: /* @__PURE__ */ a3(LayoutGlyph, { id })
|
|
1518
1716
|
}
|
|
1519
1717
|
))
|
|
1520
1718
|
] })) })
|
|
1521
1719
|
] }),
|
|
1522
|
-
LAYOUT_PANES(m3.layout) > 1 && /* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1720
|
+
LAYOUT_PANES(m3.layout) > 1 && /* @__PURE__ */ a3("div", { class: "fnc-menu-wrap", ref: sync.ref, children: [
|
|
1721
|
+
/* @__PURE__ */ a3(
|
|
1524
1722
|
"button",
|
|
1525
1723
|
{
|
|
1526
1724
|
class: "fnc-btn fnc-btn-sync",
|
|
1527
|
-
|
|
1725
|
+
"data-tip": t3.sync,
|
|
1528
1726
|
"aria-label": t3.sync,
|
|
1529
1727
|
"aria-haspopup": "menu",
|
|
1530
1728
|
"aria-expanded": sync.open,
|
|
1531
1729
|
"aria-pressed": anySync,
|
|
1532
1730
|
onClick: () => sync.setOpen(!sync.open),
|
|
1533
|
-
children: /* @__PURE__ */
|
|
1731
|
+
children: /* @__PURE__ */ a3(LinkIcon, {})
|
|
1534
1732
|
}
|
|
1535
1733
|
),
|
|
1536
|
-
sync.open && /* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
1734
|
+
sync.open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-sync-menu", role: "menu", "aria-label": t3.sync, ref: syncMenuRef, children: [
|
|
1735
|
+
/* @__PURE__ */ a3("div", { class: "fnc-menu-title", children: [
|
|
1538
1736
|
t3.sync,
|
|
1539
|
-
/* @__PURE__ */
|
|
1737
|
+
/* @__PURE__ */ a3("small", { children: t3.syncHint })
|
|
1540
1738
|
] }),
|
|
1541
|
-
SYNC_KEYS.map(({ key, label }) => /* @__PURE__ */
|
|
1739
|
+
SYNC_KEYS.map(({ key, label }) => /* @__PURE__ */ a3(
|
|
1542
1740
|
"button",
|
|
1543
1741
|
{
|
|
1544
1742
|
class: "fnc-menu-item fnc-sync-item",
|
|
@@ -1546,8 +1744,8 @@ function LayoutMenu({ ctx, multi }) {
|
|
|
1546
1744
|
"aria-checked": m3.sync[key],
|
|
1547
1745
|
onClick: () => multi.setSync({ [key]: !m3.sync[key] }),
|
|
1548
1746
|
children: [
|
|
1549
|
-
/* @__PURE__ */
|
|
1550
|
-
/* @__PURE__ */
|
|
1747
|
+
/* @__PURE__ */ a3("span", { children: t3[label] }),
|
|
1748
|
+
/* @__PURE__ */ a3("span", { class: "fnc-switch", "data-on": m3.sync[key] ? "true" : "false", "aria-hidden": "true" })
|
|
1551
1749
|
]
|
|
1552
1750
|
}
|
|
1553
1751
|
))
|
|
@@ -1563,7 +1761,7 @@ function Slot({ el, fixed = false }) {
|
|
|
1563
1761
|
ref.current?.appendChild(el);
|
|
1564
1762
|
return () => el.remove();
|
|
1565
1763
|
}, [el]);
|
|
1566
|
-
return /* @__PURE__ */
|
|
1764
|
+
return /* @__PURE__ */ a3("div", { class: fixed ? "fnc-slot-host fnc-slot-host-fixed" : "fnc-slot-host", ref });
|
|
1567
1765
|
}
|
|
1568
1766
|
|
|
1569
1767
|
// src/components/symbol-avatar.tsx
|
|
@@ -1577,10 +1775,10 @@ function SymbolAvatar({ info, size = 24 }) {
|
|
|
1577
1775
|
A2(() => setFailed(false), [info.logoUrl]);
|
|
1578
1776
|
const style = { width: `${size}px`, height: `${size}px`, fontSize: `${Math.round(size * 0.46)}px` };
|
|
1579
1777
|
if (info.logoUrl && !failed) {
|
|
1580
|
-
return /* @__PURE__ */
|
|
1778
|
+
return /* @__PURE__ */ a3("img", { class: "fnc-avatar", src: info.logoUrl, alt: "", style, onError: () => setFailed(true) });
|
|
1581
1779
|
}
|
|
1582
1780
|
const h3 = hue(info.symbol);
|
|
1583
|
-
return /* @__PURE__ */
|
|
1781
|
+
return /* @__PURE__ */ a3(
|
|
1584
1782
|
"span",
|
|
1585
1783
|
{
|
|
1586
1784
|
class: "fnc-avatar fnc-avatar-initial",
|
|
@@ -1601,18 +1799,18 @@ var displayCode = (symbol) => symbol.slice(symbol.lastIndexOf(":") + 1);
|
|
|
1601
1799
|
var toStored = (info) => JSON.parse(JSON.stringify({ ...info, tickSize: 0, price: void 0, changePercent: void 0, sparkline: void 0 }));
|
|
1602
1800
|
function Highlight({ text, query }) {
|
|
1603
1801
|
const q2 = query.trim();
|
|
1604
|
-
if (!q2) return /* @__PURE__ */
|
|
1802
|
+
if (!q2) return /* @__PURE__ */ a3($, { children: text });
|
|
1605
1803
|
const parts = [];
|
|
1606
1804
|
const lower = text.toLowerCase();
|
|
1607
1805
|
const needle = q2.toLowerCase();
|
|
1608
1806
|
let i3 = 0;
|
|
1609
1807
|
for (let at = lower.indexOf(needle); at >= 0; at = lower.indexOf(needle, i3)) {
|
|
1610
1808
|
if (at > i3) parts.push(text.slice(i3, at));
|
|
1611
|
-
parts.push(/* @__PURE__ */
|
|
1809
|
+
parts.push(/* @__PURE__ */ a3("mark", { children: text.slice(at, at + q2.length) }));
|
|
1612
1810
|
i3 = at + q2.length;
|
|
1613
1811
|
}
|
|
1614
1812
|
parts.push(text.slice(i3));
|
|
1615
|
-
return /* @__PURE__ */
|
|
1813
|
+
return /* @__PURE__ */ a3($, { children: parts });
|
|
1616
1814
|
}
|
|
1617
1815
|
function Sparkline({ values, up }) {
|
|
1618
1816
|
if (values.length < 2) return null;
|
|
@@ -1621,10 +1819,11 @@ function Sparkline({ values, up }) {
|
|
|
1621
1819
|
const w3 = 72;
|
|
1622
1820
|
const h3 = 24;
|
|
1623
1821
|
const points = values.map((v3, i3) => `${(i3 / (values.length - 1) * w3).toFixed(1)},${(h3 - 2 - (v3 - min) / (max - min || 1) * (h3 - 4)).toFixed(1)}`).join(" ");
|
|
1624
|
-
return /* @__PURE__ */
|
|
1822
|
+
return /* @__PURE__ */ a3("svg", { class: `fnc-sr-spark ${up ? "fnc-up" : "fnc-down"}`, width: w3, height: h3, viewBox: `0 0 ${w3} ${h3}`, "aria-hidden": "true", children: /* @__PURE__ */ a3("polyline", { points, fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linejoin": "round" }) });
|
|
1625
1823
|
}
|
|
1626
1824
|
function SymbolSearch({ ctx }) {
|
|
1627
|
-
const { locale, symbol: current } = useStore(ctx.store);
|
|
1825
|
+
const { locale, symbol: current, searchTarget } = useStore(ctx.store);
|
|
1826
|
+
const comparing = searchTarget === "compare";
|
|
1628
1827
|
const t3 = STRINGS[locale];
|
|
1629
1828
|
const [query, setQuery] = d2("");
|
|
1630
1829
|
const [category, setCategory] = d2(ctx.searchCategories[0]?.id ?? "all");
|
|
@@ -1678,7 +1877,8 @@ function SymbolSearch({ ctx }) {
|
|
|
1678
1877
|
if (!info) return;
|
|
1679
1878
|
save(RECENT_KEY, [toStored(info), ...recent.filter((r3) => r3.symbol !== info.symbol)].slice(0, MAX_RECENT), setRecent);
|
|
1680
1879
|
close();
|
|
1681
|
-
ctx.
|
|
1880
|
+
if (comparing) ctx.chart.addCompare(info.symbol).catch((error) => console.error("funnest-charts: compare failed", error));
|
|
1881
|
+
else ctx.selectSymbol(info.symbol);
|
|
1682
1882
|
};
|
|
1683
1883
|
const onKeyDown = (e3) => {
|
|
1684
1884
|
const count = rows.length;
|
|
@@ -1696,7 +1896,7 @@ function SymbolSearch({ ctx }) {
|
|
|
1696
1896
|
const change = info.changePercent ?? 0;
|
|
1697
1897
|
const up = change >= 0;
|
|
1698
1898
|
const trend = change > 0 ? "fnc-up" : change < 0 ? "fnc-down" : "fnc-flat";
|
|
1699
|
-
return /* @__PURE__ */
|
|
1899
|
+
return /* @__PURE__ */ a3(
|
|
1700
1900
|
"div",
|
|
1701
1901
|
{
|
|
1702
1902
|
class: "fnc-sr-row",
|
|
@@ -1706,76 +1906,76 @@ function SymbolSearch({ ctx }) {
|
|
|
1706
1906
|
onPointerMove: () => setActive(index),
|
|
1707
1907
|
onClick: () => choose(info),
|
|
1708
1908
|
children: [
|
|
1709
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ a3(
|
|
1710
1910
|
"button",
|
|
1711
1911
|
{
|
|
1712
1912
|
class: `fnc-sr-star${fav ? " is-on" : ""}`,
|
|
1713
1913
|
"aria-pressed": fav,
|
|
1714
1914
|
"aria-label": `${info.name} ${fav ? t3.removeFavorite : t3.addFavorite}`,
|
|
1715
|
-
|
|
1915
|
+
"data-tip": fav ? t3.removeFavorite : t3.addFavorite,
|
|
1716
1916
|
onClick: (e3) => {
|
|
1717
1917
|
e3.stopPropagation();
|
|
1718
1918
|
toggleFavorite(info);
|
|
1719
1919
|
},
|
|
1720
|
-
children: /* @__PURE__ */
|
|
1920
|
+
children: /* @__PURE__ */ a3(StarIcon, { filled: fav })
|
|
1721
1921
|
}
|
|
1722
1922
|
),
|
|
1723
|
-
ctx.showLogo && /* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
1725
|
-
/* @__PURE__ */
|
|
1726
|
-
/* @__PURE__ */
|
|
1727
|
-
current?.symbol === info.symbol && /* @__PURE__ */
|
|
1923
|
+
ctx.showLogo && /* @__PURE__ */ a3(SymbolAvatar, { info, size: 32 }),
|
|
1924
|
+
/* @__PURE__ */ a3("span", { class: "fnc-sr-main", children: [
|
|
1925
|
+
/* @__PURE__ */ a3("span", { class: "fnc-sr-name", children: [
|
|
1926
|
+
/* @__PURE__ */ a3(Highlight, { text: info.name, query }),
|
|
1927
|
+
current?.symbol === info.symbol && /* @__PURE__ */ a3("span", { class: "fnc-sr-current", children: t3.current })
|
|
1728
1928
|
] }),
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
1929
|
+
/* @__PURE__ */ a3("span", { class: "fnc-sr-meta", children: [
|
|
1930
|
+
/* @__PURE__ */ a3(Highlight, { text: displayCode(info.symbol), query }),
|
|
1731
1931
|
" \xB7 ",
|
|
1732
1932
|
info.exchange,
|
|
1733
1933
|
cat && ` \xB7 ${cat.label[locale]}`
|
|
1734
1934
|
] })
|
|
1735
1935
|
] }),
|
|
1736
|
-
info.sparkline && /* @__PURE__ */
|
|
1737
|
-
info.price !== void 0 && /* @__PURE__ */
|
|
1738
|
-
/* @__PURE__ */
|
|
1739
|
-
info.changePercent !== void 0 && /* @__PURE__ */
|
|
1936
|
+
info.sparkline && /* @__PURE__ */ a3(Sparkline, { values: info.sparkline, up }),
|
|
1937
|
+
info.price !== void 0 && /* @__PURE__ */ a3("span", { class: "fnc-sr-quote", children: [
|
|
1938
|
+
/* @__PURE__ */ a3("b", { children: formatPrice(info.price, info.pricePrecision) }),
|
|
1939
|
+
info.changePercent !== void 0 && /* @__PURE__ */ a3("span", { class: trend, children: [
|
|
1740
1940
|
change > 0 ? "\u2191 " : change < 0 ? "\u2193 " : "",
|
|
1741
1941
|
Math.abs(info.changePercent).toFixed(2),
|
|
1742
1942
|
"%"
|
|
1743
1943
|
] })
|
|
1744
1944
|
] }),
|
|
1745
|
-
isRecent && /* @__PURE__ */
|
|
1945
|
+
isRecent && /* @__PURE__ */ a3(
|
|
1746
1946
|
"button",
|
|
1747
1947
|
{
|
|
1748
1948
|
class: "fnc-ind-btn",
|
|
1749
1949
|
"aria-label": `${info.name} ${t3.removeRecent}`,
|
|
1750
|
-
|
|
1950
|
+
"data-tip": t3.removeRecent,
|
|
1751
1951
|
onClick: (e3) => {
|
|
1752
1952
|
e3.stopPropagation();
|
|
1753
1953
|
save(RECENT_KEY, recent.filter((r3) => r3.symbol !== info.symbol), setRecent);
|
|
1754
1954
|
},
|
|
1755
|
-
children: /* @__PURE__ */
|
|
1955
|
+
children: /* @__PURE__ */ a3(SmallCloseIcon, {})
|
|
1756
1956
|
}
|
|
1757
1957
|
)
|
|
1758
1958
|
]
|
|
1759
1959
|
}
|
|
1760
1960
|
);
|
|
1761
1961
|
};
|
|
1762
|
-
const sideItem = (label, selected, onClick, extra) => /* @__PURE__ */
|
|
1763
|
-
/* @__PURE__ */
|
|
1962
|
+
const sideItem = (label, selected, onClick, extra) => /* @__PURE__ */ a3("button", { class: "fnc-sr-side-item", "aria-pressed": selected, onClick, children: [
|
|
1963
|
+
/* @__PURE__ */ a3("span", { children: label }),
|
|
1764
1964
|
extra
|
|
1765
1965
|
] });
|
|
1766
|
-
return /* @__PURE__ */
|
|
1767
|
-
/* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
1769
|
-
exchange && /* @__PURE__ */
|
|
1966
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-backdrop", onPointerDown: (e3) => e3.target === e3.currentTarget && close(), children: /* @__PURE__ */ a3("div", { class: "fnc-dialog fnc-search-dialog", role: "dialog", "aria-modal": "true", "aria-label": comparing ? t3.compareSymbol : t3.searchSymbol, onKeyDown, children: [
|
|
1967
|
+
/* @__PURE__ */ a3("div", { class: "fnc-search", children: [
|
|
1968
|
+
/* @__PURE__ */ a3(SearchIcon, {}),
|
|
1969
|
+
exchange && /* @__PURE__ */ a3("span", { class: "fnc-chip-token", children: [
|
|
1770
1970
|
exchange,
|
|
1771
|
-
/* @__PURE__ */
|
|
1971
|
+
/* @__PURE__ */ a3("button", { "aria-label": `${exchange} ${t3.cancel}`, onClick: () => setExchange(null), children: /* @__PURE__ */ a3(SmallCloseIcon, {}) })
|
|
1772
1972
|
] }),
|
|
1773
|
-
/* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ a3(
|
|
1774
1974
|
"input",
|
|
1775
1975
|
{
|
|
1776
1976
|
ref: inputRef,
|
|
1777
1977
|
value: query,
|
|
1778
|
-
placeholder: t3.searchPlaceholder,
|
|
1978
|
+
placeholder: comparing ? t3.compareSymbol : t3.searchPlaceholder,
|
|
1779
1979
|
role: "combobox",
|
|
1780
1980
|
"aria-expanded": "true",
|
|
1781
1981
|
"aria-controls": "fnc-search-results",
|
|
@@ -1784,50 +1984,50 @@ function SymbolSearch({ ctx }) {
|
|
|
1784
1984
|
onInput: (e3) => setQuery(e3.currentTarget.value)
|
|
1785
1985
|
}
|
|
1786
1986
|
),
|
|
1787
|
-
query && /* @__PURE__ */
|
|
1788
|
-
/* @__PURE__ */
|
|
1987
|
+
query && /* @__PURE__ */ a3("button", { class: "fnc-ind-btn", "aria-label": t3.cancel, onClick: () => (setQuery(""), inputRef.current?.focus()), children: /* @__PURE__ */ a3(SmallCloseIcon, {}) }),
|
|
1988
|
+
/* @__PURE__ */ a3("button", { class: "fnc-kbd fnc-kbd-btn fnc-hide-mobile", "aria-label": t3.close, "data-tip": t3.close, onClick: close, children: "ESC" })
|
|
1789
1989
|
] }),
|
|
1790
|
-
/* @__PURE__ */
|
|
1791
|
-
/* @__PURE__ */
|
|
1792
|
-
/* @__PURE__ */
|
|
1793
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tabs", role: "tablist", children: ctx.searchCategories.map((c3) => /* @__PURE__ */ a3("button", { class: "fnc-tab", role: "tab", "aria-selected": c3.id === category, onClick: () => setCategory(c3.id), children: c3.label[locale] })) }),
|
|
1991
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-body", children: [
|
|
1992
|
+
/* @__PURE__ */ a3("nav", { class: "fnc-sr-side fnc-scroll", "aria-label": t3.searchSymbol, children: [
|
|
1993
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-side-title", children: t3.browse }),
|
|
1794
1994
|
sideItem(t3.allSymbols, view.kind === "all" && !exchange, () => (setView({ kind: "all" }), setExchange(null))),
|
|
1795
|
-
sideItem(t3.favorites, view.kind === "favorites", () => (setView({ kind: "favorites" }), setExchange(null)), /* @__PURE__ */
|
|
1796
|
-
exchanges.length > 0 && /* @__PURE__ */
|
|
1995
|
+
sideItem(t3.favorites, view.kind === "favorites", () => (setView({ kind: "favorites" }), setExchange(null)), /* @__PURE__ */ a3("em", { children: favorites.length || "" })),
|
|
1996
|
+
exchanges.length > 0 && /* @__PURE__ */ a3("div", { class: "fnc-sr-side-title", children: t3.exchanges }),
|
|
1797
1997
|
exchanges.map(
|
|
1798
|
-
([name, count]) => sideItem(name, exchange === name, () => (setView({ kind: "all" }), setExchange(exchange === name ? null : name)), /* @__PURE__ */
|
|
1998
|
+
([name, count]) => sideItem(name, exchange === name, () => (setView({ kind: "all" }), setExchange(exchange === name ? null : name)), /* @__PURE__ */ a3("em", { children: count }))
|
|
1799
1999
|
)
|
|
1800
2000
|
] }),
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
recentRows.length > 0 && /* @__PURE__ */
|
|
1803
|
-
/* @__PURE__ */
|
|
1804
|
-
/* @__PURE__ */
|
|
2001
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-list fnc-scroll", id: "fnc-search-results", role: "listbox", ref: listRef, children: [
|
|
2002
|
+
recentRows.length > 0 && /* @__PURE__ */ a3("div", { class: "fnc-sr-section", children: [
|
|
2003
|
+
/* @__PURE__ */ a3("span", { children: t3.recentSearches }),
|
|
2004
|
+
/* @__PURE__ */ a3("button", { class: "fnc-link", onClick: () => save(RECENT_KEY, [], setRecent), children: t3.clearRecent })
|
|
1805
2005
|
] }),
|
|
1806
2006
|
recentRows.map((info, i3) => row2(info, i3, true)),
|
|
1807
|
-
(recentRows.length > 0 || view.kind === "favorites") && /* @__PURE__ */
|
|
1808
|
-
loading && !results && view.kind === "all" ? Array.from({ length: 6 }, () => /* @__PURE__ */
|
|
1809
|
-
!loading && rows.length === 0 && /* @__PURE__ */
|
|
2007
|
+
(recentRows.length > 0 || view.kind === "favorites") && /* @__PURE__ */ a3("div", { class: "fnc-sr-section", children: view.kind === "favorites" ? t3.favorites : t3.symbols }),
|
|
2008
|
+
loading && !results && view.kind === "all" ? Array.from({ length: 6 }, () => /* @__PURE__ */ a3("div", { class: "fnc-sr-skeleton", "aria-hidden": "true" })) : resultRows.map((info, i3) => row2(info, recentRows.length + i3, false)),
|
|
2009
|
+
!loading && rows.length === 0 && /* @__PURE__ */ a3("div", { class: "fnc-empty", children: view.kind === "favorites" && favorites.length === 0 ? t3.noFavorites : t3.noResults })
|
|
1810
2010
|
] })
|
|
1811
2011
|
] }),
|
|
1812
|
-
/* @__PURE__ */
|
|
1813
|
-
/* @__PURE__ */
|
|
1814
|
-
/* @__PURE__ */
|
|
2012
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sr-footer", children: [
|
|
2013
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2014
|
+
/* @__PURE__ */ a3("kbd", { class: "fnc-kbd", children: "\u2191\u2193" }),
|
|
1815
2015
|
" ",
|
|
1816
2016
|
t3.navigate
|
|
1817
2017
|
] }),
|
|
1818
|
-
/* @__PURE__ */
|
|
1819
|
-
/* @__PURE__ */
|
|
2018
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2019
|
+
/* @__PURE__ */ a3("kbd", { class: "fnc-kbd", children: "\u21B5" }),
|
|
1820
2020
|
" ",
|
|
1821
2021
|
t3.openAction
|
|
1822
2022
|
] }),
|
|
1823
|
-
/* @__PURE__ */
|
|
1824
|
-
/* @__PURE__ */
|
|
2023
|
+
/* @__PURE__ */ a3("button", { class: "fnc-sr-foot-btn", onClick: close, children: [
|
|
2024
|
+
/* @__PURE__ */ a3("kbd", { class: "fnc-kbd", children: "ESC" }),
|
|
1825
2025
|
" ",
|
|
1826
2026
|
t3.close
|
|
1827
2027
|
] }),
|
|
1828
|
-
/* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
2028
|
+
/* @__PURE__ */ a3("span", { class: "fnc-spacer" }),
|
|
2029
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2030
|
+
/* @__PURE__ */ a3("kbd", { class: "fnc-kbd", children: [
|
|
1831
2031
|
/Mac|iPhone|iPad/.test(navigator.platform) ? "\u2318" : "Ctrl",
|
|
1832
2032
|
" + K"
|
|
1833
2033
|
] }),
|
|
@@ -1843,81 +2043,107 @@ function Toolbar({ ctx }) {
|
|
|
1843
2043
|
const s3 = useStore(ctx.store);
|
|
1844
2044
|
const t3 = STRINGS[s3.locale];
|
|
1845
2045
|
const canSearch = typeof ctx.datafeed.searchSymbols === "function";
|
|
1846
|
-
|
|
1847
|
-
|
|
2046
|
+
const mod = /Mac|iPhone|iPad/.test(navigator.platform) ? "\u2318" : "Ctrl";
|
|
2047
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-toolbar", role: "toolbar", children: [
|
|
2048
|
+
/* @__PURE__ */ a3(
|
|
1848
2049
|
"button",
|
|
1849
2050
|
{
|
|
1850
2051
|
class: "fnc-symbol",
|
|
1851
2052
|
disabled: !canSearch,
|
|
1852
|
-
|
|
2053
|
+
"data-tip": canSearch ? t3.searchSymbol : void 0,
|
|
1853
2054
|
"aria-haspopup": "dialog",
|
|
1854
|
-
onClick: () => ctx.setSearchOpen(true),
|
|
2055
|
+
onClick: () => ctx.setSearchOpen(true, "symbol"),
|
|
1855
2056
|
children: [
|
|
1856
|
-
ctx.showLogo && s3.symbol ? /* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
canSearch && ctx.showLogo && /* @__PURE__ */
|
|
2057
|
+
ctx.showLogo && s3.symbol ? /* @__PURE__ */ a3(SymbolAvatar, { info: s3.symbol, size: 24 }) : canSearch && /* @__PURE__ */ a3("span", { class: "fnc-icon", children: /* @__PURE__ */ a3(SearchIcon, {}) }),
|
|
2058
|
+
/* @__PURE__ */ a3("span", { class: "fnc-symbol-name", children: s3.symbol?.name ?? "\u2014" }),
|
|
2059
|
+
canSearch && ctx.showLogo && /* @__PURE__ */ a3("span", { class: "fnc-icon", children: /* @__PURE__ */ a3(ChevronDownIcon, {}) })
|
|
1859
2060
|
]
|
|
1860
2061
|
}
|
|
1861
2062
|
),
|
|
1862
|
-
/* @__PURE__ */
|
|
1863
|
-
/* @__PURE__ */
|
|
1864
|
-
/* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
1866
|
-
/* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
2063
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sep" }),
|
|
2064
|
+
/* @__PURE__ */ a3(IntervalPicker, { ctx }),
|
|
2065
|
+
/* @__PURE__ */ a3(Slot, { el: ctx.slots.toolbar }),
|
|
2066
|
+
/* @__PURE__ */ a3("div", { class: "fnc-spacer" }),
|
|
2067
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools", children: [
|
|
2068
|
+
/* @__PURE__ */ a3(ChartTypeMenu, { ctx }),
|
|
2069
|
+
/* @__PURE__ */ a3(
|
|
1869
2070
|
"button",
|
|
1870
2071
|
{
|
|
1871
|
-
class: "fnc-btn fnc-btn-wide fnc-btn-label",
|
|
1872
|
-
|
|
2072
|
+
class: "fnc-btn fnc-btn-wide fnc-btn-label fnc-btn-indicators",
|
|
2073
|
+
"data-tip": t3.addIndicator,
|
|
1873
2074
|
"aria-label": t3.addIndicator,
|
|
1874
2075
|
"aria-haspopup": "dialog",
|
|
1875
2076
|
onClick: () => ctx.store.set({ dialog: { kind: "indicators" } }),
|
|
1876
2077
|
children: [
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
/* @__PURE__ */
|
|
2078
|
+
/* @__PURE__ */ a3(IndicatorIcon, {}),
|
|
2079
|
+
/* @__PURE__ */ a3("span", { children: t3.indicators })
|
|
1879
2080
|
]
|
|
1880
2081
|
}
|
|
1881
2082
|
),
|
|
1882
|
-
|
|
2083
|
+
canSearch && /* @__PURE__ */ a3(
|
|
2084
|
+
"button",
|
|
2085
|
+
{
|
|
2086
|
+
class: "fnc-btn fnc-btn-compare",
|
|
2087
|
+
"data-tip": t3.compareSymbol,
|
|
2088
|
+
"aria-label": t3.compareSymbol,
|
|
2089
|
+
"aria-haspopup": "dialog",
|
|
2090
|
+
disabled: s3.compares.length >= 5,
|
|
2091
|
+
onClick: () => ctx.setSearchOpen(true, "compare"),
|
|
2092
|
+
children: /* @__PURE__ */ a3(CompareIcon, {})
|
|
2093
|
+
}
|
|
2094
|
+
),
|
|
2095
|
+
/* @__PURE__ */ a3(
|
|
2096
|
+
"button",
|
|
2097
|
+
{
|
|
2098
|
+
class: "fnc-btn fnc-btn-replay",
|
|
2099
|
+
"data-tip": s3.replay.selecting ? t3.replayPick : t3.replay,
|
|
2100
|
+
"aria-label": t3.replay,
|
|
2101
|
+
"aria-pressed": s3.replay.selecting || s3.replay.active,
|
|
2102
|
+
onClick: () => s3.replay.active ? ctx.chart.stopReplay() : ctx.chart.setReplaySelecting(!s3.replay.selecting),
|
|
2103
|
+
children: /* @__PURE__ */ a3(ReplayIcon, {})
|
|
2104
|
+
}
|
|
2105
|
+
),
|
|
2106
|
+
ctx.multi && /* @__PURE__ */ a3(LayoutMenu, { ctx, multi: ctx.multi })
|
|
1883
2107
|
] }),
|
|
1884
|
-
/* @__PURE__ */
|
|
1885
|
-
ctx.drawingToolbar && /* @__PURE__ */
|
|
2108
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sep" }),
|
|
2109
|
+
ctx.drawingToolbar && /* @__PURE__ */ a3(
|
|
1886
2110
|
"button",
|
|
1887
2111
|
{
|
|
1888
2112
|
class: "fnc-btn fnc-btn-drawbar",
|
|
1889
|
-
|
|
2113
|
+
"data-tip": t3.drawingTools,
|
|
1890
2114
|
"aria-label": t3.drawingTools,
|
|
1891
2115
|
"aria-pressed": s3.drawbarOpen || s3.drawingTool !== null,
|
|
1892
2116
|
onClick: () => ctx.store.set({ drawbarOpen: !s3.drawbarOpen }),
|
|
1893
|
-
children: /* @__PURE__ */
|
|
2117
|
+
children: /* @__PURE__ */ a3(PencilIcon, {})
|
|
1894
2118
|
}
|
|
1895
2119
|
),
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-undo", "data-tip": `${t3.undo} (${mod}+Z)`, "aria-label": t3.undo, disabled: !s3.canUndo, onClick: () => ctx.chart.undo(), children: /* @__PURE__ */ a3(UndoIcon, {}) }),
|
|
2121
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-undo", "data-tip": `${t3.redo} (${mod}+Shift+Z)`, "aria-label": t3.redo, disabled: !s3.canRedo, onClick: () => ctx.chart.redo(), children: /* @__PURE__ */ a3(RedoIcon, {}) }),
|
|
2122
|
+
/* @__PURE__ */ a3(Slot, { el: ctx.slots.toolbarEnd, fixed: true }),
|
|
2123
|
+
/* @__PURE__ */ a3(
|
|
1898
2124
|
"button",
|
|
1899
2125
|
{
|
|
1900
|
-
class: "fnc-btn",
|
|
1901
|
-
|
|
2126
|
+
class: "fnc-btn fnc-btn-settings",
|
|
2127
|
+
"data-tip": t3.chartSettings,
|
|
1902
2128
|
"aria-label": t3.chartSettings,
|
|
1903
2129
|
"aria-haspopup": "dialog",
|
|
1904
2130
|
onClick: () => ctx.store.set({ dialog: { kind: "chartSettings" } }),
|
|
1905
|
-
children: /* @__PURE__ */
|
|
2131
|
+
children: /* @__PURE__ */ a3(SettingsIcon, {})
|
|
1906
2132
|
}
|
|
1907
2133
|
),
|
|
1908
|
-
/* @__PURE__ */
|
|
1909
|
-
/* @__PURE__ */
|
|
2134
|
+
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-screenshot", "data-tip": t3.screenshot, "aria-label": t3.screenshot, onClick: ctx.screenshot, children: /* @__PURE__ */ a3(CameraIcon, {}) }),
|
|
2135
|
+
/* @__PURE__ */ a3(
|
|
1910
2136
|
"button",
|
|
1911
2137
|
{
|
|
1912
|
-
class: "fnc-btn",
|
|
1913
|
-
|
|
2138
|
+
class: "fnc-btn fnc-btn-fullscreen",
|
|
2139
|
+
"data-tip": s3.fullscreen ? t3.exitFullscreen : t3.fullscreen,
|
|
1914
2140
|
"aria-label": s3.fullscreen ? t3.exitFullscreen : t3.fullscreen,
|
|
1915
2141
|
onClick: ctx.toggleFullscreen,
|
|
1916
|
-
children: s3.fullscreen ? /* @__PURE__ */
|
|
2142
|
+
children: s3.fullscreen ? /* @__PURE__ */ a3(CollapseIcon, {}) : /* @__PURE__ */ a3(ExpandIcon, {})
|
|
1917
2143
|
}
|
|
1918
2144
|
),
|
|
1919
|
-
s3.searchOpen && canSearch && /* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
2145
|
+
s3.searchOpen && canSearch && /* @__PURE__ */ a3(SymbolSearch, { ctx }),
|
|
2146
|
+
/* @__PURE__ */ a3(Dialogs, { ctx })
|
|
1921
2147
|
] });
|
|
1922
2148
|
}
|
|
1923
2149
|
|
|
@@ -1931,7 +2157,7 @@ var CONTROL_OFFSET = 52;
|
|
|
1931
2157
|
var dirClass = (v3) => v3 > 0 ? "fnc-up" : v3 < 0 ? "fnc-down" : "fnc-flat";
|
|
1932
2158
|
function IndicatorItem({ ctx, item }) {
|
|
1933
2159
|
const t3 = STRINGS[ctx.store.get().locale];
|
|
1934
|
-
return /* @__PURE__ */
|
|
2160
|
+
return /* @__PURE__ */ a3(
|
|
1935
2161
|
"div",
|
|
1936
2162
|
{
|
|
1937
2163
|
class: item.visible ? "fnc-ind" : "fnc-ind fnc-ind-hidden",
|
|
@@ -1944,41 +2170,41 @@ function IndicatorItem({ ctx, item }) {
|
|
|
1944
2170
|
},
|
|
1945
2171
|
onKeyDown: (e3) => e3.key === "Enter" && ctx.store.set({ dialog: { kind: "indicatorSettings", id: item.id } }),
|
|
1946
2172
|
children: [
|
|
1947
|
-
/* @__PURE__ */
|
|
2173
|
+
/* @__PURE__ */ a3(
|
|
1948
2174
|
"button",
|
|
1949
2175
|
{
|
|
1950
2176
|
class: "fnc-ind-btn fnc-ind-eye",
|
|
1951
|
-
|
|
2177
|
+
"data-tip": item.visible ? t3.hide : t3.show,
|
|
1952
2178
|
"aria-label": `${item.title} ${item.visible ? t3.hide : t3.show}`,
|
|
1953
2179
|
"aria-pressed": !item.visible,
|
|
1954
2180
|
onClick: (e3) => {
|
|
1955
2181
|
e3.stopPropagation();
|
|
1956
2182
|
ctx.chart.setIndicatorVisible(item.id, !item.visible);
|
|
1957
2183
|
},
|
|
1958
|
-
children: item.visible ? /* @__PURE__ */
|
|
2184
|
+
children: item.visible ? /* @__PURE__ */ a3(EyeIcon, {}) : /* @__PURE__ */ a3(EyeOffIcon, {})
|
|
1959
2185
|
}
|
|
1960
2186
|
),
|
|
1961
|
-
/* @__PURE__ */
|
|
1962
|
-
item.visible && item.values.map((v3) => /* @__PURE__ */
|
|
1963
|
-
/* @__PURE__ */
|
|
1964
|
-
/* @__PURE__ */
|
|
2187
|
+
/* @__PURE__ */ a3("span", { class: "fnc-ind-title", children: item.title }),
|
|
2188
|
+
item.visible && item.values.map((v3) => /* @__PURE__ */ a3("b", { style: { color: v3.color }, "data-tip": v3.label, children: v3.value })),
|
|
2189
|
+
/* @__PURE__ */ a3("span", { class: "fnc-ind-actions", children: [
|
|
2190
|
+
/* @__PURE__ */ a3(
|
|
1965
2191
|
"button",
|
|
1966
2192
|
{
|
|
1967
2193
|
class: "fnc-ind-btn",
|
|
1968
|
-
|
|
2194
|
+
"data-tip": t3.indicatorSettings,
|
|
1969
2195
|
"aria-label": `${item.title} ${t3.indicatorSettings}`,
|
|
1970
2196
|
onClick: () => ctx.store.set({ dialog: { kind: "indicatorSettings", id: item.id } }),
|
|
1971
|
-
children: /* @__PURE__ */
|
|
2197
|
+
children: /* @__PURE__ */ a3(GearIcon, {})
|
|
1972
2198
|
}
|
|
1973
2199
|
),
|
|
1974
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ a3(
|
|
1975
2201
|
"button",
|
|
1976
2202
|
{
|
|
1977
2203
|
class: "fnc-ind-btn",
|
|
1978
|
-
|
|
2204
|
+
"data-tip": t3.removeIndicator,
|
|
1979
2205
|
"aria-label": `${item.title} ${t3.removeIndicator}`,
|
|
1980
2206
|
onClick: () => ctx.chart.removeIndicator(item.id),
|
|
1981
|
-
children: /* @__PURE__ */
|
|
2207
|
+
children: /* @__PURE__ */ a3(SmallCloseIcon, {})
|
|
1982
2208
|
}
|
|
1983
2209
|
)
|
|
1984
2210
|
] })
|
|
@@ -1998,7 +2224,9 @@ function Legend({ ctx }) {
|
|
|
1998
2224
|
"crosshairMove",
|
|
1999
2225
|
(info) => setHover(info ? { bar: info.bar, prev: ctx.chart.bars[info.index - 1], index: info.index } : null)
|
|
2000
2226
|
),
|
|
2001
|
-
ctx.chart.on("dataChange", () => refresh(void 0))
|
|
2227
|
+
ctx.chart.on("dataChange", () => refresh(void 0)),
|
|
2228
|
+
// Compare values are % from the first visible bar, so they change while scrolling.
|
|
2229
|
+
ctx.chart.on("visibleRangeChange", () => ctx.store.get().compares.length > 0 && refresh(void 0))
|
|
2002
2230
|
];
|
|
2003
2231
|
return () => offs.forEach((off) => off());
|
|
2004
2232
|
}, [ctx.chart]);
|
|
@@ -2011,7 +2239,7 @@ function Legend({ ctx }) {
|
|
|
2011
2239
|
ro.observe(el);
|
|
2012
2240
|
return () => ro.disconnect();
|
|
2013
2241
|
}, [ctx.chart]);
|
|
2014
|
-
if (!s3.symbol) return /* @__PURE__ */
|
|
2242
|
+
if (!s3.symbol) return /* @__PURE__ */ a3("div", { class: "fnc-legend", ref });
|
|
2015
2243
|
const bars = ctx.chart.bars;
|
|
2016
2244
|
const bar = hover?.bar ?? bars[bars.length - 1];
|
|
2017
2245
|
const prev = hover ? hover.prev : bars[bars.length - 2];
|
|
@@ -2022,28 +2250,28 @@ function Legend({ ctx }) {
|
|
|
2022
2250
|
const change = prev ? bar.close - prev.close : 0;
|
|
2023
2251
|
const pct = prev && prev.close ? change / prev.close * 100 : 0;
|
|
2024
2252
|
const sign = change > 0 ? "+" : "";
|
|
2025
|
-
values = /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2253
|
+
values = /* @__PURE__ */ a3("div", { class: "fnc-legend-values", children: [
|
|
2254
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2027
2255
|
t3.open,
|
|
2028
2256
|
" ",
|
|
2029
|
-
/* @__PURE__ */
|
|
2257
|
+
/* @__PURE__ */ a3("b", { class: cls, children: fmt(bar.open) })
|
|
2030
2258
|
] }),
|
|
2031
|
-
/* @__PURE__ */
|
|
2259
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2032
2260
|
t3.high,
|
|
2033
2261
|
" ",
|
|
2034
|
-
/* @__PURE__ */
|
|
2262
|
+
/* @__PURE__ */ a3("b", { class: cls, children: fmt(bar.high) })
|
|
2035
2263
|
] }),
|
|
2036
|
-
/* @__PURE__ */
|
|
2264
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2037
2265
|
t3.low,
|
|
2038
2266
|
" ",
|
|
2039
|
-
/* @__PURE__ */
|
|
2267
|
+
/* @__PURE__ */ a3("b", { class: cls, children: fmt(bar.low) })
|
|
2040
2268
|
] }),
|
|
2041
|
-
/* @__PURE__ */
|
|
2269
|
+
/* @__PURE__ */ a3("span", { children: [
|
|
2042
2270
|
t3.close_,
|
|
2043
2271
|
" ",
|
|
2044
|
-
/* @__PURE__ */
|
|
2272
|
+
/* @__PURE__ */ a3("b", { class: cls, children: fmt(bar.close) })
|
|
2045
2273
|
] }),
|
|
2046
|
-
/* @__PURE__ */
|
|
2274
|
+
/* @__PURE__ */ a3("b", { class: dirClass(change), children: [
|
|
2047
2275
|
sign,
|
|
2048
2276
|
fmt(change),
|
|
2049
2277
|
" (",
|
|
@@ -2051,33 +2279,48 @@ function Legend({ ctx }) {
|
|
|
2051
2279
|
pct.toFixed(2),
|
|
2052
2280
|
"%)"
|
|
2053
2281
|
] }),
|
|
2054
|
-
bar.volume !== void 0 && /* @__PURE__ */
|
|
2282
|
+
bar.volume !== void 0 && /* @__PURE__ */ a3("span", { children: [
|
|
2055
2283
|
t3.volume,
|
|
2056
2284
|
" ",
|
|
2057
|
-
/* @__PURE__ */
|
|
2285
|
+
/* @__PURE__ */ a3("b", { class: "fnc-flat", children: formatCompact(bar.volume, s3.locale) })
|
|
2058
2286
|
] })
|
|
2059
2287
|
] });
|
|
2060
2288
|
}
|
|
2061
2289
|
const items = s3.indicators.length ? ctx.chart.indicatorLegend(hover?.index) : [];
|
|
2062
2290
|
const overlayItems = items.filter((i3) => i3.overlay);
|
|
2063
2291
|
const paneLegends = s3.layout.panes.filter((p3) => p3.kind === "indicator").map((pane) => ({ pane, item: items.find((i3) => i3.id === pane.id) }));
|
|
2064
|
-
return /* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
2067
|
-
ctx.showLogo && /* @__PURE__ */
|
|
2068
|
-
/* @__PURE__ */
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
/* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2073
|
-
s3.loading && /* @__PURE__ */
|
|
2292
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
2293
|
+
/* @__PURE__ */ a3("div", { class: "fnc-legend", ref, children: [
|
|
2294
|
+
/* @__PURE__ */ a3("div", { class: "fnc-legend-title", children: [
|
|
2295
|
+
ctx.showLogo && /* @__PURE__ */ a3(SymbolAvatar, { info: s3.symbol, size: 18 }),
|
|
2296
|
+
/* @__PURE__ */ a3("b", { children: s3.symbol.name }),
|
|
2297
|
+
/* @__PURE__ */ a3("span", { children: "\xB7" }),
|
|
2298
|
+
/* @__PURE__ */ a3("span", { children: resolutionLabel(s3.resolution, s3.locale) }),
|
|
2299
|
+
/* @__PURE__ */ a3("span", { children: "\xB7" }),
|
|
2300
|
+
/* @__PURE__ */ a3("span", { children: s3.symbol.exchange }),
|
|
2301
|
+
s3.loading && /* @__PURE__ */ a3("span", { class: "fnc-spinner", role: "status" })
|
|
2074
2302
|
] }),
|
|
2075
2303
|
values,
|
|
2076
|
-
|
|
2077
|
-
|
|
2304
|
+
s3.compares.length > 0 && ctx.chart.compareLegend(hover?.index).map((c3) => /* @__PURE__ */ a3("div", { class: "fnc-cmp", children: [
|
|
2305
|
+
/* @__PURE__ */ a3("i", { class: "fnc-cmp-dot", style: { background: c3.color } }),
|
|
2306
|
+
/* @__PURE__ */ a3("span", { class: "fnc-cmp-name", children: c3.name }),
|
|
2307
|
+
/* @__PURE__ */ a3("b", { children: c3.value }),
|
|
2308
|
+
/* @__PURE__ */ a3(
|
|
2309
|
+
"button",
|
|
2310
|
+
{
|
|
2311
|
+
class: "fnc-ind-btn",
|
|
2312
|
+
"data-tip": t3.removeCompare,
|
|
2313
|
+
"aria-label": `${c3.name} ${t3.removeCompare}`,
|
|
2314
|
+
onClick: () => ctx.chart.removeCompare(c3.symbol),
|
|
2315
|
+
children: /* @__PURE__ */ a3(SmallCloseIcon, {})
|
|
2316
|
+
}
|
|
2317
|
+
)
|
|
2318
|
+
] })),
|
|
2319
|
+
!collapsed && overlayItems.map((item) => /* @__PURE__ */ a3(IndicatorItem, { ctx, item })),
|
|
2320
|
+
overlayItems.length > 0 && (collapsed ? /* @__PURE__ */ a3("button", { class: "fnc-ind-handle", "aria-expanded": "false", "aria-label": t3.expand, "data-tip": t3.expand, onClick: () => setCollapsed(false), children: /* @__PURE__ */ a3("span", {}) }) : /* @__PURE__ */ a3("button", { class: "fnc-ind-collapse", "aria-expanded": "true", "aria-label": t3.collapse, "data-tip": t3.collapse, onClick: () => setCollapsed(true), children: /* @__PURE__ */ a3(CollapseLeftIcon, {}) }))
|
|
2078
2321
|
] }),
|
|
2079
2322
|
paneLegends.map(
|
|
2080
|
-
({ pane, item }) => item && /* @__PURE__ */
|
|
2323
|
+
({ pane, item }) => item && /* @__PURE__ */ a3("div", { class: "fnc-legend fnc-pane-legend", style: { top: `${pane.top + 4}px` }, children: /* @__PURE__ */ a3(IndicatorItem, { ctx, item }) })
|
|
2081
2324
|
)
|
|
2082
2325
|
] });
|
|
2083
2326
|
}
|
|
@@ -2090,24 +2333,25 @@ function NavControls({ ctx }) {
|
|
|
2090
2333
|
if (plotWidth <= 0) return null;
|
|
2091
2334
|
const top = panesHeight - CONTROL_OFFSET;
|
|
2092
2335
|
const page = () => Math.max(1, Math.round(plotWidth / ctx.chart.timeScale.barSpacing / 3));
|
|
2093
|
-
const button = (label, onClick, icon) => /* @__PURE__ */
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
button(t3.
|
|
2098
|
-
button(t3.
|
|
2099
|
-
button(t3.
|
|
2100
|
-
button(t3.
|
|
2336
|
+
const button = (label, onClick, icon) => /* @__PURE__ */ a3("button", { class: "fnc-btn", "data-tip": label, "aria-label": label, onClick, children: icon });
|
|
2337
|
+
const replaying = s3.replay.active || s3.replay.selecting;
|
|
2338
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
2339
|
+
showButtons && !replaying && /* @__PURE__ */ a3("div", { class: "fnc-nav", style: { left: `${plotWidth / 2}px`, top: `${top}px` }, children: [
|
|
2340
|
+
button(t3.zoomOut, () => ctx.chart.zoom(1 / ZOOM_STEP), /* @__PURE__ */ a3(MinusIcon, {})),
|
|
2341
|
+
button(t3.zoomIn, () => ctx.chart.zoom(ZOOM_STEP), /* @__PURE__ */ a3(PlusIcon, {})),
|
|
2342
|
+
button(t3.scrollBack, () => ctx.chart.scrollBars(-page()), /* @__PURE__ */ a3(ChevronLeftIcon, {})),
|
|
2343
|
+
button(t3.scrollForward, () => ctx.chart.scrollBars(page()), /* @__PURE__ */ a3(ChevronRightIcon, {})),
|
|
2344
|
+
button(t3.resetView, () => ctx.chart.resetView(), /* @__PURE__ */ a3(ResetIcon, {}))
|
|
2101
2345
|
] }),
|
|
2102
|
-
!s3.atRealtime && /* @__PURE__ */
|
|
2346
|
+
!s3.atRealtime && /* @__PURE__ */ a3(
|
|
2103
2347
|
"button",
|
|
2104
2348
|
{
|
|
2105
2349
|
class: "fnc-realtime",
|
|
2106
2350
|
style: { left: `${plotWidth - 44}px`, top: `${top}px` },
|
|
2107
|
-
|
|
2351
|
+
"data-tip": t3.toRealtime,
|
|
2108
2352
|
"aria-label": t3.toRealtime,
|
|
2109
2353
|
onClick: () => ctx.chart.scrollToRealtime(),
|
|
2110
|
-
children: /* @__PURE__ */
|
|
2354
|
+
children: /* @__PURE__ */ a3(ToRealtimeIcon, {})
|
|
2111
2355
|
}
|
|
2112
2356
|
)
|
|
2113
2357
|
] });
|
|
@@ -2118,25 +2362,25 @@ function Attribution({ ctx }) {
|
|
|
2118
2362
|
const { panesHeight, plotWidth } = s3.layout;
|
|
2119
2363
|
if (!ctx.attribution || plotWidth <= 0) return null;
|
|
2120
2364
|
const label = s3.locale === "ko" ? "Funnest \uCC28\uD2B8" : "Charts by Funnest";
|
|
2121
|
-
return /* @__PURE__ */
|
|
2365
|
+
return /* @__PURE__ */ a3(
|
|
2122
2366
|
"a",
|
|
2123
2367
|
{
|
|
2124
2368
|
class: "fnc-attribution",
|
|
2125
2369
|
href: ATTRIBUTION_URL,
|
|
2126
2370
|
target: "_blank",
|
|
2127
2371
|
rel: "noopener",
|
|
2128
|
-
|
|
2372
|
+
"data-tip": label,
|
|
2129
2373
|
"aria-label": label,
|
|
2130
2374
|
style: { top: `${panesHeight - 36}px` },
|
|
2131
2375
|
children: [
|
|
2132
|
-
/* @__PURE__ */
|
|
2133
|
-
/* @__PURE__ */
|
|
2376
|
+
/* @__PURE__ */ a3(FunnestMark, {}),
|
|
2377
|
+
/* @__PURE__ */ a3("span", { children: "funnest" })
|
|
2134
2378
|
]
|
|
2135
2379
|
}
|
|
2136
2380
|
);
|
|
2137
2381
|
}
|
|
2138
2382
|
function PaneTools({ ctx }) {
|
|
2139
|
-
return ctx.multi ? /* @__PURE__ */
|
|
2383
|
+
return ctx.multi ? /* @__PURE__ */ a3(PaneMaximize, { ctx, multi: ctx.multi }) : null;
|
|
2140
2384
|
}
|
|
2141
2385
|
function PaneMaximize({ ctx, multi }) {
|
|
2142
2386
|
const s3 = useStore(ctx.store);
|
|
@@ -2145,29 +2389,70 @@ function PaneMaximize({ ctx, multi }) {
|
|
|
2145
2389
|
const t3 = STRINGS[s3.locale];
|
|
2146
2390
|
const maximized = m3.maximized !== null;
|
|
2147
2391
|
const label = maximized ? t3.restorePane : t3.maximizePane;
|
|
2148
|
-
return /* @__PURE__ */
|
|
2392
|
+
return /* @__PURE__ */ a3(
|
|
2149
2393
|
"button",
|
|
2150
2394
|
{
|
|
2151
2395
|
class: "fnc-btn fnc-pane-max",
|
|
2152
2396
|
style: { left: `${s3.layout.plotWidth - 36}px` },
|
|
2153
|
-
|
|
2397
|
+
"data-tip": `${label} (Alt+Enter)`,
|
|
2154
2398
|
"aria-label": label,
|
|
2155
2399
|
"aria-pressed": maximized,
|
|
2156
2400
|
onClick: () => {
|
|
2157
2401
|
const index = multi.store.get().active;
|
|
2158
2402
|
multi.toggleMaximize(index);
|
|
2159
2403
|
},
|
|
2160
|
-
children: maximized ? /* @__PURE__ */
|
|
2404
|
+
children: maximized ? /* @__PURE__ */ a3(RestoreIcon, {}) : /* @__PURE__ */ a3(MaximizeIcon, {})
|
|
2161
2405
|
}
|
|
2162
2406
|
);
|
|
2163
2407
|
}
|
|
2408
|
+
var REPLAY_SPEEDS = [
|
|
2409
|
+
{ label: "1x", interval: 1e3 },
|
|
2410
|
+
{ label: "3x", interval: 333 },
|
|
2411
|
+
{ label: "10x", interval: 100 }
|
|
2412
|
+
];
|
|
2413
|
+
function ReplayBar({ ctx }) {
|
|
2414
|
+
const s3 = useStore(ctx.store);
|
|
2415
|
+
const t3 = STRINGS[s3.locale];
|
|
2416
|
+
const r3 = s3.replay;
|
|
2417
|
+
const { plotWidth, panesHeight } = s3.layout;
|
|
2418
|
+
if (plotWidth <= 0 || !r3.active && !r3.selecting) return null;
|
|
2419
|
+
const style = { left: `${plotWidth / 2}px`, top: `${panesHeight - CONTROL_OFFSET}px` };
|
|
2420
|
+
if (!r3.active) {
|
|
2421
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-replay fnc-replay-hint", style, role: "status", children: [
|
|
2422
|
+
/* @__PURE__ */ a3(ReplayIcon, {}),
|
|
2423
|
+
/* @__PURE__ */ a3("span", { children: t3.replayPick }),
|
|
2424
|
+
/* @__PURE__ */ a3("button", { class: "fnc-ind-btn", "aria-label": t3.cancel, "data-tip": `${t3.cancel} (Esc)`, onClick: () => ctx.chart.setReplaySelecting(false), children: /* @__PURE__ */ a3(SmallCloseIcon, {}) })
|
|
2425
|
+
] });
|
|
2426
|
+
}
|
|
2427
|
+
const done = r3.remaining === 0;
|
|
2428
|
+
const button = (label, onClick, icon, disabled = false) => /* @__PURE__ */ a3("button", { class: "fnc-btn", "data-tip": label, "aria-label": label, disabled, onClick, children: icon });
|
|
2429
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-replay", style, role: "toolbar", "aria-label": t3.replay, children: [
|
|
2430
|
+
r3.playing ? button(t3.replayPause, () => ctx.chart.replayPause(), /* @__PURE__ */ a3(PauseIcon, {})) : button(t3.replayPlay, () => ctx.chart.replayPlay(), /* @__PURE__ */ a3(PlayIcon, {}), done),
|
|
2431
|
+
button(t3.replayStep, () => ctx.chart.replayStep(), /* @__PURE__ */ a3(StepIcon, {}), done),
|
|
2432
|
+
/* @__PURE__ */ a3("div", { class: "fnc-seg fnc-seg-sm", role: "radiogroup", "aria-label": t3.replaySpeed, children: REPLAY_SPEEDS.map((speed) => /* @__PURE__ */ a3(
|
|
2433
|
+
"button",
|
|
2434
|
+
{
|
|
2435
|
+
type: "button",
|
|
2436
|
+
role: "radio",
|
|
2437
|
+
"aria-checked": r3.interval === speed.interval,
|
|
2438
|
+
onClick: () => ctx.chart.setReplayInterval(speed.interval),
|
|
2439
|
+
children: speed.label
|
|
2440
|
+
}
|
|
2441
|
+
)) }),
|
|
2442
|
+
done && /* @__PURE__ */ a3("span", { class: "fnc-replay-note", children: t3.replayDone }),
|
|
2443
|
+
/* @__PURE__ */ a3("div", { class: "fnc-sep" }),
|
|
2444
|
+
button(t3.replayRestart, () => ctx.chart.setReplaySelecting(true), /* @__PURE__ */ a3(ReplayIcon, {})),
|
|
2445
|
+
button(t3.replayExit, () => ctx.chart.stopReplay(), /* @__PURE__ */ a3(SmallCloseIcon, {}))
|
|
2446
|
+
] });
|
|
2447
|
+
}
|
|
2164
2448
|
function Overlay({ ctx }) {
|
|
2165
|
-
return /* @__PURE__ */
|
|
2166
|
-
/* @__PURE__ */
|
|
2167
|
-
/* @__PURE__ */
|
|
2168
|
-
/* @__PURE__ */
|
|
2169
|
-
/* @__PURE__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
2449
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
2450
|
+
/* @__PURE__ */ a3(Attribution, { ctx }),
|
|
2451
|
+
/* @__PURE__ */ a3(Legend, { ctx }),
|
|
2452
|
+
/* @__PURE__ */ a3(NavControls, { ctx }),
|
|
2453
|
+
/* @__PURE__ */ a3(ReplayBar, { ctx }),
|
|
2454
|
+
/* @__PURE__ */ a3(SelectionBar, { ctx }),
|
|
2455
|
+
/* @__PURE__ */ a3(PaneTools, { ctx })
|
|
2171
2456
|
] });
|
|
2172
2457
|
}
|
|
2173
2458
|
|
|
@@ -2696,6 +2981,38 @@ var CSS = (
|
|
|
2696
2981
|
flex: none;
|
|
2697
2982
|
}
|
|
2698
2983
|
|
|
2984
|
+
/* Tooltip (data-tip). Hosts can restyle it with --fnc-tip-bg / --fnc-tip-text. */
|
|
2985
|
+
.fnc-tip {
|
|
2986
|
+
position: fixed;
|
|
2987
|
+
z-index: 2147483001;
|
|
2988
|
+
max-width: 240px;
|
|
2989
|
+
padding: 6px 10px;
|
|
2990
|
+
border-radius: 8px;
|
|
2991
|
+
background: var(--fnc-tip-bg, #24242b);
|
|
2992
|
+
color: var(--fnc-tip-text, #f2f2f4);
|
|
2993
|
+
font-family: var(--fnc-font);
|
|
2994
|
+
font-size: 12px;
|
|
2995
|
+
font-weight: 500;
|
|
2996
|
+
line-height: 1.4;
|
|
2997
|
+
white-space: nowrap;
|
|
2998
|
+
box-shadow: 0 6px 20px rgb(0 0 0 / 0.28);
|
|
2999
|
+
pointer-events: none;
|
|
3000
|
+
opacity: 0;
|
|
3001
|
+
visibility: hidden;
|
|
3002
|
+
transition: opacity 120ms cubic-bezier(0.4, 0, 1, 1), transform 120ms cubic-bezier(0.4, 0, 1, 1), visibility 0s 120ms;
|
|
3003
|
+
}
|
|
3004
|
+
.fnc-tip[data-side='bottom'] { transform: translateY(-4px); }
|
|
3005
|
+
.fnc-tip[data-side='top'] { transform: translateY(4px); }
|
|
3006
|
+
.fnc-tip[data-side='right'] { transform: translateX(-4px); }
|
|
3007
|
+
.fnc-tip.is-on {
|
|
3008
|
+
opacity: 1;
|
|
3009
|
+
visibility: visible;
|
|
3010
|
+
transform: none;
|
|
3011
|
+
transition: opacity 180ms cubic-bezier(0.16, 1, 0.3, 1), transform 180ms cubic-bezier(0.16, 1, 0.3, 1), visibility 0s;
|
|
3012
|
+
}
|
|
3013
|
+
@media (prefers-reduced-motion: reduce) { .fnc-tip, .fnc-tip.is-on { transform: none; } }
|
|
3014
|
+
@media (hover: none) { .fnc-tip { display: none; } }
|
|
3015
|
+
|
|
2699
3016
|
.fnc-tools { display: flex; align-items: center; gap: 4px; flex: none; }
|
|
2700
3017
|
/* Right-hand menus open toward the left so they stay on screen. */
|
|
2701
3018
|
.fnc-tools .fnc-menu { left: auto; right: 0; }
|
|
@@ -2934,6 +3251,20 @@ var CSS = (
|
|
|
2934
3251
|
.fnc-action-primary { background: var(--fnc-accent); color: #fff; }
|
|
2935
3252
|
.fnc-action-danger { flex: 0 0 auto; padding: 0 16px; color: var(--fnc-danger, #F04452); background: none; }
|
|
2936
3253
|
|
|
3254
|
+
/* \u2500\u2500 Narrow widgets (split screens next to side panels): the widget's own width decides, so
|
|
3255
|
+
every toolbar button stays reachable. Ctrl/\u2318+Z still undoes when the buttons are hidden. \u2500\u2500 */
|
|
3256
|
+
.fnc-root { container: fnc / inline-size; }
|
|
3257
|
+
@container fnc (max-width: 1100px) {
|
|
3258
|
+
.fnc-btn-undo { display: none; }
|
|
3259
|
+
.fnc-btn-label span { display: none; }
|
|
3260
|
+
.fnc-toolbar .fnc-btn-label { padding: 0 6px; }
|
|
3261
|
+
}
|
|
3262
|
+
@container fnc (max-width: 940px) {
|
|
3263
|
+
.fnc-intervals { display: none; }
|
|
3264
|
+
.fnc-interval-current { display: inline; }
|
|
3265
|
+
.fnc-btn-screenshot { display: none; }
|
|
3266
|
+
}
|
|
3267
|
+
|
|
2937
3268
|
/* \u2500\u2500 Narrow phones (\u2264 400px): drop the menu chevrons and separators so every button fits \u2500\u2500 */
|
|
2938
3269
|
@media (max-width: 400px) {
|
|
2939
3270
|
.fnc-toolbar .fnc-btn-wide > svg:last-child { display: none; }
|
|
@@ -3038,8 +3369,79 @@ var CSS = (
|
|
|
3038
3369
|
.fnc-switch[data-on='true'] { background: var(--fnc-text-2); }
|
|
3039
3370
|
.fnc-switch[data-on='true']::after { transform: translateX(16px); }
|
|
3040
3371
|
|
|
3372
|
+
/* \u2500\u2500 Drawing tool groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3373
|
+
.fnc-tool-group { position: relative; display: flex; }
|
|
3374
|
+
.fnc-tool-group[data-open='true'] { z-index: 30; }
|
|
3375
|
+
.fnc-tool-more {
|
|
3376
|
+
position: absolute;
|
|
3377
|
+
right: -2px;
|
|
3378
|
+
bottom: -2px;
|
|
3379
|
+
display: flex;
|
|
3380
|
+
align-items: flex-end;
|
|
3381
|
+
justify-content: flex-end;
|
|
3382
|
+
width: 14px;
|
|
3383
|
+
height: 14px;
|
|
3384
|
+
padding: 3px;
|
|
3385
|
+
color: var(--fnc-text-2);
|
|
3386
|
+
opacity: 0.7;
|
|
3387
|
+
}
|
|
3388
|
+
.fnc-tool-more:hover, .fnc-tool-more[aria-expanded='true'] { opacity: 1; color: var(--fnc-text); }
|
|
3389
|
+
.fnc-tool-menu { top: 0; left: calc(100% + 8px); min-width: 180px; }
|
|
3390
|
+
.fnc-tool-menu .fnc-menu-item { white-space: nowrap; }
|
|
3391
|
+
.fnc-tool-letter { font-size: 13px; font-weight: 700; }
|
|
3392
|
+
.fnc-svg-icon { display: inline-flex; }
|
|
3393
|
+
.fnc-svg-icon svg { width: 20px; height: 20px; }
|
|
3394
|
+
|
|
3395
|
+
/* \u2500\u2500 Segmented control (price scale, replay speed) \u2500\u2500\u2500\u2500 */
|
|
3396
|
+
.fnc-seg { display: inline-flex; gap: 2px; padding: 2px; border-radius: calc(var(--fnc-radius) + 2px); background: var(--fnc-surface); }
|
|
3397
|
+
.fnc-seg button {
|
|
3398
|
+
min-width: 56px;
|
|
3399
|
+
height: 30px;
|
|
3400
|
+
padding: 0 12px;
|
|
3401
|
+
border-radius: var(--fnc-radius);
|
|
3402
|
+
font-size: 13px;
|
|
3403
|
+
color: var(--fnc-text-2);
|
|
3404
|
+
}
|
|
3405
|
+
.fnc-seg button[aria-checked='true'] { background: var(--fnc-bg); color: var(--fnc-text); font-weight: 700; box-shadow: 0 1px 3px rgb(0 0 0 / 0.12); }
|
|
3406
|
+
.fnc-seg-sm button { min-width: 36px; height: 26px; padding: 0 6px; font-size: 12px; }
|
|
3407
|
+
|
|
3408
|
+
/* \u2500\u2500 Compare legend rows \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3409
|
+
.fnc-cmp { display: flex; align-items: center; gap: 6px; min-height: 22px; font-size: 12px; color: var(--fnc-text-2); pointer-events: auto; }
|
|
3410
|
+
.fnc-cmp-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
|
|
3411
|
+
.fnc-cmp-name { color: var(--fnc-text); }
|
|
3412
|
+
.fnc-cmp b { color: var(--fnc-text); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
3413
|
+
.fnc-cmp .fnc-ind-btn { opacity: 0; }
|
|
3414
|
+
.fnc-cmp:hover .fnc-ind-btn, .fnc-cmp .fnc-ind-btn:focus-visible { opacity: 1; }
|
|
3415
|
+
@media (hover: none) { .fnc-cmp .fnc-ind-btn { opacity: 1; } }
|
|
3416
|
+
|
|
3417
|
+
/* \u2500\u2500 Replay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3418
|
+
.fnc-replay {
|
|
3419
|
+
position: absolute;
|
|
3420
|
+
z-index: 6;
|
|
3421
|
+
display: flex;
|
|
3422
|
+
align-items: center;
|
|
3423
|
+
gap: 4px;
|
|
3424
|
+
padding: 4px;
|
|
3425
|
+
transform: translateX(-50%);
|
|
3426
|
+
border-radius: calc(var(--fnc-radius) + 4px);
|
|
3427
|
+
background: var(--fnc-bg);
|
|
3428
|
+
box-shadow: 0 2px 12px rgb(0 0 0 / 0.12), 0 0 0 1px var(--fnc-border);
|
|
3429
|
+
white-space: nowrap;
|
|
3430
|
+
pointer-events: auto;
|
|
3431
|
+
}
|
|
3432
|
+
.fnc-replay .fnc-btn { width: 32px; height: 32px; }
|
|
3433
|
+
.fnc-replay .fnc-sep { height: 20px; margin: 0 2px; }
|
|
3434
|
+
.fnc-replay-hint { gap: 8px; padding: 4px 4px 4px 12px; font-size: 13px; color: var(--fnc-text); }
|
|
3435
|
+
.fnc-replay-hint svg { color: var(--fnc-text-2); }
|
|
3436
|
+
.fnc-replay-note { padding: 0 6px; font-size: 12px; color: var(--fnc-text-2); }
|
|
3437
|
+
|
|
3438
|
+
/* Indicator picker search (shown when custom indicators make the list long) */
|
|
3439
|
+
.fnc-ind-search { height: 48px; padding: 0 16px; }
|
|
3440
|
+
.fnc-ind-search input { font-size: 15px; }
|
|
3441
|
+
|
|
3041
3442
|
/* \u2500\u2500 Mobile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3042
3443
|
@media (max-width: 640px) {
|
|
3444
|
+
.fnc-btn-compare, .fnc-btn-replay, .fnc-btn-undo { display: none; }
|
|
3043
3445
|
.fnc-toolbar { padding: 0 4px; gap: 2px; }
|
|
3044
3446
|
.fnc-toolbar .fnc-btn { width: 32px; height: 32px; }
|
|
3045
3447
|
.fnc-toolbar .fnc-btn-wide, .fnc-toolbar .fnc-btn-label { width: auto; padding: 0 6px; }
|
|
@@ -3116,6 +3518,77 @@ function div(className, parent) {
|
|
|
3116
3518
|
parent?.appendChild(el);
|
|
3117
3519
|
return el;
|
|
3118
3520
|
}
|
|
3521
|
+
function bindTooltips(root) {
|
|
3522
|
+
const tip = div("fnc-tip", root);
|
|
3523
|
+
tip.setAttribute("role", "tooltip");
|
|
3524
|
+
tip.id = `fnc-tip-${Math.random().toString(36).slice(2, 8)}`;
|
|
3525
|
+
let current = null;
|
|
3526
|
+
let timer;
|
|
3527
|
+
let hiddenAt = 0;
|
|
3528
|
+
const place = (el) => {
|
|
3529
|
+
const r3 = el.getBoundingClientRect();
|
|
3530
|
+
const w3 = tip.offsetWidth;
|
|
3531
|
+
const h3 = tip.offsetHeight;
|
|
3532
|
+
const vw = window.innerWidth;
|
|
3533
|
+
const vh = window.innerHeight;
|
|
3534
|
+
let side = el.closest(".fnc-drawbar") ? "right" : el.closest(".fnc-nav") ? "top" : "bottom";
|
|
3535
|
+
if (side === "bottom" && r3.bottom + h3 + 10 > vh) side = "top";
|
|
3536
|
+
let left = side === "right" ? r3.right + 8 : r3.left + r3.width / 2 - w3 / 2;
|
|
3537
|
+
const top = side === "right" ? r3.top + r3.height / 2 - h3 / 2 : side === "top" ? r3.top - h3 - 6 : r3.bottom + 6;
|
|
3538
|
+
left = Math.max(4, Math.min(vw - w3 - 4, left));
|
|
3539
|
+
tip.style.left = `${Math.round(left)}px`;
|
|
3540
|
+
tip.style.top = `${Math.round(top)}px`;
|
|
3541
|
+
tip.dataset.side = side;
|
|
3542
|
+
};
|
|
3543
|
+
const show = (el) => {
|
|
3544
|
+
const text = el.dataset.tip;
|
|
3545
|
+
if (!text || !el.isConnected) return;
|
|
3546
|
+
tip.textContent = text;
|
|
3547
|
+
el.setAttribute("aria-describedby", tip.id);
|
|
3548
|
+
place(el);
|
|
3549
|
+
tip.classList.add("is-on");
|
|
3550
|
+
};
|
|
3551
|
+
const hide = () => {
|
|
3552
|
+
clearTimeout(timer);
|
|
3553
|
+
if (tip.classList.contains("is-on")) hiddenAt = Date.now();
|
|
3554
|
+
tip.classList.remove("is-on");
|
|
3555
|
+
current?.removeAttribute("aria-describedby");
|
|
3556
|
+
current = null;
|
|
3557
|
+
};
|
|
3558
|
+
const target = (e3) => e3.target instanceof Element ? e3.target.closest("[data-tip]") : null;
|
|
3559
|
+
const onOver = (e3) => {
|
|
3560
|
+
if (e3.pointerType === "touch") return;
|
|
3561
|
+
const el = target(e3);
|
|
3562
|
+
if (el === current) return;
|
|
3563
|
+
hide();
|
|
3564
|
+
if (!el || !root.contains(el)) return;
|
|
3565
|
+
current = el;
|
|
3566
|
+
timer = setTimeout(() => show(el), Date.now() - hiddenAt < 300 ? 0 : 350);
|
|
3567
|
+
};
|
|
3568
|
+
const onFocus = (e3) => {
|
|
3569
|
+
const el = target(e3);
|
|
3570
|
+
if (!el || !e3.target.matches?.(":focus-visible")) return;
|
|
3571
|
+
hide();
|
|
3572
|
+
current = el;
|
|
3573
|
+
show(el);
|
|
3574
|
+
};
|
|
3575
|
+
root.addEventListener("pointerover", onOver);
|
|
3576
|
+
root.addEventListener("pointerleave", hide);
|
|
3577
|
+
root.addEventListener("pointerdown", hide, true);
|
|
3578
|
+
root.addEventListener("wheel", hide, { passive: true });
|
|
3579
|
+
root.addEventListener("focusin", onFocus);
|
|
3580
|
+
root.addEventListener("focusout", hide);
|
|
3581
|
+
return () => {
|
|
3582
|
+
hide();
|
|
3583
|
+
root.removeEventListener("pointerover", onOver);
|
|
3584
|
+
root.removeEventListener("pointerleave", hide);
|
|
3585
|
+
root.removeEventListener("pointerdown", hide, true);
|
|
3586
|
+
root.removeEventListener("wheel", hide);
|
|
3587
|
+
root.removeEventListener("focusin", onFocus);
|
|
3588
|
+
root.removeEventListener("focusout", hide);
|
|
3589
|
+
tip.remove();
|
|
3590
|
+
};
|
|
3591
|
+
}
|
|
3119
3592
|
function createShell(container, options) {
|
|
3120
3593
|
injectStyles(container.ownerDocument);
|
|
3121
3594
|
const storage = createStorage(options.storageKey);
|
|
@@ -3142,6 +3615,7 @@ function createShell(container, options) {
|
|
|
3142
3615
|
bottom: div("fnc-slot fnc-slot-bottom"),
|
|
3143
3616
|
footer: div("fnc-slot fnc-slot-footer")
|
|
3144
3617
|
};
|
|
3618
|
+
const unbindTips = bindTooltips(root);
|
|
3145
3619
|
const body = div("fnc-body", root);
|
|
3146
3620
|
const drawbarHost = options.drawingToolbar ? div("fnc-drawbar-host", body) : null;
|
|
3147
3621
|
const main = div("fnc-main", body);
|
|
@@ -3207,6 +3681,7 @@ function createShell(container, options) {
|
|
|
3207
3681
|
options.onFavoriteIntervalsChange?.(favoriteIntervals);
|
|
3208
3682
|
},
|
|
3209
3683
|
destroy: () => {
|
|
3684
|
+
unbindTips();
|
|
3210
3685
|
document.removeEventListener("fullscreenchange", onFullscreenChange);
|
|
3211
3686
|
darkQuery?.removeEventListener?.("change", onSchemeChange);
|
|
3212
3687
|
if (isNativeFullscreen()) void document.exitFullscreen();
|
|
@@ -3216,10 +3691,21 @@ function createShell(container, options) {
|
|
|
3216
3691
|
}
|
|
3217
3692
|
function bindWidgetKeys(shell, active, searchHotkey, extra) {
|
|
3218
3693
|
const { root } = shell;
|
|
3694
|
+
let focused = false;
|
|
3695
|
+
const onPointerDown = (e3) => focused = root.contains(e3.target);
|
|
3219
3696
|
const onKeyDown = (e3) => {
|
|
3220
3697
|
const pane = active();
|
|
3221
3698
|
if (!pane) return;
|
|
3222
3699
|
const s3 = pane.store.get();
|
|
3700
|
+
const target = e3.target;
|
|
3701
|
+
const typing = !!target && (target.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName));
|
|
3702
|
+
const key = e3.key.toLowerCase();
|
|
3703
|
+
if (focused && !typing && !s3.dialog && !s3.searchOpen && (e3.ctrlKey || e3.metaKey) && !e3.altKey && (key === "z" || key === "y")) {
|
|
3704
|
+
e3.preventDefault();
|
|
3705
|
+
if (key === "y" || e3.shiftKey) pane.chart.redo();
|
|
3706
|
+
else pane.chart.undo();
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3223
3709
|
if (searchHotkey && (e3.ctrlKey || e3.metaKey) && e3.key.toLowerCase() === "k" && pane.canSearch && !s3.dialog) {
|
|
3224
3710
|
e3.preventDefault();
|
|
3225
3711
|
pane.store.set({ searchOpen: true });
|
|
@@ -3244,9 +3730,11 @@ function bindWidgetKeys(shell, active, searchHotkey, extra) {
|
|
|
3244
3730
|
};
|
|
3245
3731
|
document.addEventListener("keydown", onKeyDown);
|
|
3246
3732
|
document.addEventListener("keyup", onKeyUp);
|
|
3733
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
3247
3734
|
return () => {
|
|
3248
3735
|
document.removeEventListener("keydown", onKeyDown);
|
|
3249
3736
|
document.removeEventListener("keyup", onKeyUp);
|
|
3737
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
3250
3738
|
};
|
|
3251
3739
|
}
|
|
3252
3740
|
|
|
@@ -3270,6 +3758,11 @@ function createPane(shell, config) {
|
|
|
3270
3758
|
layout: chart.layout,
|
|
3271
3759
|
atRealtime: true,
|
|
3272
3760
|
searchOpen: false,
|
|
3761
|
+
searchTarget: "symbol",
|
|
3762
|
+
canUndo: chart.canUndo,
|
|
3763
|
+
canRedo: chart.canRedo,
|
|
3764
|
+
compares: chart.getCompares(),
|
|
3765
|
+
replay: chart.replay,
|
|
3273
3766
|
chartType: config.chartType,
|
|
3274
3767
|
drawingTool: null,
|
|
3275
3768
|
selection: null,
|
|
@@ -3292,7 +3785,10 @@ function createPane(shell, config) {
|
|
|
3292
3785
|
chart.on("drawingsChange", (drawings) => store.set({ drawingCount: drawings.length })),
|
|
3293
3786
|
chart.on("indicatorsChange", (indicators) => store.set({ indicators })),
|
|
3294
3787
|
chart.on("magnetChange", (magnet) => store.set({ magnet })),
|
|
3295
|
-
chart.on("chartTypeChange", (chartType) => store.set({ chartType }))
|
|
3788
|
+
chart.on("chartTypeChange", (chartType) => store.set({ chartType })),
|
|
3789
|
+
chart.on("historyChange", ({ canUndo, canRedo }) => store.set({ canUndo, canRedo })),
|
|
3790
|
+
chart.on("comparesChange", (compares) => store.set({ compares })),
|
|
3791
|
+
chart.on("replayChange", (replay) => store.set({ replay }))
|
|
3296
3792
|
];
|
|
3297
3793
|
const load = (sym, res) => {
|
|
3298
3794
|
store.set({ resolution: res });
|
|
@@ -3322,7 +3818,7 @@ function createPane(shell, config) {
|
|
|
3322
3818
|
if (current) void load(current.symbol, res);
|
|
3323
3819
|
},
|
|
3324
3820
|
toggleFavoriteInterval: shell.toggleFavoriteInterval,
|
|
3325
|
-
setSearchOpen: (open) => store.set({ searchOpen:
|
|
3821
|
+
setSearchOpen: (open, target = "symbol") => store.set(open ? { searchOpen: true, searchTarget: target } : { searchOpen: false }),
|
|
3326
3822
|
screenshot: () => {
|
|
3327
3823
|
const s3 = store.get();
|
|
3328
3824
|
chart.takeScreenshot().toBlob((blob) => {
|
|
@@ -3336,7 +3832,7 @@ function createPane(shell, config) {
|
|
|
3336
3832
|
},
|
|
3337
3833
|
toggleFullscreen: shell.toggleFullscreen
|
|
3338
3834
|
};
|
|
3339
|
-
Q(/* @__PURE__ */
|
|
3835
|
+
Q(/* @__PURE__ */ a3(Overlay, { ctx }), overlayHost);
|
|
3340
3836
|
return {
|
|
3341
3837
|
stage,
|
|
3342
3838
|
chart,
|
|
@@ -3414,8 +3910,8 @@ function createTradingChart(container, options) {
|
|
|
3414
3910
|
shell.main.insertBefore(pane.stage, shell.slots.bottom);
|
|
3415
3911
|
shell.setPanes(() => [pane]);
|
|
3416
3912
|
const unbindKeys = bindWidgetKeys(shell, () => pane, searchHotkey);
|
|
3417
|
-
Q(/* @__PURE__ */
|
|
3418
|
-
if (shell.drawbarHost) Q(/* @__PURE__ */
|
|
3913
|
+
Q(/* @__PURE__ */ a3(Toolbar, { ctx: pane.ctx }), shell.toolbarHost);
|
|
3914
|
+
if (shell.drawbarHost) Q(/* @__PURE__ */ a3(DrawingToolbar, { ctx: pane.ctx }), shell.drawbarHost);
|
|
3419
3915
|
void pane.load(symbol, resolution);
|
|
3420
3916
|
return {
|
|
3421
3917
|
chart: pane.chart,
|
|
@@ -3449,17 +3945,17 @@ var DEFAULT_SYNC = { crosshair: true, time: false, symbol: false, interval: fals
|
|
|
3449
3945
|
function PaneTab({ pane, index, active, onSelect }) {
|
|
3450
3946
|
const s3 = useStore(pane.store);
|
|
3451
3947
|
const t3 = STRINGS[s3.locale];
|
|
3452
|
-
return /* @__PURE__ */
|
|
3453
|
-
/* @__PURE__ */
|
|
3948
|
+
return /* @__PURE__ */ a3("button", { class: "fnc-pane-tab", role: "tab", "aria-selected": active, onClick: onSelect, children: [
|
|
3949
|
+
/* @__PURE__ */ a3("span", { class: "fnc-pane-tab-num", children: index + 1 }),
|
|
3454
3950
|
s3.symbol?.name ?? `${t3.pane} ${index + 1}`,
|
|
3455
|
-
/* @__PURE__ */
|
|
3951
|
+
/* @__PURE__ */ a3("small", { children: resolutionLabel(s3.resolution, s3.locale) })
|
|
3456
3952
|
] });
|
|
3457
3953
|
}
|
|
3458
3954
|
function PaneTabs({ multi, panes }) {
|
|
3459
3955
|
const m3 = useStore(multi.store);
|
|
3460
3956
|
const visible = panes().slice(0, paneCount(LAYOUTS[m3.layout]));
|
|
3461
3957
|
if (!m3.narrow || visible.length < 2) return null;
|
|
3462
|
-
return /* @__PURE__ */
|
|
3958
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-pane-tabs", role: "tablist", children: visible.map((p3, i3) => /* @__PURE__ */ a3(PaneTab, { pane: p3, index: i3, active: i3 === m3.active, onSelect: () => multi.activate(i3) })) });
|
|
3463
3959
|
}
|
|
3464
3960
|
function createMultiChart(container, options) {
|
|
3465
3961
|
const {
|
|
@@ -3664,8 +4160,8 @@ function createMultiChart(container, options) {
|
|
|
3664
4160
|
}
|
|
3665
4161
|
function bindToolbar() {
|
|
3666
4162
|
const pane = panes[store.get().active];
|
|
3667
|
-
Q(/* @__PURE__ */
|
|
3668
|
-
if (shell.drawbarHost) Q(/* @__PURE__ */
|
|
4163
|
+
Q(/* @__PURE__ */ a3(Toolbar, { ctx: pane.ctx }, store.get().active), shell.toolbarHost);
|
|
4164
|
+
if (shell.drawbarHost) Q(/* @__PURE__ */ a3(DrawingToolbar, { ctx: pane.ctx }, store.get().active), shell.drawbarHost);
|
|
3669
4165
|
}
|
|
3670
4166
|
function activate(index) {
|
|
3671
4167
|
const s3 = store.get();
|
|
@@ -3722,7 +4218,7 @@ function createMultiChart(container, options) {
|
|
|
3722
4218
|
ensurePanes(Math.max(visibleCount(), Math.min(paneSpecs.length, MAX_PANES)));
|
|
3723
4219
|
shell.setPanes(() => panes);
|
|
3724
4220
|
bindToolbar();
|
|
3725
|
-
Q(/* @__PURE__ */
|
|
4221
|
+
Q(/* @__PURE__ */ a3(PaneTabs, { multi: controls, panes: () => panes }), tabsHost);
|
|
3726
4222
|
renderGrid();
|
|
3727
4223
|
const resize = new ResizeObserver(() => {
|
|
3728
4224
|
const narrow = shell.root.clientWidth > 0 && shell.root.clientWidth < narrowWidth;
|