@funnest/charts-ui 0.6.1 → 0.6.3
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/layout-menu.d.ts +1 -6
- package/dist/components/tools-menu.d.ts +10 -0
- package/dist/i18n.d.ts +2 -0
- package/dist/icons.d.ts +2 -0
- package/dist/index.js +269 -307
- package/package.json +2 -2
- package/dist/components/chart-type-menu.d.ts +0 -5
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** @jsxImportSource preact */
|
|
2
2
|
import { type LayoutId } from '../layouts';
|
|
3
3
|
/** Mini drawing of a split layout. */
|
|
4
4
|
export declare function LayoutGlyph({ id }: {
|
|
5
5
|
id: LayoutId;
|
|
6
6
|
}): import("preact").JSX.Element;
|
|
7
|
-
/** Toolbar buttons of the multi-chart widget: split layout picker and pane sync toggles. */
|
|
8
|
-
export declare function LayoutMenu({ ctx, multi }: {
|
|
9
|
-
ctx: WidgetContext;
|
|
10
|
-
multi: MultiControls;
|
|
11
|
-
}): import("preact").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
import type { WidgetContext } from '../context';
|
|
3
|
+
/**
|
|
4
|
+
* One "도구" button for the chart's less frequent tools, so the toolbar keeps symbol, interval,
|
|
5
|
+
* market info and 지표 in view: chart type, split layout (+ sync), compare, replay, price axis,
|
|
6
|
+
* screenshot and chart settings.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ToolsMenu({ ctx }: {
|
|
9
|
+
ctx: WidgetContext;
|
|
10
|
+
}): JSX.Element;
|
package/dist/i18n.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export declare const STRINGS: {
|
|
|
47
47
|
scaleLog: string;
|
|
48
48
|
scalePercent: string;
|
|
49
49
|
undo: string;
|
|
50
|
+
tools: string;
|
|
50
51
|
horizontalAt: string;
|
|
51
52
|
resetChart: string;
|
|
52
53
|
chartSettingsMore: string;
|
|
@@ -176,6 +177,7 @@ export declare const STRINGS: {
|
|
|
176
177
|
scaleLog: string;
|
|
177
178
|
scalePercent: string;
|
|
178
179
|
undo: string;
|
|
180
|
+
tools: string;
|
|
179
181
|
horizontalAt: string;
|
|
180
182
|
resetChart: string;
|
|
181
183
|
chartSettingsMore: string;
|
package/dist/icons.d.ts
CHANGED
|
@@ -52,3 +52,5 @@ export declare const SvgIcon: ({ markup }: {
|
|
|
52
52
|
}) => import("preact").JSX.Element;
|
|
53
53
|
/** Tiny corner triangle on drawing-bar buttons that hold more tools. */
|
|
54
54
|
export declare const CornerIcon: () => import("preact").JSX.Element;
|
|
55
|
+
/** Sliders: the 도구 menu. */
|
|
56
|
+
export declare const ToolsIcon: () => import("preact").JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -470,6 +470,7 @@ var STRINGS = {
|
|
|
470
470
|
scaleLog: "\uB85C\uADF8",
|
|
471
471
|
scalePercent: "%",
|
|
472
472
|
undo: "\uB418\uB3CC\uB9AC\uAE30",
|
|
473
|
+
tools: "\uB3C4\uAD6C",
|
|
473
474
|
horizontalAt: "{price}\uC5D0 \uC218\uD3C9\uC120 \uAE0B\uAE30",
|
|
474
475
|
resetChart: "\uCC28\uD2B8 \uCD08\uAE30\uD654",
|
|
475
476
|
chartSettingsMore: "\uCC28\uD2B8 \uC124\uC815\u2026",
|
|
@@ -601,6 +602,7 @@ var STRINGS = {
|
|
|
601
602
|
scaleLog: "Log",
|
|
602
603
|
scalePercent: "%",
|
|
603
604
|
undo: "Undo",
|
|
605
|
+
tools: "Tools",
|
|
604
606
|
horizontalAt: "Horizontal line at {price}",
|
|
605
607
|
resetChart: "Reset chart",
|
|
606
608
|
chartSettingsMore: "Chart settings\u2026",
|
|
@@ -815,10 +817,6 @@ var FunnestMark = () => /* @__PURE__ */ a3("svg", { width: "20", height: "20", v
|
|
|
815
817
|
/* @__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" }),
|
|
816
818
|
/* @__PURE__ */ a3("circle", { cx: "24.6", cy: "8.6", r: "2.9", fill: "#FFD43B" })
|
|
817
819
|
] });
|
|
818
|
-
var LinkIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
819
|
-
/* @__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" }),
|
|
820
|
-
/* @__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" })
|
|
821
|
-
] });
|
|
822
820
|
var MaximizeIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M11 4h5v5M9 16H4v-5M16 4l-5 5M4 16l5-5" }) });
|
|
823
821
|
var RestoreIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M15 9h-4V5M5 11h4v4M11 9l5-5M9 11l-5 5" }) });
|
|
824
822
|
var CompareIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
@@ -851,6 +849,11 @@ var SvgIcon = ({ markup }) => markup.trim().startsWith("<svg") ? /* @__PURE__ */
|
|
|
851
849
|
}
|
|
852
850
|
);
|
|
853
851
|
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" }) });
|
|
852
|
+
var ToolsIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
853
|
+
/* @__PURE__ */ a3("path", { d: "M3.5 6h7M14.5 6h2M3.5 14h2M9.5 14h7" }),
|
|
854
|
+
/* @__PURE__ */ a3("circle", { cx: "12.5", cy: "6", r: "2" }),
|
|
855
|
+
/* @__PURE__ */ a3("circle", { cx: "7.5", cy: "14", r: "2" })
|
|
856
|
+
] });
|
|
854
857
|
|
|
855
858
|
// src/store.ts
|
|
856
859
|
var Store = class {
|
|
@@ -1037,93 +1040,6 @@ function SelectionBar({ ctx }) {
|
|
|
1037
1040
|
] });
|
|
1038
1041
|
}
|
|
1039
1042
|
|
|
1040
|
-
// src/components/keep-in-view.ts
|
|
1041
|
-
var MARGIN = 8;
|
|
1042
|
-
function useKeepInView(open) {
|
|
1043
|
-
const ref = T2(null);
|
|
1044
|
-
F2(() => {
|
|
1045
|
-
const el = ref.current;
|
|
1046
|
-
if (!open || !el) return;
|
|
1047
|
-
el.style.translate = "";
|
|
1048
|
-
const fit = () => {
|
|
1049
|
-
el.style.translate = "";
|
|
1050
|
-
const r3 = el.getBoundingClientRect();
|
|
1051
|
-
const root = el.closest(".fnc-root")?.getBoundingClientRect();
|
|
1052
|
-
const minX = Math.max(0, root?.left ?? 0) + MARGIN;
|
|
1053
|
-
const maxX = Math.min(document.documentElement.clientWidth, root?.right ?? Infinity) - MARGIN;
|
|
1054
|
-
let dx = 0;
|
|
1055
|
-
if (r3.right > maxX) dx = maxX - r3.right;
|
|
1056
|
-
if (r3.left + dx < minX) dx = minX - r3.left;
|
|
1057
|
-
if (dx) el.style.translate = `${Math.round(dx)}px 0`;
|
|
1058
|
-
};
|
|
1059
|
-
fit();
|
|
1060
|
-
window.addEventListener("resize", fit);
|
|
1061
|
-
return () => window.removeEventListener("resize", fit);
|
|
1062
|
-
}, [open]);
|
|
1063
|
-
return ref;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
// src/components/chart-type-menu.tsx
|
|
1067
|
-
var TYPES = [
|
|
1068
|
-
{ type: "candles", label: "candles", icon: CandlesIcon },
|
|
1069
|
-
{ type: "line", label: "line", icon: LineChartIcon },
|
|
1070
|
-
{ type: "area", label: "area", icon: AreaChartIcon }
|
|
1071
|
-
];
|
|
1072
|
-
function ChartTypeMenu({ ctx }) {
|
|
1073
|
-
const s3 = useStore(ctx.store);
|
|
1074
|
-
const t3 = STRINGS[s3.locale];
|
|
1075
|
-
const [open, setOpen] = d2(false);
|
|
1076
|
-
const ref = T2(null);
|
|
1077
|
-
const menuRef = useKeepInView(open);
|
|
1078
|
-
const current = TYPES.find((x2) => x2.type === s3.chartType) ?? TYPES[0];
|
|
1079
|
-
A2(() => {
|
|
1080
|
-
if (!open) return;
|
|
1081
|
-
const onDown = (e3) => !ref.current?.contains(e3.target) && setOpen(false);
|
|
1082
|
-
const onKey = (e3) => e3.key === "Escape" && setOpen(false);
|
|
1083
|
-
document.addEventListener("pointerdown", onDown);
|
|
1084
|
-
document.addEventListener("keydown", onKey);
|
|
1085
|
-
return () => {
|
|
1086
|
-
document.removeEventListener("pointerdown", onDown);
|
|
1087
|
-
document.removeEventListener("keydown", onKey);
|
|
1088
|
-
};
|
|
1089
|
-
}, [open]);
|
|
1090
|
-
const choose = (type) => {
|
|
1091
|
-
ctx.chart.setChartType(type);
|
|
1092
|
-
ctx.store.set({ chartType: type });
|
|
1093
|
-
setOpen(false);
|
|
1094
|
-
};
|
|
1095
|
-
return /* @__PURE__ */ a3("div", { class: "fnc-menu-wrap fnc-chart-type", ref, children: [
|
|
1096
|
-
/* @__PURE__ */ a3(
|
|
1097
|
-
"button",
|
|
1098
|
-
{
|
|
1099
|
-
class: "fnc-btn fnc-btn-wide",
|
|
1100
|
-
"data-tip": t3.chartType,
|
|
1101
|
-
"aria-label": t3.chartType,
|
|
1102
|
-
"aria-haspopup": "menu",
|
|
1103
|
-
"aria-expanded": open,
|
|
1104
|
-
onClick: () => setOpen(!open),
|
|
1105
|
-
children: [
|
|
1106
|
-
/* @__PURE__ */ a3(current.icon, {}),
|
|
1107
|
-
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
1108
|
-
]
|
|
1109
|
-
}
|
|
1110
|
-
),
|
|
1111
|
-
open && /* @__PURE__ */ a3("div", { class: "fnc-menu", role: "menu", ref: menuRef, children: TYPES.map(({ type, label, icon: Icon2 }) => /* @__PURE__ */ a3(
|
|
1112
|
-
"button",
|
|
1113
|
-
{
|
|
1114
|
-
class: "fnc-menu-item",
|
|
1115
|
-
role: "menuitemradio",
|
|
1116
|
-
"aria-checked": type === s3.chartType,
|
|
1117
|
-
onClick: () => choose(type),
|
|
1118
|
-
children: [
|
|
1119
|
-
/* @__PURE__ */ a3(Icon2, {}),
|
|
1120
|
-
/* @__PURE__ */ a3("span", { children: t3[label] })
|
|
1121
|
-
]
|
|
1122
|
-
}
|
|
1123
|
-
)) })
|
|
1124
|
-
] });
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
1043
|
// src/components/indicator-dialogs.tsx
|
|
1128
1044
|
import {
|
|
1129
1045
|
maLines,
|
|
@@ -1484,6 +1400,32 @@ function Dialogs({ ctx }) {
|
|
|
1484
1400
|
return null;
|
|
1485
1401
|
}
|
|
1486
1402
|
|
|
1403
|
+
// src/components/keep-in-view.ts
|
|
1404
|
+
var MARGIN = 8;
|
|
1405
|
+
function useKeepInView(open) {
|
|
1406
|
+
const ref = T2(null);
|
|
1407
|
+
F2(() => {
|
|
1408
|
+
const el = ref.current;
|
|
1409
|
+
if (!open || !el) return;
|
|
1410
|
+
el.style.translate = "";
|
|
1411
|
+
const fit = () => {
|
|
1412
|
+
el.style.translate = "";
|
|
1413
|
+
const r3 = el.getBoundingClientRect();
|
|
1414
|
+
const root = el.closest(".fnc-root")?.getBoundingClientRect();
|
|
1415
|
+
const minX = Math.max(0, root?.left ?? 0) + MARGIN;
|
|
1416
|
+
const maxX = Math.min(document.documentElement.clientWidth, root?.right ?? Infinity) - MARGIN;
|
|
1417
|
+
let dx = 0;
|
|
1418
|
+
if (r3.right > maxX) dx = maxX - r3.right;
|
|
1419
|
+
if (r3.left + dx < minX) dx = minX - r3.left;
|
|
1420
|
+
if (dx) el.style.translate = `${Math.round(dx)}px 0`;
|
|
1421
|
+
};
|
|
1422
|
+
fit();
|
|
1423
|
+
window.addEventListener("resize", fit);
|
|
1424
|
+
return () => window.removeEventListener("resize", fit);
|
|
1425
|
+
}, [open]);
|
|
1426
|
+
return ref;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1487
1429
|
// src/components/interval-picker.tsx
|
|
1488
1430
|
var GROUP_LABEL = {
|
|
1489
1431
|
minutes: "intervalMinutes",
|
|
@@ -1577,181 +1519,6 @@ function IntervalPicker({ ctx }) {
|
|
|
1577
1519
|
] });
|
|
1578
1520
|
}
|
|
1579
1521
|
|
|
1580
|
-
// src/layouts.ts
|
|
1581
|
-
var row = (...children) => ({ dir: "row", children });
|
|
1582
|
-
var col = (...children) => ({ dir: "col", children });
|
|
1583
|
-
var LAYOUTS = {
|
|
1584
|
-
"1": 0,
|
|
1585
|
-
"2-cols": row(0, 1),
|
|
1586
|
-
"2-rows": col(0, 1),
|
|
1587
|
-
"3-cols": row(0, 1, 2),
|
|
1588
|
-
"3-rows": col(0, 1, 2),
|
|
1589
|
-
"3-left": row(0, col(1, 2)),
|
|
1590
|
-
"3-top": col(0, row(1, 2)),
|
|
1591
|
-
"4-grid": col(row(0, 1), row(2, 3)),
|
|
1592
|
-
"4-cols": row(0, 1, 2, 3),
|
|
1593
|
-
"4-left": row(0, col(1, 2, 3)),
|
|
1594
|
-
"6-grid": col(row(0, 1, 2), row(3, 4, 5)),
|
|
1595
|
-
"8-grid": col(row(0, 1, 2, 3), row(4, 5, 6, 7))
|
|
1596
|
-
};
|
|
1597
|
-
var LAYOUT_GROUPS = [
|
|
1598
|
-
["1"],
|
|
1599
|
-
["2-cols", "2-rows"],
|
|
1600
|
-
["3-cols", "3-rows", "3-left", "3-top"],
|
|
1601
|
-
["4-grid", "4-cols", "4-left"],
|
|
1602
|
-
["6-grid", "8-grid"]
|
|
1603
|
-
];
|
|
1604
|
-
var MAX_PANES = 8;
|
|
1605
|
-
function isLayoutId(value) {
|
|
1606
|
-
return typeof value === "string" && value in LAYOUTS;
|
|
1607
|
-
}
|
|
1608
|
-
function paneCount(node) {
|
|
1609
|
-
if (typeof node === "number") return 1;
|
|
1610
|
-
let n2 = 0;
|
|
1611
|
-
for (const child of node.children) n2 += paneCount(child);
|
|
1612
|
-
return n2;
|
|
1613
|
-
}
|
|
1614
|
-
function sizesFor(sizes, key, count) {
|
|
1615
|
-
const s3 = sizes[key];
|
|
1616
|
-
return s3 && s3.length === count && s3.every((v3) => Number.isFinite(v3) && v3 > 0) ? s3 : Array(count).fill(1);
|
|
1617
|
-
}
|
|
1618
|
-
function resizePair(weights, i3, deltaFraction, min = 0.12) {
|
|
1619
|
-
const total = weights.reduce((a5, b2) => a5 + b2, 0);
|
|
1620
|
-
const a4 = weights[i3];
|
|
1621
|
-
const b = weights[i3 + 1];
|
|
1622
|
-
const pair = a4 + b;
|
|
1623
|
-
const delta = deltaFraction * total;
|
|
1624
|
-
const nextA = Math.min(pair * (1 - min), Math.max(pair * min, a4 + delta));
|
|
1625
|
-
const next = [...weights];
|
|
1626
|
-
next[i3] = nextA;
|
|
1627
|
-
next[i3 + 1] = pair - nextA;
|
|
1628
|
-
return next;
|
|
1629
|
-
}
|
|
1630
|
-
function layoutRects(node, x2 = 0, y3 = 0, w3 = 20, h3 = 16, gap = 1.6) {
|
|
1631
|
-
if (typeof node === "number") return [{ x: x2, y: y3, w: w3, h: h3 }];
|
|
1632
|
-
const n2 = node.children.length;
|
|
1633
|
-
const out = [];
|
|
1634
|
-
node.children.forEach((child, i3) => {
|
|
1635
|
-
if (node.dir === "row") {
|
|
1636
|
-
const cw = (w3 - gap * (n2 - 1)) / n2;
|
|
1637
|
-
out.push(...layoutRects(child, x2 + i3 * (cw + gap), y3, cw, h3, gap));
|
|
1638
|
-
} else {
|
|
1639
|
-
const ch = (h3 - gap * (n2 - 1)) / n2;
|
|
1640
|
-
out.push(...layoutRects(child, x2, y3 + i3 * (ch + gap), w3, ch, gap));
|
|
1641
|
-
}
|
|
1642
|
-
});
|
|
1643
|
-
return out;
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
// src/components/layout-menu.tsx
|
|
1647
|
-
var LAYOUT_PANES = (id) => paneCount(LAYOUTS[id]);
|
|
1648
|
-
function LayoutGlyph({ id }) {
|
|
1649
|
-
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" })) });
|
|
1650
|
-
}
|
|
1651
|
-
function usePopover() {
|
|
1652
|
-
const [open, setOpen] = d2(false);
|
|
1653
|
-
const ref = T2(null);
|
|
1654
|
-
A2(() => {
|
|
1655
|
-
if (!open) return;
|
|
1656
|
-
const onDown = (e3) => !ref.current?.contains(e3.target) && setOpen(false);
|
|
1657
|
-
const onKey = (e3) => e3.key === "Escape" && setOpen(false);
|
|
1658
|
-
document.addEventListener("pointerdown", onDown);
|
|
1659
|
-
document.addEventListener("keydown", onKey);
|
|
1660
|
-
return () => {
|
|
1661
|
-
document.removeEventListener("pointerdown", onDown);
|
|
1662
|
-
document.removeEventListener("keydown", onKey);
|
|
1663
|
-
};
|
|
1664
|
-
}, [open]);
|
|
1665
|
-
return { open, setOpen, ref };
|
|
1666
|
-
}
|
|
1667
|
-
var SYNC_KEYS = [
|
|
1668
|
-
{ key: "crosshair", label: "syncCrosshair" },
|
|
1669
|
-
{ key: "time", label: "syncTime" },
|
|
1670
|
-
{ key: "symbol", label: "syncSymbol" },
|
|
1671
|
-
{ key: "interval", label: "syncInterval" }
|
|
1672
|
-
];
|
|
1673
|
-
function LayoutMenu({ ctx, multi }) {
|
|
1674
|
-
const s3 = useStore(ctx.store);
|
|
1675
|
-
const m3 = useStore(multi.store);
|
|
1676
|
-
const t3 = STRINGS[s3.locale];
|
|
1677
|
-
const layout = usePopover();
|
|
1678
|
-
const sync = usePopover();
|
|
1679
|
-
const layoutMenuRef = useKeepInView(layout.open);
|
|
1680
|
-
const syncMenuRef = useKeepInView(sync.open);
|
|
1681
|
-
const anySync = Object.values(m3.sync).some(Boolean);
|
|
1682
|
-
return /* @__PURE__ */ a3($, { children: [
|
|
1683
|
-
/* @__PURE__ */ a3("div", { class: "fnc-menu-wrap", ref: layout.ref, children: [
|
|
1684
|
-
/* @__PURE__ */ a3(
|
|
1685
|
-
"button",
|
|
1686
|
-
{
|
|
1687
|
-
class: "fnc-btn fnc-btn-wide fnc-btn-layout",
|
|
1688
|
-
"data-tip": t3.layout,
|
|
1689
|
-
"aria-label": t3.layout,
|
|
1690
|
-
"aria-haspopup": "menu",
|
|
1691
|
-
"aria-expanded": layout.open,
|
|
1692
|
-
onClick: () => layout.setOpen(!layout.open),
|
|
1693
|
-
children: [
|
|
1694
|
-
/* @__PURE__ */ a3(LayoutGlyph, { id: m3.layout }),
|
|
1695
|
-
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
1696
|
-
]
|
|
1697
|
-
}
|
|
1698
|
-
),
|
|
1699
|
-
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: [
|
|
1700
|
-
/* @__PURE__ */ a3("span", { class: "fnc-layout-count", children: group[0].split("-")[0] }),
|
|
1701
|
-
group.map((id) => /* @__PURE__ */ a3(
|
|
1702
|
-
"button",
|
|
1703
|
-
{
|
|
1704
|
-
class: "fnc-layout-opt",
|
|
1705
|
-
role: "menuitemradio",
|
|
1706
|
-
"aria-checked": id === m3.layout,
|
|
1707
|
-
"aria-label": `${t3.layout} ${id}`,
|
|
1708
|
-
"data-layout": id,
|
|
1709
|
-
onClick: () => {
|
|
1710
|
-
multi.setLayout(id);
|
|
1711
|
-
layout.setOpen(false);
|
|
1712
|
-
},
|
|
1713
|
-
children: /* @__PURE__ */ a3(LayoutGlyph, { id })
|
|
1714
|
-
}
|
|
1715
|
-
))
|
|
1716
|
-
] })) })
|
|
1717
|
-
] }),
|
|
1718
|
-
LAYOUT_PANES(m3.layout) > 1 && /* @__PURE__ */ a3("div", { class: "fnc-menu-wrap", ref: sync.ref, children: [
|
|
1719
|
-
/* @__PURE__ */ a3(
|
|
1720
|
-
"button",
|
|
1721
|
-
{
|
|
1722
|
-
class: "fnc-btn fnc-btn-sync",
|
|
1723
|
-
"data-tip": t3.sync,
|
|
1724
|
-
"aria-label": t3.sync,
|
|
1725
|
-
"aria-haspopup": "menu",
|
|
1726
|
-
"aria-expanded": sync.open,
|
|
1727
|
-
"aria-pressed": anySync,
|
|
1728
|
-
onClick: () => sync.setOpen(!sync.open),
|
|
1729
|
-
children: /* @__PURE__ */ a3(LinkIcon, {})
|
|
1730
|
-
}
|
|
1731
|
-
),
|
|
1732
|
-
sync.open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-sync-menu", role: "menu", "aria-label": t3.sync, ref: syncMenuRef, children: [
|
|
1733
|
-
/* @__PURE__ */ a3("div", { class: "fnc-menu-title", children: [
|
|
1734
|
-
t3.sync,
|
|
1735
|
-
/* @__PURE__ */ a3("small", { children: t3.syncHint })
|
|
1736
|
-
] }),
|
|
1737
|
-
SYNC_KEYS.map(({ key, label }) => /* @__PURE__ */ a3(
|
|
1738
|
-
"button",
|
|
1739
|
-
{
|
|
1740
|
-
class: "fnc-menu-item fnc-sync-item",
|
|
1741
|
-
role: "menuitemcheckbox",
|
|
1742
|
-
"aria-checked": m3.sync[key],
|
|
1743
|
-
onClick: () => multi.setSync({ [key]: !m3.sync[key] }),
|
|
1744
|
-
children: [
|
|
1745
|
-
/* @__PURE__ */ a3("span", { children: t3[label] }),
|
|
1746
|
-
/* @__PURE__ */ a3("span", { class: "fnc-switch", "data-on": m3.sync[key] ? "true" : "false", "aria-hidden": "true" })
|
|
1747
|
-
]
|
|
1748
|
-
}
|
|
1749
|
-
))
|
|
1750
|
-
] })
|
|
1751
|
-
] })
|
|
1752
|
-
] });
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
1522
|
// src/components/slot.tsx
|
|
1756
1523
|
function Slot({ el, fixed = false }) {
|
|
1757
1524
|
const ref = T2(null);
|
|
@@ -2036,6 +1803,230 @@ function SymbolSearch({ ctx }) {
|
|
|
2036
1803
|
] }) });
|
|
2037
1804
|
}
|
|
2038
1805
|
|
|
1806
|
+
// src/layouts.ts
|
|
1807
|
+
var row = (...children) => ({ dir: "row", children });
|
|
1808
|
+
var col = (...children) => ({ dir: "col", children });
|
|
1809
|
+
var LAYOUTS = {
|
|
1810
|
+
"1": 0,
|
|
1811
|
+
"2-cols": row(0, 1),
|
|
1812
|
+
"2-rows": col(0, 1),
|
|
1813
|
+
"3-cols": row(0, 1, 2),
|
|
1814
|
+
"3-rows": col(0, 1, 2),
|
|
1815
|
+
"3-left": row(0, col(1, 2)),
|
|
1816
|
+
"3-top": col(0, row(1, 2)),
|
|
1817
|
+
"4-grid": col(row(0, 1), row(2, 3)),
|
|
1818
|
+
"4-cols": row(0, 1, 2, 3),
|
|
1819
|
+
"4-left": row(0, col(1, 2, 3)),
|
|
1820
|
+
"6-grid": col(row(0, 1, 2), row(3, 4, 5)),
|
|
1821
|
+
"8-grid": col(row(0, 1, 2, 3), row(4, 5, 6, 7))
|
|
1822
|
+
};
|
|
1823
|
+
var LAYOUT_GROUPS = [
|
|
1824
|
+
["1"],
|
|
1825
|
+
["2-cols", "2-rows"],
|
|
1826
|
+
["3-cols", "3-rows", "3-left", "3-top"],
|
|
1827
|
+
["4-grid", "4-cols", "4-left"],
|
|
1828
|
+
["6-grid", "8-grid"]
|
|
1829
|
+
];
|
|
1830
|
+
var MAX_PANES = 8;
|
|
1831
|
+
function isLayoutId(value) {
|
|
1832
|
+
return typeof value === "string" && value in LAYOUTS;
|
|
1833
|
+
}
|
|
1834
|
+
function paneCount(node) {
|
|
1835
|
+
if (typeof node === "number") return 1;
|
|
1836
|
+
let n2 = 0;
|
|
1837
|
+
for (const child of node.children) n2 += paneCount(child);
|
|
1838
|
+
return n2;
|
|
1839
|
+
}
|
|
1840
|
+
function sizesFor(sizes, key, count) {
|
|
1841
|
+
const s3 = sizes[key];
|
|
1842
|
+
return s3 && s3.length === count && s3.every((v3) => Number.isFinite(v3) && v3 > 0) ? s3 : Array(count).fill(1);
|
|
1843
|
+
}
|
|
1844
|
+
function resizePair(weights, i3, deltaFraction, min = 0.12) {
|
|
1845
|
+
const total = weights.reduce((a5, b2) => a5 + b2, 0);
|
|
1846
|
+
const a4 = weights[i3];
|
|
1847
|
+
const b = weights[i3 + 1];
|
|
1848
|
+
const pair = a4 + b;
|
|
1849
|
+
const delta = deltaFraction * total;
|
|
1850
|
+
const nextA = Math.min(pair * (1 - min), Math.max(pair * min, a4 + delta));
|
|
1851
|
+
const next = [...weights];
|
|
1852
|
+
next[i3] = nextA;
|
|
1853
|
+
next[i3 + 1] = pair - nextA;
|
|
1854
|
+
return next;
|
|
1855
|
+
}
|
|
1856
|
+
function layoutRects(node, x2 = 0, y3 = 0, w3 = 20, h3 = 16, gap = 1.6) {
|
|
1857
|
+
if (typeof node === "number") return [{ x: x2, y: y3, w: w3, h: h3 }];
|
|
1858
|
+
const n2 = node.children.length;
|
|
1859
|
+
const out = [];
|
|
1860
|
+
node.children.forEach((child, i3) => {
|
|
1861
|
+
if (node.dir === "row") {
|
|
1862
|
+
const cw = (w3 - gap * (n2 - 1)) / n2;
|
|
1863
|
+
out.push(...layoutRects(child, x2 + i3 * (cw + gap), y3, cw, h3, gap));
|
|
1864
|
+
} else {
|
|
1865
|
+
const ch = (h3 - gap * (n2 - 1)) / n2;
|
|
1866
|
+
out.push(...layoutRects(child, x2, y3 + i3 * (ch + gap), w3, ch, gap));
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1869
|
+
return out;
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
// src/components/layout-menu.tsx
|
|
1873
|
+
function LayoutGlyph({ id }) {
|
|
1874
|
+
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" })) });
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
// src/components/tools-menu.tsx
|
|
1878
|
+
var TYPES = [
|
|
1879
|
+
{ type: "candles", label: "candles", icon: CandlesIcon },
|
|
1880
|
+
{ type: "line", label: "line", icon: LineChartIcon },
|
|
1881
|
+
{ type: "area", label: "area", icon: AreaChartIcon }
|
|
1882
|
+
];
|
|
1883
|
+
var SCALES2 = [
|
|
1884
|
+
{ mode: "normal", label: "scaleNormal" },
|
|
1885
|
+
{ mode: "log", label: "scaleLog" },
|
|
1886
|
+
{ mode: "percent", label: "scalePercent" }
|
|
1887
|
+
];
|
|
1888
|
+
var SYNC_KEYS = [
|
|
1889
|
+
{ key: "crosshair", label: "syncCrosshair" },
|
|
1890
|
+
{ key: "time", label: "syncTime" },
|
|
1891
|
+
{ key: "symbol", label: "syncSymbol" },
|
|
1892
|
+
{ key: "interval", label: "syncInterval" }
|
|
1893
|
+
];
|
|
1894
|
+
function LayoutSection({ ctx, multi, close }) {
|
|
1895
|
+
const s3 = useStore(ctx.store);
|
|
1896
|
+
const m3 = useStore(multi.store);
|
|
1897
|
+
const t3 = STRINGS[s3.locale];
|
|
1898
|
+
return /* @__PURE__ */ a3($, { children: [
|
|
1899
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-section", children: t3.layout }),
|
|
1900
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-layouts", children: LAYOUT_GROUPS.map((group) => /* @__PURE__ */ a3("div", { class: "fnc-layout-row", children: [
|
|
1901
|
+
/* @__PURE__ */ a3("span", { class: "fnc-layout-count", children: group[0].split("-")[0] }),
|
|
1902
|
+
group.map((id) => /* @__PURE__ */ a3(
|
|
1903
|
+
"button",
|
|
1904
|
+
{
|
|
1905
|
+
class: "fnc-layout-opt",
|
|
1906
|
+
role: "menuitemradio",
|
|
1907
|
+
"aria-checked": id === m3.layout,
|
|
1908
|
+
"aria-label": `${t3.layout} ${id}`,
|
|
1909
|
+
"data-layout": id,
|
|
1910
|
+
onClick: () => {
|
|
1911
|
+
multi.setLayout(id);
|
|
1912
|
+
close();
|
|
1913
|
+
},
|
|
1914
|
+
children: /* @__PURE__ */ a3(LayoutGlyph, { id })
|
|
1915
|
+
}
|
|
1916
|
+
))
|
|
1917
|
+
] })) }),
|
|
1918
|
+
paneCount(LAYOUTS[m3.layout]) > 1 && /* @__PURE__ */ a3("div", { class: "fnc-tools-section", children: t3.sync }),
|
|
1919
|
+
paneCount(LAYOUTS[m3.layout]) > 1 && SYNC_KEYS.map(({ key, label }) => /* @__PURE__ */ a3(
|
|
1920
|
+
"button",
|
|
1921
|
+
{
|
|
1922
|
+
class: "fnc-menu-item fnc-sync-item",
|
|
1923
|
+
role: "menuitemcheckbox",
|
|
1924
|
+
"aria-checked": m3.sync[key],
|
|
1925
|
+
onClick: () => multi.setSync({ [key]: !m3.sync[key] }),
|
|
1926
|
+
children: [
|
|
1927
|
+
/* @__PURE__ */ a3("span", { children: t3[label] }),
|
|
1928
|
+
/* @__PURE__ */ a3("span", { class: "fnc-switch", "data-on": m3.sync[key] ? "true" : "false", "aria-hidden": "true" })
|
|
1929
|
+
]
|
|
1930
|
+
}
|
|
1931
|
+
))
|
|
1932
|
+
] });
|
|
1933
|
+
}
|
|
1934
|
+
function ToolsMenu({ ctx }) {
|
|
1935
|
+
const s3 = useStore(ctx.store);
|
|
1936
|
+
const t3 = STRINGS[s3.locale];
|
|
1937
|
+
const [open, setOpen] = d2(false);
|
|
1938
|
+
const [scale, setScale] = d2(ctx.chart.settings.priceScale);
|
|
1939
|
+
const ref = T2(null);
|
|
1940
|
+
const menuRef = useKeepInView(open);
|
|
1941
|
+
const canSearch = typeof ctx.datafeed.searchSymbols === "function";
|
|
1942
|
+
const close = () => setOpen(false);
|
|
1943
|
+
A2(() => ctx.chart.on("settingsChange", (settings) => setScale(settings.priceScale)), [ctx.chart]);
|
|
1944
|
+
A2(() => {
|
|
1945
|
+
if (!open) return;
|
|
1946
|
+
const onDown = (e3) => !ref.current?.contains(e3.target) && setOpen(false);
|
|
1947
|
+
const onKey = (e3) => e3.key === "Escape" && setOpen(false);
|
|
1948
|
+
document.addEventListener("pointerdown", onDown);
|
|
1949
|
+
document.addEventListener("keydown", onKey);
|
|
1950
|
+
return () => {
|
|
1951
|
+
document.removeEventListener("pointerdown", onDown);
|
|
1952
|
+
document.removeEventListener("keydown", onKey);
|
|
1953
|
+
};
|
|
1954
|
+
}, [open]);
|
|
1955
|
+
const item = (cls, label, icon, onClick, opts = {}) => /* @__PURE__ */ a3(
|
|
1956
|
+
"button",
|
|
1957
|
+
{
|
|
1958
|
+
class: `fnc-menu-item fnc-tools-item ${cls}`,
|
|
1959
|
+
role: "menuitem",
|
|
1960
|
+
disabled: opts.disabled,
|
|
1961
|
+
"aria-pressed": opts.pressed,
|
|
1962
|
+
onClick: () => {
|
|
1963
|
+
close();
|
|
1964
|
+
onClick();
|
|
1965
|
+
},
|
|
1966
|
+
children: [
|
|
1967
|
+
icon,
|
|
1968
|
+
/* @__PURE__ */ a3("span", { children: label })
|
|
1969
|
+
]
|
|
1970
|
+
}
|
|
1971
|
+
);
|
|
1972
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-menu-wrap fnc-tools-wrap", ref, children: [
|
|
1973
|
+
/* @__PURE__ */ a3(
|
|
1974
|
+
"button",
|
|
1975
|
+
{
|
|
1976
|
+
class: "fnc-btn fnc-btn-wide fnc-btn-label fnc-btn-tools",
|
|
1977
|
+
"data-tip": t3.tools,
|
|
1978
|
+
"aria-label": t3.tools,
|
|
1979
|
+
"aria-haspopup": "menu",
|
|
1980
|
+
"aria-expanded": open,
|
|
1981
|
+
"aria-pressed": s3.replay.active || s3.replay.selecting || s3.compares.length > 0,
|
|
1982
|
+
onClick: () => setOpen(!open),
|
|
1983
|
+
children: [
|
|
1984
|
+
/* @__PURE__ */ a3(ToolsIcon, {}),
|
|
1985
|
+
/* @__PURE__ */ a3("span", { children: t3.tools }),
|
|
1986
|
+
/* @__PURE__ */ a3(ChevronDownIcon, {})
|
|
1987
|
+
]
|
|
1988
|
+
}
|
|
1989
|
+
),
|
|
1990
|
+
open && /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-tools-menu", role: "menu", "aria-label": t3.tools, ref: menuRef, children: [
|
|
1991
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-section", children: t3.chartType }),
|
|
1992
|
+
/* @__PURE__ */ a3("div", { class: "fnc-seg fnc-tools-seg", role: "radiogroup", "aria-label": t3.chartType, children: TYPES.map(({ type, label, icon: Icon2 }) => /* @__PURE__ */ a3(
|
|
1993
|
+
"button",
|
|
1994
|
+
{
|
|
1995
|
+
type: "button",
|
|
1996
|
+
role: "radio",
|
|
1997
|
+
"aria-checked": s3.chartType === type,
|
|
1998
|
+
"data-type": type,
|
|
1999
|
+
onClick: () => {
|
|
2000
|
+
ctx.chart.setChartType(type);
|
|
2001
|
+
ctx.store.set({ chartType: type });
|
|
2002
|
+
},
|
|
2003
|
+
children: [
|
|
2004
|
+
/* @__PURE__ */ a3(Icon2, {}),
|
|
2005
|
+
/* @__PURE__ */ a3("span", { children: t3[label] })
|
|
2006
|
+
]
|
|
2007
|
+
}
|
|
2008
|
+
)) }),
|
|
2009
|
+
ctx.multi && /* @__PURE__ */ a3(LayoutSection, { ctx, multi: ctx.multi, close }),
|
|
2010
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-sep" }),
|
|
2011
|
+
canSearch && item("fnc-btn-compare", t3.compareSymbol, /* @__PURE__ */ a3(CompareIcon, {}), () => ctx.setSearchOpen(true, "compare"), {
|
|
2012
|
+
disabled: s3.compares.length >= 5
|
|
2013
|
+
}),
|
|
2014
|
+
item(
|
|
2015
|
+
"fnc-btn-replay",
|
|
2016
|
+
s3.replay.active ? t3.replayExit : t3.replay,
|
|
2017
|
+
/* @__PURE__ */ a3(ReplayIcon, {}),
|
|
2018
|
+
() => s3.replay.active ? ctx.chart.stopReplay() : ctx.chart.setReplaySelecting(true),
|
|
2019
|
+
{ pressed: s3.replay.active || s3.replay.selecting }
|
|
2020
|
+
),
|
|
2021
|
+
item("fnc-btn-screenshot", t3.screenshot, /* @__PURE__ */ a3(CameraIcon, {}), ctx.screenshot),
|
|
2022
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-section", children: t3.settingsScale }),
|
|
2023
|
+
/* @__PURE__ */ a3("div", { class: "fnc-seg fnc-tools-seg", role: "radiogroup", "aria-label": t3.settingsScale, children: SCALES2.map(({ mode, label }) => /* @__PURE__ */ a3("button", { type: "button", role: "radio", "aria-checked": scale === mode, onClick: () => ctx.chart.setSettings({ priceScale: mode }), children: /* @__PURE__ */ a3("span", { children: t3[label] }) })) }),
|
|
2024
|
+
/* @__PURE__ */ a3("div", { class: "fnc-tools-sep" }),
|
|
2025
|
+
item("fnc-btn-settings", t3.chartSettingsMore, /* @__PURE__ */ a3(SettingsIcon, {}), () => ctx.store.set({ dialog: { kind: "chartSettings" } }))
|
|
2026
|
+
] })
|
|
2027
|
+
] });
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2039
2030
|
// src/components/toolbar.tsx
|
|
2040
2031
|
function Toolbar({ ctx }) {
|
|
2041
2032
|
const s3 = useStore(ctx.store);
|
|
@@ -2062,7 +2053,6 @@ function Toolbar({ ctx }) {
|
|
|
2062
2053
|
/* @__PURE__ */ a3(Slot, { el: ctx.slots.toolbar }),
|
|
2063
2054
|
/* @__PURE__ */ a3("div", { class: "fnc-spacer" }),
|
|
2064
2055
|
/* @__PURE__ */ a3("div", { class: "fnc-tools", children: [
|
|
2065
|
-
/* @__PURE__ */ a3(ChartTypeMenu, { ctx }),
|
|
2066
2056
|
/* @__PURE__ */ a3(
|
|
2067
2057
|
"button",
|
|
2068
2058
|
{
|
|
@@ -2077,30 +2067,7 @@ function Toolbar({ ctx }) {
|
|
|
2077
2067
|
]
|
|
2078
2068
|
}
|
|
2079
2069
|
),
|
|
2080
|
-
|
|
2081
|
-
"button",
|
|
2082
|
-
{
|
|
2083
|
-
class: "fnc-btn fnc-btn-compare",
|
|
2084
|
-
"data-tip": t3.compareSymbol,
|
|
2085
|
-
"aria-label": t3.compareSymbol,
|
|
2086
|
-
"aria-haspopup": "dialog",
|
|
2087
|
-
disabled: s3.compares.length >= 5,
|
|
2088
|
-
onClick: () => ctx.setSearchOpen(true, "compare"),
|
|
2089
|
-
children: /* @__PURE__ */ a3(CompareIcon, {})
|
|
2090
|
-
}
|
|
2091
|
-
),
|
|
2092
|
-
/* @__PURE__ */ a3(
|
|
2093
|
-
"button",
|
|
2094
|
-
{
|
|
2095
|
-
class: "fnc-btn fnc-btn-replay",
|
|
2096
|
-
"data-tip": s3.replay.selecting ? t3.replayPick : t3.replay,
|
|
2097
|
-
"aria-label": t3.replay,
|
|
2098
|
-
"aria-pressed": s3.replay.selecting || s3.replay.active,
|
|
2099
|
-
onClick: () => s3.replay.active ? ctx.chart.stopReplay() : ctx.chart.setReplaySelecting(!s3.replay.selecting),
|
|
2100
|
-
children: /* @__PURE__ */ a3(ReplayIcon, {})
|
|
2101
|
-
}
|
|
2102
|
-
),
|
|
2103
|
-
ctx.multi && /* @__PURE__ */ a3(LayoutMenu, { ctx, multi: ctx.multi })
|
|
2070
|
+
/* @__PURE__ */ a3(ToolsMenu, { ctx })
|
|
2104
2071
|
] }),
|
|
2105
2072
|
/* @__PURE__ */ a3("div", { class: "fnc-sep" }),
|
|
2106
2073
|
ctx.drawingToolbar && /* @__PURE__ */ a3(
|
|
@@ -2115,18 +2082,6 @@ function Toolbar({ ctx }) {
|
|
|
2115
2082
|
}
|
|
2116
2083
|
),
|
|
2117
2084
|
/* @__PURE__ */ a3(Slot, { el: ctx.slots.toolbarEnd, fixed: true }),
|
|
2118
|
-
/* @__PURE__ */ a3(
|
|
2119
|
-
"button",
|
|
2120
|
-
{
|
|
2121
|
-
class: "fnc-btn fnc-btn-settings",
|
|
2122
|
-
"data-tip": t3.chartSettings,
|
|
2123
|
-
"aria-label": t3.chartSettings,
|
|
2124
|
-
"aria-haspopup": "dialog",
|
|
2125
|
-
onClick: () => ctx.store.set({ dialog: { kind: "chartSettings" } }),
|
|
2126
|
-
children: /* @__PURE__ */ a3(SettingsIcon, {})
|
|
2127
|
-
}
|
|
2128
|
-
),
|
|
2129
|
-
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-screenshot", "data-tip": t3.screenshot, "aria-label": t3.screenshot, onClick: ctx.screenshot, children: /* @__PURE__ */ a3(CameraIcon, {}) }),
|
|
2130
2085
|
/* @__PURE__ */ a3(
|
|
2131
2086
|
"button",
|
|
2132
2087
|
{
|
|
@@ -3338,7 +3293,6 @@ var CSS = (
|
|
|
3338
3293
|
@container fnc (max-width: 940px) {
|
|
3339
3294
|
.fnc-intervals { display: none; }
|
|
3340
3295
|
.fnc-interval-current { display: inline; }
|
|
3341
|
-
.fnc-btn-screenshot { display: none; }
|
|
3342
3296
|
}
|
|
3343
3297
|
|
|
3344
3298
|
/* \u2500\u2500 Narrow phones (\u2264 400px): drop the menu chevrons and separators so every button fits \u2500\u2500 */
|
|
@@ -3452,6 +3406,17 @@ var CSS = (
|
|
|
3452
3406
|
.fnc-ctx-menu kbd { font: inherit; font-size: 12px; color: var(--fnc-text-2); }
|
|
3453
3407
|
.fnc-ctx-sep { height: 1px; margin: 4px 6px; background: var(--fnc-border); }
|
|
3454
3408
|
|
|
3409
|
+
/* \u2500\u2500 \uB3C4\uAD6C menu: chart type, split, compare, replay, axis, screenshot, settings \u2500\u2500 */
|
|
3410
|
+
.fnc-tools-menu { width: 300px; padding: 8px; gap: 2px; max-height: 72vh; overflow-y: auto; }
|
|
3411
|
+
.fnc-tools-section { padding: 8px 6px 6px; font-size: 12px; font-weight: 700; color: var(--fnc-text-2); }
|
|
3412
|
+
.fnc-tools-seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; margin: 0 2px 4px; }
|
|
3413
|
+
.fnc-tools-seg button { display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-width: 0; padding: 0 6px; }
|
|
3414
|
+
.fnc-tools-seg svg { width: 16px; height: 16px; flex: none; }
|
|
3415
|
+
.fnc-tools-layouts { display: flex; flex-direction: column; gap: 2px; padding: 0 2px 4px; }
|
|
3416
|
+
.fnc-tools-sep { height: 1px; margin: 6px 4px; background: var(--fnc-border); }
|
|
3417
|
+
.fnc-tools-item svg { flex: none; color: var(--fnc-text-2); }
|
|
3418
|
+
.fnc-tools-item[aria-pressed='true'] { background: var(--fnc-surface); color: var(--fnc-text); }
|
|
3419
|
+
|
|
3455
3420
|
/* \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 */
|
|
3456
3421
|
.fnc-tool-group { position: relative; display: flex; }
|
|
3457
3422
|
.fnc-tool-group[data-open='true'] { z-index: 30; }
|
|
@@ -3524,7 +3489,6 @@ var CSS = (
|
|
|
3524
3489
|
|
|
3525
3490
|
/* \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 */
|
|
3526
3491
|
@media (max-width: 640px) {
|
|
3527
|
-
.fnc-btn-compare, .fnc-btn-replay { display: none; }
|
|
3528
3492
|
.fnc-toolbar { padding: 0 4px; gap: 2px; }
|
|
3529
3493
|
.fnc-toolbar .fnc-btn { width: 32px; height: 32px; }
|
|
3530
3494
|
.fnc-toolbar .fnc-btn-wide, .fnc-toolbar .fnc-btn-label { width: auto; padding: 0 6px; }
|
|
@@ -3533,9 +3497,7 @@ var CSS = (
|
|
|
3533
3497
|
/* Logo only on phones; the name is in the chart legend right below. */
|
|
3534
3498
|
.fnc-toolbar .fnc-symbol:has(.fnc-avatar) :is(.fnc-symbol-name, .fnc-icon) { display: none; }
|
|
3535
3499
|
.fnc-chip { padding: 0 8px; }
|
|
3536
|
-
.fnc-btn-screenshot { display: none; }
|
|
3537
3500
|
.fnc-btn-label span { display: none; }
|
|
3538
|
-
.fnc-btn-sync { display: none; }
|
|
3539
3501
|
.fnc-intervals { display: none; }
|
|
3540
3502
|
.fnc-interval-current { display: inline; }
|
|
3541
3503
|
.fnc-interval-menu { left: auto; right: -40px; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnest/charts-ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Pro trading UI (toolbar, drawing tools, sheets) for Funnest Charts. Framework-agnostic.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chart",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"NOTICE"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@funnest/charts": "0.6.
|
|
45
|
+
"@funnest/charts": "0.6.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"preact": "^11.2.0"
|