@tradecanvas/chart 1.71.0 → 1.72.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LayoutSession-DO4bYkUi.cjs +2 -0
- package/dist/LayoutSession-DO4bYkUi.cjs.map +1 -0
- package/dist/{LayoutSession-BOQCN6yY.js → LayoutSession-qRYG8GTD.js} +539 -552
- package/dist/LayoutSession-qRYG8GTD.js.map +1 -0
- package/dist/WidgetCommandPalette-CeCLHPy1.js +177 -0
- package/dist/WidgetCommandPalette-CeCLHPy1.js.map +1 -0
- package/dist/WidgetCommandPalette-ZZNbWwCZ.cjs +2 -0
- package/dist/WidgetCommandPalette-ZZNbWwCZ.cjs.map +1 -0
- package/dist/WidgetDrawingSettings-BeW8fX7r.js +474 -0
- package/dist/WidgetDrawingSettings-BeW8fX7r.js.map +1 -0
- package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs +2 -0
- package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs.map +1 -0
- package/dist/WidgetGoToDate-BNdngHlg.cjs +2 -0
- package/dist/WidgetGoToDate-BNdngHlg.cjs.map +1 -0
- package/dist/WidgetGoToDate-hcDtezRm.js +191 -0
- package/dist/WidgetGoToDate-hcDtezRm.js.map +1 -0
- package/dist/WidgetHotkeySheet-1lRFSdvt.js +416 -0
- package/dist/WidgetHotkeySheet-1lRFSdvt.js.map +1 -0
- package/dist/WidgetHotkeySheet-y5LWKSG6.cjs +2 -0
- package/dist/WidgetHotkeySheet-y5LWKSG6.cjs.map +1 -0
- package/dist/WidgetIndicatorPicker-CGvZ5kYd.js +245 -0
- package/dist/WidgetIndicatorPicker-CGvZ5kYd.js.map +1 -0
- package/dist/WidgetIndicatorPicker-DuKJFPRC.cjs +2 -0
- package/dist/WidgetIndicatorPicker-DuKJFPRC.cjs.map +1 -0
- package/dist/WidgetIndicatorSettings-C7vpco6e.cjs +2 -0
- package/dist/WidgetIndicatorSettings-C7vpco6e.cjs.map +1 -0
- package/dist/WidgetIndicatorSettings-dDkqzzYo.js +326 -0
- package/dist/WidgetIndicatorSettings-dDkqzzYo.js.map +1 -0
- package/dist/WidgetSettings-D7Pq42zW.cjs +2 -0
- package/dist/WidgetSettings-D7Pq42zW.cjs.map +1 -0
- package/dist/WidgetSettings-eOo93L7Z.js +546 -0
- package/dist/WidgetSettings-eOo93L7Z.js.map +1 -0
- package/dist/WidgetSymbolSearch-C4OR42nZ.cjs +2 -0
- package/dist/WidgetSymbolSearch-C4OR42nZ.cjs.map +1 -0
- package/dist/WidgetSymbolSearch-CvPpjIwa.js +580 -0
- package/dist/WidgetSymbolSearch-CvPpjIwa.js.map +1 -0
- package/dist/focusTrap-Br9Zfje0.js +27 -0
- package/dist/focusTrap-Br9Zfje0.js.map +1 -0
- package/dist/focusTrap-DrhhmG0V.cjs +2 -0
- package/dist/focusTrap-DrhhmG0V.cjs.map +1 -0
- package/dist/i18n-C2nQBZTY.cjs +2 -0
- package/dist/i18n-C2nQBZTY.cjs.map +1 -0
- package/dist/{i18n-DUmd4Z_r.js → i18n-C5v6Tzp1.js} +3 -1
- package/dist/i18n-C5v6Tzp1.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/indicatorInputWords-Bd9Pt6qp.js +25 -0
- package/dist/indicatorInputWords-Bd9Pt6qp.js.map +1 -0
- package/dist/indicatorInputWords-CTA4IcJR.cjs +2 -0
- package/dist/indicatorInputWords-CTA4IcJR.cjs.map +1 -0
- package/dist/indicatorLabel-BNZvaOcl.cjs +2 -0
- package/dist/indicatorLabel-BNZvaOcl.cjs.map +1 -0
- package/dist/indicatorLabel-Sbegyhp2.js +17 -0
- package/dist/indicatorLabel-Sbegyhp2.js.map +1 -0
- package/dist/indicatorSettingsTabs-B0liE3ST.cjs +2 -0
- package/dist/indicatorSettingsTabs-B0liE3ST.cjs.map +1 -0
- package/dist/indicatorSettingsTabs-XcgMdbLp.js +161 -0
- package/dist/indicatorSettingsTabs-XcgMdbLp.js.map +1 -0
- package/dist/monthView-B-CieFDJ.cjs +2 -0
- package/dist/monthView-B-CieFDJ.cjs.map +1 -0
- package/dist/monthView-N8yDaTqZ.js +198 -0
- package/dist/monthView-N8yDaTqZ.js.map +1 -0
- package/dist/platformKeys-B82-j1Fs.cjs +2 -0
- package/dist/platformKeys-B82-j1Fs.cjs.map +1 -0
- package/dist/platformKeys-Dd1qOCjF.js +5 -0
- package/dist/platformKeys-Dd1qOCjF.js.map +1 -0
- package/dist/settingsControls-DIjzCFHI.js +379 -0
- package/dist/settingsControls-DIjzCFHI.js.map +1 -0
- package/dist/settingsControls-Tn8_vJJv.cjs +2 -0
- package/dist/settingsControls-Tn8_vJJv.cjs.map +1 -0
- package/dist/symbolCatalog-CA1fpz3s.js +90 -0
- package/dist/symbolCatalog-CA1fpz3s.js.map +1 -0
- package/dist/symbolCatalog-Dx1YnZgm.cjs +2 -0
- package/dist/symbolCatalog-Dx1YnZgm.cjs.map +1 -0
- package/dist/widget/ChartWidget.d.ts +102 -582
- package/dist/widget/ChartWidget.d.ts.map +1 -1
- package/dist/widget/WidgetAlerts.d.ts +35 -0
- package/dist/widget/WidgetAlerts.d.ts.map +1 -0
- package/dist/widget/WidgetChartSettings.d.ts +194 -0
- package/dist/widget/WidgetChartSettings.d.ts.map +1 -0
- package/dist/widget/WidgetCommands.d.ts +54 -0
- package/dist/widget/WidgetCommands.d.ts.map +1 -0
- package/dist/widget/WidgetCompares.d.ts +140 -0
- package/dist/widget/WidgetCompares.d.ts.map +1 -0
- package/dist/widget/WidgetDockArea.d.ts +89 -0
- package/dist/widget/WidgetDockArea.d.ts.map +1 -0
- package/dist/widget/WidgetDrawingEdit.d.ts +73 -0
- package/dist/widget/WidgetDrawingEdit.d.ts.map +1 -0
- package/dist/widget/WidgetGoToDate.d.ts +1 -14
- package/dist/widget/WidgetGoToDate.d.ts.map +1 -1
- package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -1
- package/dist/widget/WidgetIntervals.d.ts +66 -0
- package/dist/widget/WidgetIntervals.d.ts.map +1 -0
- package/dist/widget/WidgetLayouts.d.ts +85 -0
- package/dist/widget/WidgetLayouts.d.ts.map +1 -0
- package/dist/widget/WidgetLegendView.d.ts +54 -0
- package/dist/widget/WidgetLegendView.d.ts.map +1 -0
- package/dist/widget/WidgetMenus.d.ts +79 -0
- package/dist/widget/WidgetMenus.d.ts.map +1 -0
- package/dist/widget/WidgetReplay.d.ts +199 -0
- package/dist/widget/WidgetReplay.d.ts.map +1 -0
- package/dist/widget/WidgetTrading.d.ts +48 -0
- package/dist/widget/WidgetTrading.d.ts.map +1 -0
- package/dist/widget/WidgetWatchlists.d.ts +77 -0
- package/dist/widget/WidgetWatchlists.d.ts.map +1 -0
- package/dist/widget/drawingSettingsTabs.d.ts +2 -19
- package/dist/widget/drawingSettingsTabs.d.ts.map +1 -1
- package/dist/widget/drawingText.d.ts +24 -0
- package/dist/widget/drawingText.d.ts.map +1 -0
- package/dist/widget/index.cjs +22 -23
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.js +6193 -9868
- package/dist/widget/index.js.map +1 -1
- package/dist/widget/keyTarget.d.ts +4 -0
- package/dist/widget/keyTarget.d.ts.map +1 -1
- package/dist/widget/lazyPart.d.ts +47 -0
- package/dist/widget/lazyPart.d.ts.map +1 -0
- package/dist/widget/locales/ar.d.ts.map +1 -1
- package/dist/widget/locales/cs.d.ts.map +1 -1
- package/dist/widget/locales/da.d.ts.map +1 -1
- package/dist/widget/locales/de.d.ts.map +1 -1
- package/dist/widget/locales/el.d.ts.map +1 -1
- package/dist/widget/locales/en.d.ts +1 -0
- package/dist/widget/locales/en.d.ts.map +1 -1
- package/dist/widget/locales/es.d.ts.map +1 -1
- package/dist/widget/locales/et.d.ts.map +1 -1
- package/dist/widget/locales/fa.d.ts.map +1 -1
- package/dist/widget/locales/fr.d.ts.map +1 -1
- package/dist/widget/locales/he.d.ts.map +1 -1
- package/dist/widget/locales/hu.d.ts.map +1 -1
- package/dist/widget/locales/id.d.ts.map +1 -1
- package/dist/widget/locales/index.cjs +1 -1
- package/dist/widget/locales/index.cjs.map +1 -1
- package/dist/widget/locales/index.js +29 -1
- package/dist/widget/locales/index.js.map +1 -1
- package/dist/widget/locales/it.d.ts.map +1 -1
- package/dist/widget/locales/ja.d.ts.map +1 -1
- package/dist/widget/locales/ko.d.ts.map +1 -1
- package/dist/widget/locales/ms.d.ts.map +1 -1
- package/dist/widget/locales/nb.d.ts.map +1 -1
- package/dist/widget/locales/nl.d.ts.map +1 -1
- package/dist/widget/locales/pl.d.ts.map +1 -1
- package/dist/widget/locales/pt.d.ts.map +1 -1
- package/dist/widget/locales/ro.d.ts.map +1 -1
- package/dist/widget/locales/ru.d.ts.map +1 -1
- package/dist/widget/locales/sk.d.ts.map +1 -1
- package/dist/widget/locales/sv.d.ts.map +1 -1
- package/dist/widget/locales/th.d.ts.map +1 -1
- package/dist/widget/locales/tr.d.ts.map +1 -1
- package/dist/widget/locales/vi.d.ts.map +1 -1
- package/dist/widget/locales/zh.d.ts.map +1 -1
- package/dist/widget/locales/zhHant.d.ts.map +1 -1
- package/dist/widget/pageEnv.d.ts +5 -0
- package/dist/widget/pageEnv.d.ts.map +1 -0
- package/dist/widget/signals.d.ts +41 -0
- package/dist/widget/signals.d.ts.map +1 -0
- package/dist/widget/wallTime.d.ts +15 -0
- package/dist/widget/wallTime.d.ts.map +1 -0
- package/dist/widget/widgetDialogs.d.ts +17 -0
- package/dist/widget/widgetDialogs.d.ts.map +1 -0
- package/dist/widgetFeatures-BM6u0u74.js +186 -0
- package/dist/widgetFeatures-BM6u0u74.js.map +1 -0
- package/dist/widgetFeatures-BZ8OVPN2.cjs +3 -0
- package/dist/widgetFeatures-BZ8OVPN2.cjs.map +1 -0
- package/dist/widgetLocales-BPK5i0Ok.cjs +2 -0
- package/dist/widgetLocales-BPK5i0Ok.cjs.map +1 -0
- package/dist/widgetLocales-DgTR8JSu.js +838 -0
- package/dist/widgetLocales-DgTR8JSu.js.map +1 -0
- package/package.json +3 -3
- package/dist/LayoutSession-BOQCN6yY.js.map +0 -1
- package/dist/LayoutSession-RF8OqOXy.cjs +0 -2
- package/dist/LayoutSession-RF8OqOXy.cjs.map +0 -1
- package/dist/i18n-BsstZ9md.cjs +0 -2
- package/dist/i18n-BsstZ9md.cjs.map +0 -1
- package/dist/i18n-DUmd4Z_r.js.map +0 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { i as e, n as t } from "./focusTrap-Br9Zfje0.js";
|
|
2
|
+
import { t as n } from "./i18n-C5v6Tzp1.js";
|
|
3
|
+
import { n as r } from "./platformKeys-Dd1qOCjF.js";
|
|
4
|
+
//#region src/widget/WidgetCommandPalette.ts
|
|
5
|
+
var i = 5, a = 229, o = [
|
|
6
|
+
"action",
|
|
7
|
+
"drawing",
|
|
8
|
+
"chartType",
|
|
9
|
+
"timeframe",
|
|
10
|
+
"indicator"
|
|
11
|
+
], s = {
|
|
12
|
+
indicator: "palette.group.indicator",
|
|
13
|
+
chartType: "palette.group.chartType",
|
|
14
|
+
drawing: "palette.group.drawing",
|
|
15
|
+
timeframe: "palette.group.timeframe",
|
|
16
|
+
action: "palette.group.action"
|
|
17
|
+
}, c = (e) => `${e.category}:${e.id}`;
|
|
18
|
+
function l(e, t) {
|
|
19
|
+
let n = e.label.toLowerCase(), i = r(n);
|
|
20
|
+
return e.id.toLowerCase() === t || i === t ? 5 : i.startsWith(t) ? 4 : n.split(/[\s/()-]+/).some((e) => e.startsWith(t)) ? 3 : i.includes(t) || e.id.toLowerCase().includes(t) ? 2 : e.shortcut && r(e.shortcut).includes(t) ? 1 : 0;
|
|
21
|
+
}
|
|
22
|
+
var u = 0, d = class {
|
|
23
|
+
backdrop = null;
|
|
24
|
+
input = null;
|
|
25
|
+
list = null;
|
|
26
|
+
emptyEl = null;
|
|
27
|
+
liveEl = null;
|
|
28
|
+
items = [];
|
|
29
|
+
shown = [];
|
|
30
|
+
selectedIndex = 0;
|
|
31
|
+
returnFocus = null;
|
|
32
|
+
uid = ++u;
|
|
33
|
+
constructor(e, t = () => document.body, r = n, i) {
|
|
34
|
+
this.callbacks = e, this.host = t, this.t = r, this.recents = i;
|
|
35
|
+
}
|
|
36
|
+
open(e) {
|
|
37
|
+
this.backdrop || (this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null, this.items = e, this.build(), this.render(), this.input?.focus());
|
|
38
|
+
}
|
|
39
|
+
close() {
|
|
40
|
+
if (!this.backdrop) return;
|
|
41
|
+
this.backdrop.remove(), this.backdrop = this.input = this.list = this.emptyEl = this.liveEl = null, this.callbacks.onClose();
|
|
42
|
+
let e = this.returnFocus;
|
|
43
|
+
this.returnFocus = null, e?.isConnected && e.focus();
|
|
44
|
+
}
|
|
45
|
+
isOpen() {
|
|
46
|
+
return this.backdrop !== null;
|
|
47
|
+
}
|
|
48
|
+
destroy() {
|
|
49
|
+
this.close();
|
|
50
|
+
}
|
|
51
|
+
build() {
|
|
52
|
+
let t = document.createElement("div");
|
|
53
|
+
t.className = "tcw-modal-backdrop";
|
|
54
|
+
let n = !1;
|
|
55
|
+
t.addEventListener("pointerdown", (e) => {
|
|
56
|
+
n = e.target === t;
|
|
57
|
+
}), t.addEventListener("click", (e) => {
|
|
58
|
+
e.target === t && n && this.close(), n = !1;
|
|
59
|
+
});
|
|
60
|
+
let r = document.createElement("div");
|
|
61
|
+
r.className = "tcw-modal tcw-cp", r.setAttribute("role", "dialog"), r.setAttribute("aria-modal", "true"), r.setAttribute("aria-label", this.t("hotkeys.commandPalette")), r.tabIndex = -1, r.addEventListener("keydown", (e) => this.onKeyDown(e, r));
|
|
62
|
+
let i = document.createElement("label");
|
|
63
|
+
i.className = "tcw-ss-search tcw-cp-search", i.innerHTML = e("search", 16);
|
|
64
|
+
let a = document.createElement("input");
|
|
65
|
+
a.type = "search", a.className = "tcw-cp-input", a.placeholder = this.t("palette.placeholder"), a.setAttribute("aria-label", this.t("palette.placeholder")), a.setAttribute("role", "combobox"), a.setAttribute("aria-expanded", "true"), a.setAttribute("aria-autocomplete", "list"), a.setAttribute("aria-controls", `tcw-cp-list-${this.uid}`), a.autocomplete = "off", a.spellcheck = !1, a.addEventListener("input", () => this.render()), i.appendChild(a);
|
|
66
|
+
let o = document.createElement("div");
|
|
67
|
+
o.className = "tcw-cp-results";
|
|
68
|
+
let s = document.createElement("div");
|
|
69
|
+
s.className = "tcw-cp-list", s.id = `tcw-cp-list-${this.uid}`, s.setAttribute("role", "listbox"), s.setAttribute("aria-label", this.t("hotkeys.commandPalette"));
|
|
70
|
+
let c = document.createElement("div");
|
|
71
|
+
c.className = "tcw-cp-empty", o.append(s, c), o.addEventListener("mousedown", (e) => e.preventDefault());
|
|
72
|
+
let l = document.createElement("div");
|
|
73
|
+
l.className = "tcw-cp-live tcw-visually-hidden", l.setAttribute("aria-live", "polite"), r.append(i, o, l), t.appendChild(r), this.host().appendChild(t), this.backdrop = t, this.input = a, this.list = s, this.emptyEl = c, this.liveEl = l;
|
|
74
|
+
}
|
|
75
|
+
groups() {
|
|
76
|
+
let e = r((this.input?.value ?? "").trim()), t = [];
|
|
77
|
+
if (!e) {
|
|
78
|
+
let e = new Map(this.items.map((e) => [c(e), e])), n = (this.recents?.list() ?? []).map((t) => e.get(t)).filter((e) => !!e).slice(0, i);
|
|
79
|
+
n.length > 0 && t.push({
|
|
80
|
+
key: "recent",
|
|
81
|
+
label: this.t("palette.group.recent"),
|
|
82
|
+
items: n
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
for (let n of o) {
|
|
86
|
+
let r = this.items.filter((e) => e.category === n);
|
|
87
|
+
e && (r = r.map((t, n) => ({
|
|
88
|
+
item: t,
|
|
89
|
+
at: n,
|
|
90
|
+
s: l(t, e)
|
|
91
|
+
})).filter((e) => e.s > 0).sort((e, t) => t.s - e.s || e.at - t.at).map((e) => e.item)), r.length > 0 && t.push({
|
|
92
|
+
key: n,
|
|
93
|
+
label: this.t(s[n]),
|
|
94
|
+
items: r
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return e && t.sort((t, n) => l(n.items[0], e) - l(t.items[0], e)), t;
|
|
98
|
+
}
|
|
99
|
+
render() {
|
|
100
|
+
let e = this.list;
|
|
101
|
+
if (!e) return;
|
|
102
|
+
let t = this.groups();
|
|
103
|
+
this.shown = t.flatMap((e) => e.items), this.selectedIndex = 0;
|
|
104
|
+
let n = 0;
|
|
105
|
+
e.replaceChildren(...t.map((e) => {
|
|
106
|
+
let t = document.createElement("div");
|
|
107
|
+
t.setAttribute("role", "group"), t.className = "tcw-cp-group";
|
|
108
|
+
let r = document.createElement("div");
|
|
109
|
+
return r.className = "tcw-cp-heading", r.id = `tcw-cp-${e.key}-${this.uid}`, r.setAttribute("role", "presentation"), r.textContent = e.label, t.setAttribute("aria-labelledby", r.id), t.append(r, ...e.items.map((e) => this.row(e, n++))), t;
|
|
110
|
+
}));
|
|
111
|
+
let r = this.shown.length === 0 ? this.t("palette.empty") : "";
|
|
112
|
+
this.emptyEl && (this.emptyEl.textContent = r), this.emptyEl?.toggleAttribute("hidden", this.shown.length > 0), this.liveEl && (this.liveEl.textContent = r), this.markSelection();
|
|
113
|
+
}
|
|
114
|
+
row(t, n) {
|
|
115
|
+
let r = document.createElement("div");
|
|
116
|
+
r.className = "tcw-cp-row", r.id = `tcw-cp-opt-${this.uid}-${n}`, r.dataset.id = t.id, r.setAttribute("role", "option"), r.classList.toggle("tcw-on", !!t.active);
|
|
117
|
+
let i = document.createElement("span");
|
|
118
|
+
if (i.className = "tcw-cp-label", i.textContent = t.label, r.appendChild(i), t.shortcut) {
|
|
119
|
+
let e = document.createElement("kbd");
|
|
120
|
+
e.className = "tcw-cp-key", e.dir = "ltr", e.textContent = t.shortcut, r.appendChild(e);
|
|
121
|
+
}
|
|
122
|
+
if (t.active) {
|
|
123
|
+
let t = document.createElement("span");
|
|
124
|
+
t.className = "tcw-cp-check", t.innerHTML = e("check", 14), r.appendChild(t);
|
|
125
|
+
}
|
|
126
|
+
return r.addEventListener("click", () => this.run(n)), r.addEventListener("mousemove", () => {
|
|
127
|
+
this.selectedIndex !== n && (this.selectedIndex = n, this.markSelection());
|
|
128
|
+
}), r;
|
|
129
|
+
}
|
|
130
|
+
markSelection() {
|
|
131
|
+
let e = this.list?.querySelectorAll(".tcw-cp-row") ?? [], t = null;
|
|
132
|
+
e.forEach((e, n) => {
|
|
133
|
+
let r = n === this.selectedIndex;
|
|
134
|
+
e.setAttribute("aria-selected", String(r)), e.classList.toggle("tcw-selected", r), r && (t = e);
|
|
135
|
+
});
|
|
136
|
+
let n = t;
|
|
137
|
+
n ? (this.input?.setAttribute("aria-activedescendant", n.id), n.scrollIntoView?.({ block: "nearest" })) : this.input?.removeAttribute("aria-activedescendant");
|
|
138
|
+
}
|
|
139
|
+
run(e) {
|
|
140
|
+
let t = this.shown[e];
|
|
141
|
+
if (t) switch (this.recents?.add(c(t)), this.close(), t.category) {
|
|
142
|
+
case "indicator":
|
|
143
|
+
this.callbacks.onIndicator(t.id);
|
|
144
|
+
break;
|
|
145
|
+
case "chartType":
|
|
146
|
+
this.callbacks.onChartType(t.id);
|
|
147
|
+
break;
|
|
148
|
+
case "drawing":
|
|
149
|
+
this.callbacks.onDrawingTool(t.id);
|
|
150
|
+
break;
|
|
151
|
+
case "timeframe":
|
|
152
|
+
this.callbacks.onTimeframe(t.id);
|
|
153
|
+
break;
|
|
154
|
+
case "action":
|
|
155
|
+
this.callbacks.onAction(t.id);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
onKeyDown(e, n) {
|
|
160
|
+
if (e.stopPropagation(), e.isComposing || e.keyCode === a) return;
|
|
161
|
+
let r = (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k";
|
|
162
|
+
if (e.key === "Escape" || r) {
|
|
163
|
+
e.preventDefault(), this.close();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (t(e, n), e.target !== this.input) return;
|
|
167
|
+
let i = this.shown.length;
|
|
168
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
169
|
+
if (e.preventDefault(), i === 0) return;
|
|
170
|
+
this.selectedIndex = (this.selectedIndex + (e.key === "ArrowDown" ? 1 : -1) + i) % i, this.markSelection();
|
|
171
|
+
} else e.key === "Enter" && (e.preventDefault(), e.repeat || this.run(this.selectedIndex));
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
//#endregion
|
|
175
|
+
export { d as WidgetCommandPalette };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=WidgetCommandPalette-CeCLHPy1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetCommandPalette-CeCLHPy1.js","names":[],"sources":["../src/widget/WidgetCommandPalette.ts"],"sourcesContent":["import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\nimport { EN_TRANSLATOR, type Translator } from './i18n.js';\nimport { createIcon } from './icons.js';\nimport { keepTabInside } from './focusTrap.js';\nimport { searchForm } from './platformKeys.js';\n\nexport interface CommandItem {\n id: string;\n label: string;\n category: CommandCategory;\n /** Its keys, written at the row's end (\"Alt+T\"). */\n shortcut?: string;\n /** On now (an indicator on the chart, the chart type in use): ticked. */\n active?: boolean;\n}\n\nexport type CommandCategory = 'indicator' | 'chartType' | 'drawing' | 'timeframe' | 'action';\n\nexport interface CommandPaletteCallbacks {\n onIndicator: (id: string) => void;\n onChartType: (type: ChartType) => void;\n onDrawingTool: (tool: DrawingToolType) => void;\n onTimeframe: (tf: TimeFrame) => void;\n onAction: (id: string) => void;\n onClose: () => void;\n}\n\n/** The commands used last, by `category:id`, newest first. */\nexport interface CommandRecents {\n list: () => readonly string[];\n add: (key: string) => void;\n}\n\n/** Commands used last, shown at the top before anything is typed. */\nconst RECENT_SHOWN = 5;\n/** The key code a browser gives a key an input method takes. */\nconst IME_KEY_CODE = 229;\n\n/** The widget's own commands first; the indicators, which have a dialog of their own, last. */\nconst CATEGORY_ORDER: readonly CommandCategory[] = ['action', 'drawing', 'chartType', 'timeframe', 'indicator'];\nconst CATEGORY_LABELS = {\n indicator: 'palette.group.indicator',\n chartType: 'palette.group.chartType',\n drawing: 'palette.group.drawing',\n timeframe: 'palette.group.timeframe',\n action: 'palette.group.action',\n} as const satisfies Record<CommandCategory, string>;\n\nconst keyOf = (item: CommandItem) => `${item.category}:${item.id}`;\n\n/**\n * How well `item` answers `query` (lower case, no spaces): its name or id\n * whole, then a name that starts with it, a word of the name that does, the\n * name holding it, its keys holding it (\"alt+t\"); 0 when nothing does.\n */\nfunction score(item: CommandItem, query: string): number {\n const label = item.label.toLowerCase();\n const flat = searchForm(label);\n if (item.id.toLowerCase() === query || flat === query) return 5;\n if (flat.startsWith(query)) return 4;\n if (label.split(/[\\s/()-]+/).some((word) => word.startsWith(query))) return 3;\n if (flat.includes(query) || item.id.toLowerCase().includes(query)) return 2;\n if (item.shortcut && searchForm(item.shortcut).includes(query)) return 1;\n return 0;\n}\n\ninterface Group {\n key: string;\n label: string;\n items: CommandItem[];\n}\n\nlet paletteSeq = 0;\n\n/**\n * The command palette (Ctrl+K): indicators, chart types, drawing tools,\n * intervals and the widget's own actions, in groups, with their keys. Before\n * anything is typed the commands used last come first. The keys stay in its\n * search: up and down move through the list, Enter runs a command.\n */\nexport class WidgetCommandPalette {\n private backdrop: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private emptyEl: HTMLDivElement | null = null;\n /** Says \"No results\" to a screen reader. */\n private liveEl: HTMLDivElement | null = null;\n private items: CommandItem[] = [];\n /** The rows on show, in order, for the keys. */\n private shown: CommandItem[] = [];\n private selectedIndex = 0;\n private returnFocus: HTMLElement | null = null;\n private readonly uid = ++paletteSeq;\n\n /** Where the overlay mounts (the widget's portal: themed, and inside it when fullscreen). */\n constructor(\n private readonly callbacks: CommandPaletteCallbacks,\n private readonly host: () => HTMLElement = () => document.body,\n private readonly t: Translator = EN_TRANSLATOR,\n private readonly recents?: CommandRecents,\n ) {}\n\n open(items: CommandItem[]): void {\n if (this.backdrop) return;\n this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.items = items;\n this.build();\n this.render();\n this.input?.focus();\n }\n\n close(): void {\n if (!this.backdrop) return;\n this.backdrop.remove();\n this.backdrop = this.input = this.list = this.emptyEl = this.liveEl = null;\n this.callbacks.onClose();\n const back = this.returnFocus;\n this.returnFocus = null;\n if (back?.isConnected) back.focus();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n\n private build(): void {\n const backdrop = document.createElement('div');\n backdrop.className = 'tcw-modal-backdrop';\n // A press that starts in the palette and ends on the backdrop doesn't close it.\n let pressedBackdrop = false;\n backdrop.addEventListener('pointerdown', (e) => {\n pressedBackdrop = e.target === backdrop;\n });\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop && pressedBackdrop) this.close();\n pressedBackdrop = false;\n });\n\n const modal = document.createElement('div');\n modal.className = 'tcw-modal tcw-cp';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-label', this.t('hotkeys.commandPalette'));\n modal.tabIndex = -1;\n modal.addEventListener('keydown', (e) => this.onKeyDown(e, modal));\n\n const search = document.createElement('label');\n search.className = 'tcw-ss-search tcw-cp-search';\n search.innerHTML = createIcon('search', 16);\n const input = document.createElement('input');\n input.type = 'search';\n input.className = 'tcw-cp-input';\n input.placeholder = this.t('palette.placeholder');\n input.setAttribute('aria-label', this.t('palette.placeholder'));\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `tcw-cp-list-${this.uid}`);\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.addEventListener('input', () => this.render());\n search.appendChild(input);\n\n const results = document.createElement('div');\n results.className = 'tcw-cp-results';\n const list = document.createElement('div');\n list.className = 'tcw-cp-list';\n list.id = `tcw-cp-list-${this.uid}`;\n list.setAttribute('role', 'listbox');\n list.setAttribute('aria-label', this.t('hotkeys.commandPalette'));\n const empty = document.createElement('div');\n empty.className = 'tcw-cp-empty';\n results.append(list, empty);\n // A press on a heading or between the rows keeps the keyboard in the search.\n results.addEventListener('mousedown', (e) => e.preventDefault());\n const live = document.createElement('div');\n live.className = 'tcw-cp-live tcw-visually-hidden';\n live.setAttribute('aria-live', 'polite');\n\n modal.append(search, results, live);\n backdrop.appendChild(modal);\n this.host().appendChild(backdrop);\n this.backdrop = backdrop;\n this.input = input;\n this.list = list;\n this.emptyEl = empty;\n this.liveEl = live;\n }\n\n /** The groups for what is typed: the commands used last first while nothing is, then each kind. */\n private groups(): Group[] {\n const query = searchForm((this.input?.value ?? '').trim());\n const groups: Group[] = [];\n if (!query) {\n const byKey = new Map(this.items.map((item) => [keyOf(item), item]));\n const recent = (this.recents?.list() ?? []).map((k) => byKey.get(k)).filter((i): i is CommandItem => !!i).slice(0, RECENT_SHOWN);\n if (recent.length > 0) groups.push({ key: 'recent', label: this.t('palette.group.recent'), items: recent });\n }\n for (const category of CATEGORY_ORDER) {\n let items = this.items.filter((item) => item.category === category);\n if (query) {\n items = items\n .map((item, at) => ({ item, at, s: score(item, query) }))\n .filter((r) => r.s > 0)\n .sort((a, b) => b.s - a.s || a.at - b.at)\n .map((r) => r.item);\n }\n if (items.length > 0) groups.push({ key: category, label: this.t(CATEGORY_LABELS[category]), items });\n }\n // Searching, the group with the best match comes first (the order above among equals).\n if (query) groups.sort((a, b) => score(b.items[0], query) - score(a.items[0], query));\n return groups;\n }\n\n private render(): void {\n const list = this.list;\n if (!list) return;\n const groups = this.groups();\n this.shown = groups.flatMap((g) => g.items);\n this.selectedIndex = 0;\n let index = 0;\n list.replaceChildren(...groups.map((group) => {\n const el = document.createElement('div');\n el.setAttribute('role', 'group');\n el.className = 'tcw-cp-group';\n const heading = document.createElement('div');\n heading.className = 'tcw-cp-heading';\n heading.id = `tcw-cp-${group.key}-${this.uid}`;\n heading.setAttribute('role', 'presentation');\n heading.textContent = group.label;\n el.setAttribute('aria-labelledby', heading.id);\n el.append(heading, ...group.items.map((item) => this.row(item, index++)));\n return el;\n }));\n const note = this.shown.length === 0 ? this.t('palette.empty') : '';\n if (this.emptyEl) this.emptyEl.textContent = note;\n this.emptyEl?.toggleAttribute('hidden', this.shown.length > 0);\n if (this.liveEl) this.liveEl.textContent = note;\n this.markSelection();\n }\n\n private row(item: CommandItem, index: number): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-cp-row';\n row.id = `tcw-cp-opt-${this.uid}-${index}`;\n row.dataset.id = item.id;\n row.setAttribute('role', 'option');\n row.classList.toggle('tcw-on', !!item.active);\n const label = document.createElement('span');\n label.className = 'tcw-cp-label';\n label.textContent = item.label;\n row.appendChild(label);\n if (item.shortcut) {\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cp-key';\n // Keys read left to right in any widget: ⌘+P, never P+⌘.\n kbd.dir = 'ltr';\n kbd.textContent = item.shortcut;\n row.appendChild(kbd);\n }\n if (item.active) {\n const check = document.createElement('span');\n check.className = 'tcw-cp-check';\n check.innerHTML = createIcon('check', 14);\n row.appendChild(check);\n }\n row.addEventListener('click', () => this.run(index));\n row.addEventListener('mousemove', () => {\n if (this.selectedIndex === index) return;\n this.selectedIndex = index;\n this.markSelection();\n });\n return row;\n }\n\n private markSelection(): void {\n const rows = this.list?.querySelectorAll<HTMLElement>('.tcw-cp-row') ?? [];\n let active: HTMLElement | null = null;\n rows.forEach((el, i) => {\n const on = i === this.selectedIndex;\n el.setAttribute('aria-selected', String(on));\n el.classList.toggle('tcw-selected', on);\n if (on) active = el;\n });\n const row = active as HTMLElement | null;\n if (row) {\n this.input?.setAttribute('aria-activedescendant', row.id);\n row.scrollIntoView?.({ block: 'nearest' });\n } else {\n this.input?.removeAttribute('aria-activedescendant');\n }\n }\n\n private run(index: number): void {\n const item = this.shown[index];\n if (!item) return;\n this.recents?.add(keyOf(item));\n this.close();\n switch (item.category) {\n case 'indicator': this.callbacks.onIndicator(item.id); break;\n case 'chartType': this.callbacks.onChartType(item.id as ChartType); break;\n case 'drawing': this.callbacks.onDrawingTool(item.id as DrawingToolType); break;\n case 'timeframe': this.callbacks.onTimeframe(item.id as TimeFrame); break;\n case 'action': this.callbacks.onAction(item.id); break;\n }\n }\n\n private onKeyDown(e: KeyboardEvent, modal: HTMLElement): void {\n e.stopPropagation(); // keys here must not drive chart shortcuts\n // Enter, Escape and the arrows pick and close among an input method's candidates while it composes.\n if (e.isComposing || e.keyCode === IME_KEY_CODE) return;\n // Escape, and the key that opened it, shut it (the browser's own Ctrl+K kept away).\n const toggle = (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k';\n if (e.key === 'Escape' || toggle) {\n e.preventDefault();\n this.close();\n return;\n }\n keepTabInside(e, modal);\n if (e.target !== this.input) return;\n const count = this.shown.length;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n if (count === 0) return;\n this.selectedIndex = (this.selectedIndex + (e.key === 'ArrowDown' ? 1 : -1) + count) % count;\n this.markSelection();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (!e.repeat) this.run(this.selectedIndex);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./focusTrap-DrhhmG0V.cjs`),t=require(`./i18n-C2nQBZTY.cjs`),n=require(`./platformKeys-B82-j1Fs.cjs`);var r=5,i=229,a=[`action`,`drawing`,`chartType`,`timeframe`,`indicator`],o={indicator:`palette.group.indicator`,chartType:`palette.group.chartType`,drawing:`palette.group.drawing`,timeframe:`palette.group.timeframe`,action:`palette.group.action`},s=e=>`${e.category}:${e.id}`;function c(e,t){let r=e.label.toLowerCase(),i=n.n(r);return e.id.toLowerCase()===t||i===t?5:i.startsWith(t)?4:r.split(/[\s/()-]+/).some(e=>e.startsWith(t))?3:i.includes(t)||e.id.toLowerCase().includes(t)?2:e.shortcut&&n.n(e.shortcut).includes(t)?1:0}var l=0,u=class{backdrop=null;input=null;list=null;emptyEl=null;liveEl=null;items=[];shown=[];selectedIndex=0;returnFocus=null;uid=++l;constructor(e,n=()=>document.body,r=t.t,i){this.callbacks=e,this.host=n,this.t=r,this.recents=i}open(e){this.backdrop||(this.returnFocus=document.activeElement instanceof HTMLElement?document.activeElement:null,this.items=e,this.build(),this.render(),this.input?.focus())}close(){if(!this.backdrop)return;this.backdrop.remove(),this.backdrop=this.input=this.list=this.emptyEl=this.liveEl=null,this.callbacks.onClose();let e=this.returnFocus;this.returnFocus=null,e?.isConnected&&e.focus()}isOpen(){return this.backdrop!==null}destroy(){this.close()}build(){let t=document.createElement(`div`);t.className=`tcw-modal-backdrop`;let n=!1;t.addEventListener(`pointerdown`,e=>{n=e.target===t}),t.addEventListener(`click`,e=>{e.target===t&&n&&this.close(),n=!1});let r=document.createElement(`div`);r.className=`tcw-modal tcw-cp`,r.setAttribute(`role`,`dialog`),r.setAttribute(`aria-modal`,`true`),r.setAttribute(`aria-label`,this.t(`hotkeys.commandPalette`)),r.tabIndex=-1,r.addEventListener(`keydown`,e=>this.onKeyDown(e,r));let i=document.createElement(`label`);i.className=`tcw-ss-search tcw-cp-search`,i.innerHTML=e.i(`search`,16);let a=document.createElement(`input`);a.type=`search`,a.className=`tcw-cp-input`,a.placeholder=this.t(`palette.placeholder`),a.setAttribute(`aria-label`,this.t(`palette.placeholder`)),a.setAttribute(`role`,`combobox`),a.setAttribute(`aria-expanded`,`true`),a.setAttribute(`aria-autocomplete`,`list`),a.setAttribute(`aria-controls`,`tcw-cp-list-${this.uid}`),a.autocomplete=`off`,a.spellcheck=!1,a.addEventListener(`input`,()=>this.render()),i.appendChild(a);let o=document.createElement(`div`);o.className=`tcw-cp-results`;let s=document.createElement(`div`);s.className=`tcw-cp-list`,s.id=`tcw-cp-list-${this.uid}`,s.setAttribute(`role`,`listbox`),s.setAttribute(`aria-label`,this.t(`hotkeys.commandPalette`));let c=document.createElement(`div`);c.className=`tcw-cp-empty`,o.append(s,c),o.addEventListener(`mousedown`,e=>e.preventDefault());let l=document.createElement(`div`);l.className=`tcw-cp-live tcw-visually-hidden`,l.setAttribute(`aria-live`,`polite`),r.append(i,o,l),t.appendChild(r),this.host().appendChild(t),this.backdrop=t,this.input=a,this.list=s,this.emptyEl=c,this.liveEl=l}groups(){let e=n.n((this.input?.value??``).trim()),t=[];if(!e){let e=new Map(this.items.map(e=>[s(e),e])),n=(this.recents?.list()??[]).map(t=>e.get(t)).filter(e=>!!e).slice(0,r);n.length>0&&t.push({key:`recent`,label:this.t(`palette.group.recent`),items:n})}for(let n of a){let r=this.items.filter(e=>e.category===n);e&&(r=r.map((t,n)=>({item:t,at:n,s:c(t,e)})).filter(e=>e.s>0).sort((e,t)=>t.s-e.s||e.at-t.at).map(e=>e.item)),r.length>0&&t.push({key:n,label:this.t(o[n]),items:r})}return e&&t.sort((t,n)=>c(n.items[0],e)-c(t.items[0],e)),t}render(){let e=this.list;if(!e)return;let t=this.groups();this.shown=t.flatMap(e=>e.items),this.selectedIndex=0;let n=0;e.replaceChildren(...t.map(e=>{let t=document.createElement(`div`);t.setAttribute(`role`,`group`),t.className=`tcw-cp-group`;let r=document.createElement(`div`);return r.className=`tcw-cp-heading`,r.id=`tcw-cp-${e.key}-${this.uid}`,r.setAttribute(`role`,`presentation`),r.textContent=e.label,t.setAttribute(`aria-labelledby`,r.id),t.append(r,...e.items.map(e=>this.row(e,n++))),t}));let r=this.shown.length===0?this.t(`palette.empty`):``;this.emptyEl&&(this.emptyEl.textContent=r),this.emptyEl?.toggleAttribute(`hidden`,this.shown.length>0),this.liveEl&&(this.liveEl.textContent=r),this.markSelection()}row(t,n){let r=document.createElement(`div`);r.className=`tcw-cp-row`,r.id=`tcw-cp-opt-${this.uid}-${n}`,r.dataset.id=t.id,r.setAttribute(`role`,`option`),r.classList.toggle(`tcw-on`,!!t.active);let i=document.createElement(`span`);if(i.className=`tcw-cp-label`,i.textContent=t.label,r.appendChild(i),t.shortcut){let e=document.createElement(`kbd`);e.className=`tcw-cp-key`,e.dir=`ltr`,e.textContent=t.shortcut,r.appendChild(e)}if(t.active){let t=document.createElement(`span`);t.className=`tcw-cp-check`,t.innerHTML=e.i(`check`,14),r.appendChild(t)}return r.addEventListener(`click`,()=>this.run(n)),r.addEventListener(`mousemove`,()=>{this.selectedIndex!==n&&(this.selectedIndex=n,this.markSelection())}),r}markSelection(){let e=this.list?.querySelectorAll(`.tcw-cp-row`)??[],t=null;e.forEach((e,n)=>{let r=n===this.selectedIndex;e.setAttribute(`aria-selected`,String(r)),e.classList.toggle(`tcw-selected`,r),r&&(t=e)});let n=t;n?(this.input?.setAttribute(`aria-activedescendant`,n.id),n.scrollIntoView?.({block:`nearest`})):this.input?.removeAttribute(`aria-activedescendant`)}run(e){let t=this.shown[e];if(t)switch(this.recents?.add(s(t)),this.close(),t.category){case`indicator`:this.callbacks.onIndicator(t.id);break;case`chartType`:this.callbacks.onChartType(t.id);break;case`drawing`:this.callbacks.onDrawingTool(t.id);break;case`timeframe`:this.callbacks.onTimeframe(t.id);break;case`action`:this.callbacks.onAction(t.id);break}}onKeyDown(t,n){if(t.stopPropagation(),t.isComposing||t.keyCode===i)return;let r=(t.ctrlKey||t.metaKey)&&t.key.toLowerCase()===`k`;if(t.key===`Escape`||r){t.preventDefault(),this.close();return}if(e.n(t,n),t.target!==this.input)return;let a=this.shown.length;if(t.key===`ArrowDown`||t.key===`ArrowUp`){if(t.preventDefault(),a===0)return;this.selectedIndex=(this.selectedIndex+(t.key===`ArrowDown`?1:-1)+a)%a,this.markSelection()}else t.key===`Enter`&&(t.preventDefault(),t.repeat||this.run(this.selectedIndex))}};exports.WidgetCommandPalette=u;
|
|
2
|
+
//# sourceMappingURL=WidgetCommandPalette-ZZNbWwCZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetCommandPalette-ZZNbWwCZ.cjs","names":[],"sources":["../src/widget/WidgetCommandPalette.ts"],"sourcesContent":["import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\nimport { EN_TRANSLATOR, type Translator } from './i18n.js';\nimport { createIcon } from './icons.js';\nimport { keepTabInside } from './focusTrap.js';\nimport { searchForm } from './platformKeys.js';\n\nexport interface CommandItem {\n id: string;\n label: string;\n category: CommandCategory;\n /** Its keys, written at the row's end (\"Alt+T\"). */\n shortcut?: string;\n /** On now (an indicator on the chart, the chart type in use): ticked. */\n active?: boolean;\n}\n\nexport type CommandCategory = 'indicator' | 'chartType' | 'drawing' | 'timeframe' | 'action';\n\nexport interface CommandPaletteCallbacks {\n onIndicator: (id: string) => void;\n onChartType: (type: ChartType) => void;\n onDrawingTool: (tool: DrawingToolType) => void;\n onTimeframe: (tf: TimeFrame) => void;\n onAction: (id: string) => void;\n onClose: () => void;\n}\n\n/** The commands used last, by `category:id`, newest first. */\nexport interface CommandRecents {\n list: () => readonly string[];\n add: (key: string) => void;\n}\n\n/** Commands used last, shown at the top before anything is typed. */\nconst RECENT_SHOWN = 5;\n/** The key code a browser gives a key an input method takes. */\nconst IME_KEY_CODE = 229;\n\n/** The widget's own commands first; the indicators, which have a dialog of their own, last. */\nconst CATEGORY_ORDER: readonly CommandCategory[] = ['action', 'drawing', 'chartType', 'timeframe', 'indicator'];\nconst CATEGORY_LABELS = {\n indicator: 'palette.group.indicator',\n chartType: 'palette.group.chartType',\n drawing: 'palette.group.drawing',\n timeframe: 'palette.group.timeframe',\n action: 'palette.group.action',\n} as const satisfies Record<CommandCategory, string>;\n\nconst keyOf = (item: CommandItem) => `${item.category}:${item.id}`;\n\n/**\n * How well `item` answers `query` (lower case, no spaces): its name or id\n * whole, then a name that starts with it, a word of the name that does, the\n * name holding it, its keys holding it (\"alt+t\"); 0 when nothing does.\n */\nfunction score(item: CommandItem, query: string): number {\n const label = item.label.toLowerCase();\n const flat = searchForm(label);\n if (item.id.toLowerCase() === query || flat === query) return 5;\n if (flat.startsWith(query)) return 4;\n if (label.split(/[\\s/()-]+/).some((word) => word.startsWith(query))) return 3;\n if (flat.includes(query) || item.id.toLowerCase().includes(query)) return 2;\n if (item.shortcut && searchForm(item.shortcut).includes(query)) return 1;\n return 0;\n}\n\ninterface Group {\n key: string;\n label: string;\n items: CommandItem[];\n}\n\nlet paletteSeq = 0;\n\n/**\n * The command palette (Ctrl+K): indicators, chart types, drawing tools,\n * intervals and the widget's own actions, in groups, with their keys. Before\n * anything is typed the commands used last come first. The keys stay in its\n * search: up and down move through the list, Enter runs a command.\n */\nexport class WidgetCommandPalette {\n private backdrop: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private emptyEl: HTMLDivElement | null = null;\n /** Says \"No results\" to a screen reader. */\n private liveEl: HTMLDivElement | null = null;\n private items: CommandItem[] = [];\n /** The rows on show, in order, for the keys. */\n private shown: CommandItem[] = [];\n private selectedIndex = 0;\n private returnFocus: HTMLElement | null = null;\n private readonly uid = ++paletteSeq;\n\n /** Where the overlay mounts (the widget's portal: themed, and inside it when fullscreen). */\n constructor(\n private readonly callbacks: CommandPaletteCallbacks,\n private readonly host: () => HTMLElement = () => document.body,\n private readonly t: Translator = EN_TRANSLATOR,\n private readonly recents?: CommandRecents,\n ) {}\n\n open(items: CommandItem[]): void {\n if (this.backdrop) return;\n this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.items = items;\n this.build();\n this.render();\n this.input?.focus();\n }\n\n close(): void {\n if (!this.backdrop) return;\n this.backdrop.remove();\n this.backdrop = this.input = this.list = this.emptyEl = this.liveEl = null;\n this.callbacks.onClose();\n const back = this.returnFocus;\n this.returnFocus = null;\n if (back?.isConnected) back.focus();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n\n private build(): void {\n const backdrop = document.createElement('div');\n backdrop.className = 'tcw-modal-backdrop';\n // A press that starts in the palette and ends on the backdrop doesn't close it.\n let pressedBackdrop = false;\n backdrop.addEventListener('pointerdown', (e) => {\n pressedBackdrop = e.target === backdrop;\n });\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop && pressedBackdrop) this.close();\n pressedBackdrop = false;\n });\n\n const modal = document.createElement('div');\n modal.className = 'tcw-modal tcw-cp';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-label', this.t('hotkeys.commandPalette'));\n modal.tabIndex = -1;\n modal.addEventListener('keydown', (e) => this.onKeyDown(e, modal));\n\n const search = document.createElement('label');\n search.className = 'tcw-ss-search tcw-cp-search';\n search.innerHTML = createIcon('search', 16);\n const input = document.createElement('input');\n input.type = 'search';\n input.className = 'tcw-cp-input';\n input.placeholder = this.t('palette.placeholder');\n input.setAttribute('aria-label', this.t('palette.placeholder'));\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'true');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-controls', `tcw-cp-list-${this.uid}`);\n input.autocomplete = 'off';\n input.spellcheck = false;\n input.addEventListener('input', () => this.render());\n search.appendChild(input);\n\n const results = document.createElement('div');\n results.className = 'tcw-cp-results';\n const list = document.createElement('div');\n list.className = 'tcw-cp-list';\n list.id = `tcw-cp-list-${this.uid}`;\n list.setAttribute('role', 'listbox');\n list.setAttribute('aria-label', this.t('hotkeys.commandPalette'));\n const empty = document.createElement('div');\n empty.className = 'tcw-cp-empty';\n results.append(list, empty);\n // A press on a heading or between the rows keeps the keyboard in the search.\n results.addEventListener('mousedown', (e) => e.preventDefault());\n const live = document.createElement('div');\n live.className = 'tcw-cp-live tcw-visually-hidden';\n live.setAttribute('aria-live', 'polite');\n\n modal.append(search, results, live);\n backdrop.appendChild(modal);\n this.host().appendChild(backdrop);\n this.backdrop = backdrop;\n this.input = input;\n this.list = list;\n this.emptyEl = empty;\n this.liveEl = live;\n }\n\n /** The groups for what is typed: the commands used last first while nothing is, then each kind. */\n private groups(): Group[] {\n const query = searchForm((this.input?.value ?? '').trim());\n const groups: Group[] = [];\n if (!query) {\n const byKey = new Map(this.items.map((item) => [keyOf(item), item]));\n const recent = (this.recents?.list() ?? []).map((k) => byKey.get(k)).filter((i): i is CommandItem => !!i).slice(0, RECENT_SHOWN);\n if (recent.length > 0) groups.push({ key: 'recent', label: this.t('palette.group.recent'), items: recent });\n }\n for (const category of CATEGORY_ORDER) {\n let items = this.items.filter((item) => item.category === category);\n if (query) {\n items = items\n .map((item, at) => ({ item, at, s: score(item, query) }))\n .filter((r) => r.s > 0)\n .sort((a, b) => b.s - a.s || a.at - b.at)\n .map((r) => r.item);\n }\n if (items.length > 0) groups.push({ key: category, label: this.t(CATEGORY_LABELS[category]), items });\n }\n // Searching, the group with the best match comes first (the order above among equals).\n if (query) groups.sort((a, b) => score(b.items[0], query) - score(a.items[0], query));\n return groups;\n }\n\n private render(): void {\n const list = this.list;\n if (!list) return;\n const groups = this.groups();\n this.shown = groups.flatMap((g) => g.items);\n this.selectedIndex = 0;\n let index = 0;\n list.replaceChildren(...groups.map((group) => {\n const el = document.createElement('div');\n el.setAttribute('role', 'group');\n el.className = 'tcw-cp-group';\n const heading = document.createElement('div');\n heading.className = 'tcw-cp-heading';\n heading.id = `tcw-cp-${group.key}-${this.uid}`;\n heading.setAttribute('role', 'presentation');\n heading.textContent = group.label;\n el.setAttribute('aria-labelledby', heading.id);\n el.append(heading, ...group.items.map((item) => this.row(item, index++)));\n return el;\n }));\n const note = this.shown.length === 0 ? this.t('palette.empty') : '';\n if (this.emptyEl) this.emptyEl.textContent = note;\n this.emptyEl?.toggleAttribute('hidden', this.shown.length > 0);\n if (this.liveEl) this.liveEl.textContent = note;\n this.markSelection();\n }\n\n private row(item: CommandItem, index: number): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-cp-row';\n row.id = `tcw-cp-opt-${this.uid}-${index}`;\n row.dataset.id = item.id;\n row.setAttribute('role', 'option');\n row.classList.toggle('tcw-on', !!item.active);\n const label = document.createElement('span');\n label.className = 'tcw-cp-label';\n label.textContent = item.label;\n row.appendChild(label);\n if (item.shortcut) {\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cp-key';\n // Keys read left to right in any widget: ⌘+P, never P+⌘.\n kbd.dir = 'ltr';\n kbd.textContent = item.shortcut;\n row.appendChild(kbd);\n }\n if (item.active) {\n const check = document.createElement('span');\n check.className = 'tcw-cp-check';\n check.innerHTML = createIcon('check', 14);\n row.appendChild(check);\n }\n row.addEventListener('click', () => this.run(index));\n row.addEventListener('mousemove', () => {\n if (this.selectedIndex === index) return;\n this.selectedIndex = index;\n this.markSelection();\n });\n return row;\n }\n\n private markSelection(): void {\n const rows = this.list?.querySelectorAll<HTMLElement>('.tcw-cp-row') ?? [];\n let active: HTMLElement | null = null;\n rows.forEach((el, i) => {\n const on = i === this.selectedIndex;\n el.setAttribute('aria-selected', String(on));\n el.classList.toggle('tcw-selected', on);\n if (on) active = el;\n });\n const row = active as HTMLElement | null;\n if (row) {\n this.input?.setAttribute('aria-activedescendant', row.id);\n row.scrollIntoView?.({ block: 'nearest' });\n } else {\n this.input?.removeAttribute('aria-activedescendant');\n }\n }\n\n private run(index: number): void {\n const item = this.shown[index];\n if (!item) return;\n this.recents?.add(keyOf(item));\n this.close();\n switch (item.category) {\n case 'indicator': this.callbacks.onIndicator(item.id); break;\n case 'chartType': this.callbacks.onChartType(item.id as ChartType); break;\n case 'drawing': this.callbacks.onDrawingTool(item.id as DrawingToolType); break;\n case 'timeframe': this.callbacks.onTimeframe(item.id as TimeFrame); break;\n case 'action': this.callbacks.onAction(item.id); break;\n }\n }\n\n private onKeyDown(e: KeyboardEvent, modal: HTMLElement): void {\n e.stopPropagation(); // keys here must not drive chart shortcuts\n // Enter, Escape and the arrows pick and close among an input method's candidates while it composes.\n if (e.isComposing || e.keyCode === IME_KEY_CODE) return;\n // Escape, and the key that opened it, shut it (the browser's own Ctrl+K kept away).\n const toggle = (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k';\n if (e.key === 'Escape' || toggle) {\n e.preventDefault();\n this.close();\n return;\n }\n keepTabInside(e, modal);\n if (e.target !== this.input) return;\n const count = this.shown.length;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n if (count === 0) return;\n this.selectedIndex = (this.selectedIndex + (e.key === 'ArrowDown' ? 1 : -1) + count) % count;\n this.markSelection();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (!e.repeat) this.run(this.selectedIndex);\n }\n }\n}\n"],"mappings":"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"}
|