@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.
Files changed (177) hide show
  1. package/dist/LayoutSession-DO4bYkUi.cjs +2 -0
  2. package/dist/LayoutSession-DO4bYkUi.cjs.map +1 -0
  3. package/dist/{LayoutSession-BOQCN6yY.js → LayoutSession-qRYG8GTD.js} +539 -552
  4. package/dist/LayoutSession-qRYG8GTD.js.map +1 -0
  5. package/dist/WidgetCommandPalette-CeCLHPy1.js +177 -0
  6. package/dist/WidgetCommandPalette-CeCLHPy1.js.map +1 -0
  7. package/dist/WidgetCommandPalette-ZZNbWwCZ.cjs +2 -0
  8. package/dist/WidgetCommandPalette-ZZNbWwCZ.cjs.map +1 -0
  9. package/dist/WidgetDrawingSettings-BeW8fX7r.js +474 -0
  10. package/dist/WidgetDrawingSettings-BeW8fX7r.js.map +1 -0
  11. package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs +2 -0
  12. package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs.map +1 -0
  13. package/dist/WidgetGoToDate-BNdngHlg.cjs +2 -0
  14. package/dist/WidgetGoToDate-BNdngHlg.cjs.map +1 -0
  15. package/dist/WidgetGoToDate-hcDtezRm.js +191 -0
  16. package/dist/WidgetGoToDate-hcDtezRm.js.map +1 -0
  17. package/dist/WidgetHotkeySheet-1lRFSdvt.js +416 -0
  18. package/dist/WidgetHotkeySheet-1lRFSdvt.js.map +1 -0
  19. package/dist/WidgetHotkeySheet-y5LWKSG6.cjs +2 -0
  20. package/dist/WidgetHotkeySheet-y5LWKSG6.cjs.map +1 -0
  21. package/dist/WidgetIndicatorPicker-CGvZ5kYd.js +245 -0
  22. package/dist/WidgetIndicatorPicker-CGvZ5kYd.js.map +1 -0
  23. package/dist/WidgetIndicatorPicker-DuKJFPRC.cjs +2 -0
  24. package/dist/WidgetIndicatorPicker-DuKJFPRC.cjs.map +1 -0
  25. package/dist/WidgetIndicatorSettings-C7vpco6e.cjs +2 -0
  26. package/dist/WidgetIndicatorSettings-C7vpco6e.cjs.map +1 -0
  27. package/dist/WidgetIndicatorSettings-dDkqzzYo.js +326 -0
  28. package/dist/WidgetIndicatorSettings-dDkqzzYo.js.map +1 -0
  29. package/dist/WidgetSettings-D7Pq42zW.cjs +2 -0
  30. package/dist/WidgetSettings-D7Pq42zW.cjs.map +1 -0
  31. package/dist/WidgetSettings-eOo93L7Z.js +546 -0
  32. package/dist/WidgetSettings-eOo93L7Z.js.map +1 -0
  33. package/dist/WidgetSymbolSearch-C4OR42nZ.cjs +2 -0
  34. package/dist/WidgetSymbolSearch-C4OR42nZ.cjs.map +1 -0
  35. package/dist/WidgetSymbolSearch-CvPpjIwa.js +580 -0
  36. package/dist/WidgetSymbolSearch-CvPpjIwa.js.map +1 -0
  37. package/dist/focusTrap-Br9Zfje0.js +27 -0
  38. package/dist/focusTrap-Br9Zfje0.js.map +1 -0
  39. package/dist/focusTrap-DrhhmG0V.cjs +2 -0
  40. package/dist/focusTrap-DrhhmG0V.cjs.map +1 -0
  41. package/dist/i18n-C2nQBZTY.cjs +2 -0
  42. package/dist/i18n-C2nQBZTY.cjs.map +1 -0
  43. package/dist/{i18n-DUmd4Z_r.js → i18n-C5v6Tzp1.js} +3 -1
  44. package/dist/i18n-C5v6Tzp1.js.map +1 -0
  45. package/dist/index.cjs +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -1
  49. package/dist/indicatorInputWords-Bd9Pt6qp.js +25 -0
  50. package/dist/indicatorInputWords-Bd9Pt6qp.js.map +1 -0
  51. package/dist/indicatorInputWords-CTA4IcJR.cjs +2 -0
  52. package/dist/indicatorInputWords-CTA4IcJR.cjs.map +1 -0
  53. package/dist/indicatorLabel-BNZvaOcl.cjs +2 -0
  54. package/dist/indicatorLabel-BNZvaOcl.cjs.map +1 -0
  55. package/dist/indicatorLabel-Sbegyhp2.js +17 -0
  56. package/dist/indicatorLabel-Sbegyhp2.js.map +1 -0
  57. package/dist/indicatorSettingsTabs-B0liE3ST.cjs +2 -0
  58. package/dist/indicatorSettingsTabs-B0liE3ST.cjs.map +1 -0
  59. package/dist/indicatorSettingsTabs-XcgMdbLp.js +161 -0
  60. package/dist/indicatorSettingsTabs-XcgMdbLp.js.map +1 -0
  61. package/dist/monthView-B-CieFDJ.cjs +2 -0
  62. package/dist/monthView-B-CieFDJ.cjs.map +1 -0
  63. package/dist/monthView-N8yDaTqZ.js +198 -0
  64. package/dist/monthView-N8yDaTqZ.js.map +1 -0
  65. package/dist/platformKeys-B82-j1Fs.cjs +2 -0
  66. package/dist/platformKeys-B82-j1Fs.cjs.map +1 -0
  67. package/dist/platformKeys-Dd1qOCjF.js +5 -0
  68. package/dist/platformKeys-Dd1qOCjF.js.map +1 -0
  69. package/dist/settingsControls-DIjzCFHI.js +379 -0
  70. package/dist/settingsControls-DIjzCFHI.js.map +1 -0
  71. package/dist/settingsControls-Tn8_vJJv.cjs +2 -0
  72. package/dist/settingsControls-Tn8_vJJv.cjs.map +1 -0
  73. package/dist/symbolCatalog-CA1fpz3s.js +90 -0
  74. package/dist/symbolCatalog-CA1fpz3s.js.map +1 -0
  75. package/dist/symbolCatalog-Dx1YnZgm.cjs +2 -0
  76. package/dist/symbolCatalog-Dx1YnZgm.cjs.map +1 -0
  77. package/dist/widget/ChartWidget.d.ts +102 -582
  78. package/dist/widget/ChartWidget.d.ts.map +1 -1
  79. package/dist/widget/WidgetAlerts.d.ts +35 -0
  80. package/dist/widget/WidgetAlerts.d.ts.map +1 -0
  81. package/dist/widget/WidgetChartSettings.d.ts +194 -0
  82. package/dist/widget/WidgetChartSettings.d.ts.map +1 -0
  83. package/dist/widget/WidgetCommands.d.ts +54 -0
  84. package/dist/widget/WidgetCommands.d.ts.map +1 -0
  85. package/dist/widget/WidgetCompares.d.ts +140 -0
  86. package/dist/widget/WidgetCompares.d.ts.map +1 -0
  87. package/dist/widget/WidgetDockArea.d.ts +89 -0
  88. package/dist/widget/WidgetDockArea.d.ts.map +1 -0
  89. package/dist/widget/WidgetDrawingEdit.d.ts +73 -0
  90. package/dist/widget/WidgetDrawingEdit.d.ts.map +1 -0
  91. package/dist/widget/WidgetGoToDate.d.ts +1 -14
  92. package/dist/widget/WidgetGoToDate.d.ts.map +1 -1
  93. package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -1
  94. package/dist/widget/WidgetIntervals.d.ts +66 -0
  95. package/dist/widget/WidgetIntervals.d.ts.map +1 -0
  96. package/dist/widget/WidgetLayouts.d.ts +85 -0
  97. package/dist/widget/WidgetLayouts.d.ts.map +1 -0
  98. package/dist/widget/WidgetLegendView.d.ts +54 -0
  99. package/dist/widget/WidgetLegendView.d.ts.map +1 -0
  100. package/dist/widget/WidgetMenus.d.ts +79 -0
  101. package/dist/widget/WidgetMenus.d.ts.map +1 -0
  102. package/dist/widget/WidgetReplay.d.ts +199 -0
  103. package/dist/widget/WidgetReplay.d.ts.map +1 -0
  104. package/dist/widget/WidgetTrading.d.ts +48 -0
  105. package/dist/widget/WidgetTrading.d.ts.map +1 -0
  106. package/dist/widget/WidgetWatchlists.d.ts +77 -0
  107. package/dist/widget/WidgetWatchlists.d.ts.map +1 -0
  108. package/dist/widget/drawingSettingsTabs.d.ts +2 -19
  109. package/dist/widget/drawingSettingsTabs.d.ts.map +1 -1
  110. package/dist/widget/drawingText.d.ts +24 -0
  111. package/dist/widget/drawingText.d.ts.map +1 -0
  112. package/dist/widget/index.cjs +22 -23
  113. package/dist/widget/index.cjs.map +1 -1
  114. package/dist/widget/index.js +6193 -9868
  115. package/dist/widget/index.js.map +1 -1
  116. package/dist/widget/keyTarget.d.ts +4 -0
  117. package/dist/widget/keyTarget.d.ts.map +1 -1
  118. package/dist/widget/lazyPart.d.ts +47 -0
  119. package/dist/widget/lazyPart.d.ts.map +1 -0
  120. package/dist/widget/locales/ar.d.ts.map +1 -1
  121. package/dist/widget/locales/cs.d.ts.map +1 -1
  122. package/dist/widget/locales/da.d.ts.map +1 -1
  123. package/dist/widget/locales/de.d.ts.map +1 -1
  124. package/dist/widget/locales/el.d.ts.map +1 -1
  125. package/dist/widget/locales/en.d.ts +1 -0
  126. package/dist/widget/locales/en.d.ts.map +1 -1
  127. package/dist/widget/locales/es.d.ts.map +1 -1
  128. package/dist/widget/locales/et.d.ts.map +1 -1
  129. package/dist/widget/locales/fa.d.ts.map +1 -1
  130. package/dist/widget/locales/fr.d.ts.map +1 -1
  131. package/dist/widget/locales/he.d.ts.map +1 -1
  132. package/dist/widget/locales/hu.d.ts.map +1 -1
  133. package/dist/widget/locales/id.d.ts.map +1 -1
  134. package/dist/widget/locales/index.cjs +1 -1
  135. package/dist/widget/locales/index.cjs.map +1 -1
  136. package/dist/widget/locales/index.js +29 -1
  137. package/dist/widget/locales/index.js.map +1 -1
  138. package/dist/widget/locales/it.d.ts.map +1 -1
  139. package/dist/widget/locales/ja.d.ts.map +1 -1
  140. package/dist/widget/locales/ko.d.ts.map +1 -1
  141. package/dist/widget/locales/ms.d.ts.map +1 -1
  142. package/dist/widget/locales/nb.d.ts.map +1 -1
  143. package/dist/widget/locales/nl.d.ts.map +1 -1
  144. package/dist/widget/locales/pl.d.ts.map +1 -1
  145. package/dist/widget/locales/pt.d.ts.map +1 -1
  146. package/dist/widget/locales/ro.d.ts.map +1 -1
  147. package/dist/widget/locales/ru.d.ts.map +1 -1
  148. package/dist/widget/locales/sk.d.ts.map +1 -1
  149. package/dist/widget/locales/sv.d.ts.map +1 -1
  150. package/dist/widget/locales/th.d.ts.map +1 -1
  151. package/dist/widget/locales/tr.d.ts.map +1 -1
  152. package/dist/widget/locales/vi.d.ts.map +1 -1
  153. package/dist/widget/locales/zh.d.ts.map +1 -1
  154. package/dist/widget/locales/zhHant.d.ts.map +1 -1
  155. package/dist/widget/pageEnv.d.ts +5 -0
  156. package/dist/widget/pageEnv.d.ts.map +1 -0
  157. package/dist/widget/signals.d.ts +41 -0
  158. package/dist/widget/signals.d.ts.map +1 -0
  159. package/dist/widget/wallTime.d.ts +15 -0
  160. package/dist/widget/wallTime.d.ts.map +1 -0
  161. package/dist/widget/widgetDialogs.d.ts +17 -0
  162. package/dist/widget/widgetDialogs.d.ts.map +1 -0
  163. package/dist/widgetFeatures-BM6u0u74.js +186 -0
  164. package/dist/widgetFeatures-BM6u0u74.js.map +1 -0
  165. package/dist/widgetFeatures-BZ8OVPN2.cjs +3 -0
  166. package/dist/widgetFeatures-BZ8OVPN2.cjs.map +1 -0
  167. package/dist/widgetLocales-BPK5i0Ok.cjs +2 -0
  168. package/dist/widgetLocales-BPK5i0Ok.cjs.map +1 -0
  169. package/dist/widgetLocales-DgTR8JSu.js +838 -0
  170. package/dist/widgetLocales-DgTR8JSu.js.map +1 -0
  171. package/package.json +3 -3
  172. package/dist/LayoutSession-BOQCN6yY.js.map +0 -1
  173. package/dist/LayoutSession-RF8OqOXy.cjs +0 -2
  174. package/dist/LayoutSession-RF8OqOXy.cjs.map +0 -1
  175. package/dist/i18n-BsstZ9md.cjs +0 -2
  176. package/dist/i18n-BsstZ9md.cjs.map +0 -1
  177. 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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"}