@unabridged/midwest 0.23.0 → 0.23.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.
@@ -0,0 +1,52 @@
1
+ const PLACEHOLDER = "\uE000";
2
+ function renderMarkdown(src) {
3
+ const blocks = [];
4
+ const withoutFences = src.replace(/```(\w*)\n?([\s\S]*?)```/g, (_match, _lang, code) => {
5
+ const body = escapeHtml(code.replace(/\n$/, ""));
6
+ blocks.push(`<pre class="command-palette-code"><code>${body}</code></pre>`);
7
+ return `${PLACEHOLDER}${blocks.length - 1}${PLACEHOLDER}`;
8
+ });
9
+ const lines = escapeHtml(withoutFences).split("\n");
10
+ const out = [];
11
+ let listOpen = false;
12
+ const closeList = () => {
13
+ if (listOpen) {
14
+ out.push("</ul>");
15
+ listOpen = false;
16
+ }
17
+ };
18
+ for (const line of lines) {
19
+ const placeholder = line.match(new RegExp(`^${PLACEHOLDER}(\\d+)${PLACEHOLDER}$`));
20
+ if (placeholder) {
21
+ closeList();
22
+ out.push(line);
23
+ continue;
24
+ }
25
+ const item = line.match(/^\s*[-*]\s+(.*)$/);
26
+ if (item) {
27
+ if (!listOpen) {
28
+ out.push("<ul>");
29
+ listOpen = true;
30
+ }
31
+ out.push(`<li>${inline(item[1])}</li>`);
32
+ continue;
33
+ }
34
+ closeList();
35
+ if (line.trim() !== "")
36
+ out.push(`<p>${inline(line)}</p>`);
37
+ }
38
+ closeList();
39
+ return out.join("\n").replace(new RegExp(`${PLACEHOLDER}(\\d+)${PLACEHOLDER}`, "g"), (_match, index) => blocks[Number(index)]);
40
+ }
41
+ function inline(text) {
42
+ return text.replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/\*([^*]+)\*/g, "<em>$1</em>").replace(
43
+ /\[([^\]]+)\]\((https?:\/\/[^\s)]+|mailto:[^\s)]+)\)/g,
44
+ '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
45
+ );
46
+ }
47
+ function escapeHtml(text) {
48
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
49
+ }
50
+
51
+ export { renderMarkdown };
52
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sources":["../../../../../../../app/assets/javascript/midwest/markdown.ts"],"sourcesContent":["// Tiny, dependency-free Markdown renderer for streamed chat responses.\n//\n// It is intentionally a small subset (paragraphs, lists, fenced/inline code,\n// bold, italic, and safe links) rather than a full CommonMark implementation —\n// the command palette streams tokens and cannot afford a heavy parser.\n//\n// Security: model output is untrusted. Text is HTML-escaped BEFORE any markup is\n// applied, and links are restricted to http(s)/mailto, so the result is safe to\n// assign to innerHTML.\n\nconst PLACEHOLDER = '\\uE000' // private-use char, unlikely in real text\n\nexport function renderMarkdown (src: string): string {\n const blocks: string[] = []\n\n // Pull fenced code blocks out first so their contents are never treated as markup.\n const withoutFences = src.replace(/```(\\w*)\\n?([\\s\\S]*?)```/g, (_match, _lang, code: string) => {\n const body = escapeHtml(code.replace(/\\n$/, ''))\n blocks.push(`<pre class=\"command-palette-code\"><code>${body}</code></pre>`)\n return `${PLACEHOLDER}${blocks.length - 1}${PLACEHOLDER}`\n })\n\n const lines = escapeHtml(withoutFences).split('\\n')\n const out: string[] = []\n let listOpen = false\n\n const closeList = () => {\n if (listOpen) {\n out.push('</ul>')\n listOpen = false\n }\n }\n\n for (const line of lines) {\n const placeholder = line.match(new RegExp(`^${PLACEHOLDER}(\\\\d+)${PLACEHOLDER}$`))\n if (placeholder) {\n closeList()\n out.push(line)\n continue\n }\n\n const item = line.match(/^\\s*[-*]\\s+(.*)$/)\n if (item) {\n if (!listOpen) {\n out.push('<ul>')\n listOpen = true\n }\n out.push(`<li>${inline(item[1])}</li>`)\n continue\n }\n\n closeList()\n if (line.trim() !== '') out.push(`<p>${inline(line)}</p>`)\n }\n\n closeList()\n\n return out\n .join('\\n')\n .replace(new RegExp(`${PLACEHOLDER}(\\\\d+)${PLACEHOLDER}`, 'g'), (_match, index: string) => blocks[Number(index)])\n}\n\nfunction inline (text: string): string {\n return text\n .replace(/`([^`]+)`/g, '<code>$1</code>')\n .replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>')\n .replace(/\\*([^*]+)\\*/g, '<em>$1</em>')\n .replace(\n /\\[([^\\]]+)\\]\\((https?:\\/\\/[^\\s)]+|mailto:[^\\s)]+)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>'\n )\n}\n\nfunction escapeHtml (text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n}\n"],"names":[],"mappings":"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"}
@@ -1,20 +1,48 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
  import { cloneTemplate } from '../../../assets/javascript/midwest/template_helpers.js';
3
+ import { renderMarkdown } from '../../../assets/javascript/midwest/markdown.js';
3
4
 
4
5
  class CommandPalette extends Controller {
5
- static targets = ["input", "list", "empty", "body", "turboList", "itemTemplate", "groupTemplate"];
6
+ static targets = [
7
+ "input",
8
+ "list",
9
+ "empty",
10
+ "body",
11
+ "turboList",
12
+ "itemTemplate",
13
+ "groupTemplate",
14
+ "modes",
15
+ "chat",
16
+ "transcript",
17
+ "starters",
18
+ "messageTemplate",
19
+ "actionTemplate"
20
+ ];
6
21
  static values = {
7
22
  hotkey: { type: String, default: "k" },
8
23
  items: { type: Array, default: [] },
9
24
  src: { type: String, default: "" },
10
- turboFrameUrl: { type: String, default: "" }
25
+ turboFrameUrl: { type: String, default: "" },
26
+ chatEnabled: { type: Boolean, default: false },
27
+ chatMode: { type: String, default: "proxy" },
28
+ chatTrigger: { type: String, default: "toggle" },
29
+ chatAgentic: { type: Boolean, default: true },
30
+ chatPlaceholder: { type: String, default: "Ask AI\u2026" },
31
+ chatEndpoint: { type: String, default: "" },
32
+ chatUrl: { type: String, default: "" },
33
+ chatModel: { type: String, default: "" }
11
34
  };
12
35
  highlightedIndex = -1;
13
36
  fetchAbort = null;
14
37
  searchTimer;
15
38
  allItems = [];
39
+ mode = "command";
40
+ commandPlaceholder = "";
41
+ messages = [];
42
+ streamAbort = null;
16
43
  connect() {
17
44
  this.allItems = this.itemsValue;
45
+ this.commandPlaceholder = this.inputTarget.placeholder;
18
46
  document.addEventListener("keydown", this.handleGlobalKeydown);
19
47
  this.element.addEventListener("click", this.handleBackdropClick);
20
48
  if (!this.turboFrameUrlValue) {
@@ -26,6 +54,8 @@ class CommandPalette extends Controller {
26
54
  this.element.removeEventListener("click", this.handleBackdropClick);
27
55
  if (this.fetchAbort)
28
56
  this.fetchAbort.abort();
57
+ if (this.streamAbort)
58
+ this.streamAbort.abort();
29
59
  if (this.searchTimer)
30
60
  clearTimeout(this.searchTimer);
31
61
  }
@@ -59,6 +89,8 @@ class CommandPalette extends Controller {
59
89
  this.element.showModal();
60
90
  this.inputTarget.value = "";
61
91
  this.highlightedIndex = -1;
92
+ if (this.chatEnabledValue)
93
+ this.resetChat();
62
94
  if (this.turboFrameUrlValue) {
63
95
  this.navigateFrame("");
64
96
  } else {
@@ -72,6 +104,8 @@ class CommandPalette extends Controller {
72
104
  this.element.close();
73
105
  }
74
106
  filter() {
107
+ if (this.mode === "chat")
108
+ return;
75
109
  const query = this.inputTarget.value.trim().toLowerCase();
76
110
  if (this.turboFrameUrlValue) {
77
111
  this.debouncedNavigateFrame(query);
@@ -92,6 +126,21 @@ class CommandPalette extends Controller {
92
126
  this.renderItems(filtered);
93
127
  }
94
128
  navigate(event) {
129
+ if (this.mode === "chat") {
130
+ if (event.key === "Enter" && !event.shiftKey) {
131
+ event.preventDefault();
132
+ this.send();
133
+ } else if (event.key === "Escape") {
134
+ event.preventDefault();
135
+ this.close();
136
+ }
137
+ return;
138
+ }
139
+ if (event.key === "Tab" && !event.shiftKey && this.chatEnabledValue && this.chatTriggerValue === "toggle" && this.inputTarget.value.trim() === "") {
140
+ event.preventDefault();
141
+ this.setMode("chat");
142
+ return;
143
+ }
95
144
  const items = this.visibleItems;
96
145
  switch (event.key) {
97
146
  case "ArrowDown":
@@ -126,6 +175,225 @@ class CommandPalette extends Controller {
126
175
  this.selectItem(items[index]);
127
176
  }
128
177
  }
178
+ // ── Chat mode ───────────────────────────────────────────────────────
179
+ switchMode(event) {
180
+ const mode = event.currentTarget.dataset.mode === "chat" ? "chat" : "command";
181
+ this.setMode(mode);
182
+ if (mode === "command")
183
+ this.filter();
184
+ this.inputTarget.focus();
185
+ }
186
+ useStarter(event) {
187
+ this.inputTarget.value = event.currentTarget.textContent?.trim() || "";
188
+ this.send();
189
+ }
190
+ resetChat() {
191
+ if (this.streamAbort)
192
+ this.streamAbort.abort();
193
+ this.messages = [];
194
+ if (this.hasTranscriptTarget)
195
+ this.transcriptTarget.innerHTML = "";
196
+ if (this.hasStartersTarget)
197
+ this.startersTarget.hidden = false;
198
+ this.setBusy(false);
199
+ this.setMode("command");
200
+ }
201
+ setMode(mode) {
202
+ if (!this.chatEnabledValue)
203
+ return;
204
+ this.mode = mode;
205
+ const chat = mode === "chat";
206
+ this.element.classList.toggle("chat-active", chat);
207
+ if (this.hasModesTarget) {
208
+ this.modesTarget.querySelectorAll(".command-palette-mode").forEach((el) => {
209
+ el.setAttribute("aria-pressed", String(el.dataset.mode === mode));
210
+ });
211
+ }
212
+ if (this.hasChatTarget)
213
+ this.chatTarget.hidden = !chat;
214
+ if (chat) {
215
+ this.emptyTarget.hidden = true;
216
+ if (this.hasListTarget)
217
+ this.listTarget.hidden = true;
218
+ if (this.hasTurboListTarget)
219
+ this.turboListTarget.hidden = true;
220
+ this.inputTarget.placeholder = this.chatPlaceholderValue;
221
+ } else {
222
+ this.inputTarget.placeholder = this.commandPlaceholder;
223
+ if (this.hasTurboListTarget)
224
+ this.turboListTarget.hidden = false;
225
+ }
226
+ }
227
+ stop() {
228
+ if (this.streamAbort)
229
+ this.streamAbort.abort();
230
+ }
231
+ send() {
232
+ if (this.streamAbort)
233
+ return;
234
+ const text = this.inputTarget.value.trim();
235
+ if (!text)
236
+ return;
237
+ this.appendMessage("user", text);
238
+ this.messages.push({ role: "user", content: text });
239
+ this.inputTarget.value = "";
240
+ if (this.hasStartersTarget)
241
+ this.startersTarget.hidden = true;
242
+ void this.streamReply();
243
+ }
244
+ async streamReply() {
245
+ const message = this.appendMessage("assistant", "");
246
+ const bubble = message.querySelector(".command-palette-message-bubble");
247
+ this.setBusy(true);
248
+ this.streamAbort = new AbortController();
249
+ let reply = "";
250
+ try {
251
+ const response = await fetch(this.chatRequestUrl(), {
252
+ method: "POST",
253
+ headers: { "Content-Type": "application/json", Accept: "text/event-stream" },
254
+ body: JSON.stringify(this.chatRequestBody()),
255
+ signal: this.streamAbort.signal
256
+ });
257
+ if (!response.ok || !response.body)
258
+ throw new Error(`Chat request failed (${response.status})`);
259
+ const reader = response.body.getReader();
260
+ const decoder = new TextDecoder();
261
+ let buffer = "";
262
+ for (; ; ) {
263
+ const { value, done } = await reader.read();
264
+ if (done)
265
+ break;
266
+ buffer += decoder.decode(value, { stream: true });
267
+ const events = buffer.split("\n\n");
268
+ buffer = events.pop() || "";
269
+ for (const event of events) {
270
+ const data = this.parseSseData(event);
271
+ if (!data)
272
+ continue;
273
+ const delta = data.choices?.[0]?.delta?.content;
274
+ if (delta) {
275
+ reply += delta;
276
+ bubble.innerHTML = renderMarkdown(reply);
277
+ this.scrollTranscript();
278
+ } else if (data.midwest) {
279
+ this.handleAgentEvent(data.midwest);
280
+ }
281
+ }
282
+ }
283
+ this.messages.push({ role: "assistant", content: reply });
284
+ } catch (error) {
285
+ if (error.name === "AbortError") {
286
+ if (reply)
287
+ this.messages.push({ role: "assistant", content: reply });
288
+ } else {
289
+ message.classList.add("is-error");
290
+ bubble.textContent = "Something went wrong. Please try again.";
291
+ }
292
+ } finally {
293
+ this.streamAbort = null;
294
+ this.setBusy(false);
295
+ this.scrollTranscript();
296
+ }
297
+ }
298
+ parseSseData(event) {
299
+ const data = event.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("");
300
+ if (!data || data === "[DONE]")
301
+ return null;
302
+ try {
303
+ return JSON.parse(data);
304
+ } catch {
305
+ return null;
306
+ }
307
+ }
308
+ // Agentic events: the server streams a tool "action row" and/or a client
309
+ // directive (navigate / run a palette command). Directives reuse the same
310
+ // execution path as manual selection.
311
+ handleAgentEvent(event) {
312
+ if (event.type === "tool") {
313
+ this.appendActionRow(event);
314
+ } else if (event.type === "directive" && event.directive) {
315
+ this.performDirective(event.directive);
316
+ }
317
+ }
318
+ // Action rows live in the current assistant message's card footer.
319
+ appendActionRow(event) {
320
+ if (!this.hasActionTemplateTarget)
321
+ return;
322
+ const footer = this.currentActionFooter();
323
+ if (!footer)
324
+ return;
325
+ const action = cloneTemplate(this.actionTemplateTarget);
326
+ const label = action.querySelector(".command-palette-action-label");
327
+ if (label)
328
+ label.textContent = event.label || "Action";
329
+ footer.hidden = false;
330
+ footer.appendChild(action);
331
+ this.scrollTranscript();
332
+ }
333
+ currentActionFooter() {
334
+ const messages = this.transcriptTarget.querySelectorAll(
335
+ ".command-palette-message.role-assistant"
336
+ );
337
+ const last = messages[messages.length - 1];
338
+ return last ? last.querySelector(".command-palette-action-footer") : null;
339
+ }
340
+ performDirective(directive) {
341
+ if (directive.url) {
342
+ this.visit(directive.url, directive.method);
343
+ } else if (directive.action) {
344
+ this.element.dispatchEvent(
345
+ new CustomEvent("midwest-command-palette:action", {
346
+ bubbles: true,
347
+ detail: { action: directive.action }
348
+ })
349
+ );
350
+ }
351
+ }
352
+ chatRequestUrl() {
353
+ return this.chatModeValue === "proxy" ? this.chatEndpointValue : this.chatUrlValue;
354
+ }
355
+ chatRequestBody() {
356
+ const body = { messages: this.messages, stream: true };
357
+ if (this.chatModeValue !== "proxy" && this.chatModelValue)
358
+ body.model = this.chatModelValue;
359
+ if (this.chatModeValue === "proxy" && this.chatAgenticValue) {
360
+ body.commands = this.allItems.map((item) => ({
361
+ label: item.label,
362
+ description: item.description,
363
+ url: item.url,
364
+ action: item.action,
365
+ method: item.method,
366
+ icon: item.icon
367
+ }));
368
+ }
369
+ return body;
370
+ }
371
+ setBusy(busy) {
372
+ this.element.classList.toggle("chat-busy", busy);
373
+ if (this.hasStopTarget)
374
+ this.stopTarget.hidden = !busy;
375
+ if (this.hasTranscriptTarget)
376
+ this.transcriptTarget.setAttribute("aria-busy", String(busy));
377
+ }
378
+ scrollTranscript() {
379
+ if (this.hasTranscriptTarget)
380
+ this.transcriptTarget.scrollTop = this.transcriptTarget.scrollHeight;
381
+ }
382
+ appendMessage(role, text) {
383
+ const li = cloneTemplate(this.messageTemplateTarget);
384
+ li.classList.add(`role-${role}`);
385
+ if (role === "user")
386
+ li.classList.add("is-end");
387
+ const roleEl = li.querySelector(".command-palette-message-role");
388
+ if (roleEl)
389
+ roleEl.textContent = role === "user" ? "You" : "Assistant";
390
+ const bubble = li.querySelector(".command-palette-message-bubble");
391
+ if (text)
392
+ bubble.textContent = text;
393
+ this.transcriptTarget.appendChild(li);
394
+ this.scrollTranscript();
395
+ return li;
396
+ }
129
397
  // ── Remote search ───────────────────────────────────────────────────
130
398
  fetchRemote(query) {
131
399
  if (this.fetchAbort)
@@ -1 +1 @@
1
- {"version":3,"file":"command_palette_component_controller.js","sources":["../../../../../../../app/components/midwest/command_palette_component/command_palette_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\nimport { cloneTemplate } from '../../../assets/javascript/midwest/template_helpers'\n\ninterface PaletteItem {\n label: string\n description?: string\n icon?: string\n url?: string\n action?: string\n group?: string\n shortcut?: string\n method?: string\n confirm?: string\n}\n\nexport default class CommandPalette extends Controller<HTMLDialogElement> {\n static targets = ['input', 'list', 'empty', 'body', 'turboList', 'itemTemplate', 'groupTemplate']\n\n static values = {\n hotkey: { type: String, default: 'k' },\n items: { type: Array, default: [] },\n src: { type: String, default: '' },\n turboFrameUrl: { type: String, default: '' }\n }\n\n declare readonly inputTarget: HTMLInputElement\n declare readonly listTarget: HTMLElement\n declare readonly emptyTarget: HTMLElement\n declare readonly bodyTarget: HTMLElement\n declare readonly turboListTarget: HTMLElement\n declare readonly hasTurboListTarget: boolean\n declare readonly hasListTarget: boolean\n declare readonly itemTemplateTarget: HTMLTemplateElement\n declare readonly groupTemplateTarget: HTMLTemplateElement\n\n declare hotkeyValue: string\n declare itemsValue: PaletteItem[]\n declare srcValue: string\n declare turboFrameUrlValue: string\n\n private highlightedIndex = -1\n private fetchAbort: AbortController | null = null\n private searchTimer: number | undefined\n private allItems: PaletteItem[] = []\n\n connect () {\n this.allItems = this.itemsValue\n document.addEventListener('keydown', this.handleGlobalKeydown)\n this.element.addEventListener('click', this.handleBackdropClick)\n\n // Only render client-side items when not in turbo-frame mode\n if (!this.turboFrameUrlValue) {\n this.renderItems(this.allItems)\n }\n }\n\n disconnect () {\n document.removeEventListener('keydown', this.handleGlobalKeydown)\n this.element.removeEventListener('click', this.handleBackdropClick)\n if (this.fetchAbort) this.fetchAbort.abort()\n if (this.searchTimer) clearTimeout(this.searchTimer)\n }\n\n // ── Turbo frame lifecycle ───────────────────────────────────────────\n\n turboListTargetConnected (el: HTMLElement) {\n el.addEventListener('turbo:frame-load', this.onFrameLoad)\n }\n\n turboListTargetDisconnected (el: HTMLElement) {\n el.removeEventListener('turbo:frame-load', this.onFrameLoad)\n }\n\n private onFrameLoad = () => {\n if (!this.hasListTarget) return\n\n const items = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n if (items.length > 0) {\n this.highlightedIndex = 0\n this.updateHighlight()\n this.emptyTarget.hidden = true\n if (this.hasListTarget) this.listTarget.hidden = false\n } else {\n this.emptyTarget.hidden = false\n if (this.hasListTarget) this.listTarget.hidden = true\n }\n }\n\n // ── Public actions ──────────────────────────────────────────────────\n\n open () {\n if (this.element.open) return\n this.element.showModal()\n this.inputTarget.value = ''\n this.highlightedIndex = -1\n\n if (this.turboFrameUrlValue) {\n this.navigateFrame('')\n } else {\n this.renderItems(this.allItems)\n }\n\n requestAnimationFrame(() => this.inputTarget.focus())\n }\n\n close () {\n if (!this.element.open) return\n this.element.close()\n }\n\n filter () {\n const query = this.inputTarget.value.trim().toLowerCase()\n\n if (this.turboFrameUrlValue) {\n this.debouncedNavigateFrame(query)\n return\n }\n\n if (this.srcValue && query.length > 0) {\n this.fetchRemote(query)\n return\n }\n\n if (query.length === 0) {\n this.renderItems(this.allItems)\n return\n }\n\n const filtered = this.allItems.filter(item => {\n const haystack = `${item.label} ${item.description || ''} ${item.group || ''}`.toLowerCase()\n return haystack.includes(query)\n })\n\n this.renderItems(filtered)\n }\n\n navigate (event: KeyboardEvent) {\n const items = this.visibleItems\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n this.highlightedIndex = Math.min(this.highlightedIndex + 1, items.length - 1)\n this.updateHighlight()\n break\n case 'ArrowUp':\n event.preventDefault()\n this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0)\n this.updateHighlight()\n break\n case 'Enter':\n event.preventDefault()\n if (this.highlightedIndex >= 0 && this.highlightedIndex < items.length) {\n this.selectItem(items[this.highlightedIndex])\n }\n break\n case 'Escape':\n event.preventDefault()\n this.close()\n break\n }\n }\n\n select (event: Event) {\n const el = (event.target as HTMLElement).closest<HTMLElement>('.command-palette-item')\n if (!el) return\n const index = parseInt(el.dataset.index || '-1', 10)\n const items = this.visibleItems\n if (index >= 0 && index < items.length) {\n this.selectItem(items[index])\n }\n }\n\n // ── Remote search ───────────────────────────────────────────────────\n\n private fetchRemote (query: string) {\n if (this.fetchAbort) this.fetchAbort.abort()\n if (this.searchTimer) clearTimeout(this.searchTimer)\n\n this.searchTimer = window.setTimeout(async () => {\n this.fetchAbort = new AbortController()\n try {\n const url = new URL(this.srcValue, window.location.origin)\n url.searchParams.set('q', query)\n const response = await fetch(url.toString(), {\n headers: { Accept: 'application/json' },\n signal: this.fetchAbort.signal\n })\n if (response.ok) {\n const data: PaletteItem[] = await response.json()\n this.renderItems(data)\n }\n } catch (e) {\n if ((e as Error).name !== 'AbortError') throw e\n }\n }, 200)\n }\n\n // ── Turbo frame navigation ──────────────────────────────────────────\n\n private navigateFrame (query: string) {\n if (!this.hasTurboListTarget) return\n const url = new URL(this.turboFrameUrlValue, window.location.href)\n if (query) url.searchParams.set('q', query)\n this.turboListTarget.setAttribute('src', url.toString())\n }\n\n private debouncedNavigateFrame (query: string) {\n if (this.searchTimer) clearTimeout(this.searchTimer)\n\n this.searchTimer = window.setTimeout(() => {\n this.navigateFrame(query)\n }, 200)\n }\n\n // ── Rendering ───────────────────────────────────────────────────────\n\n private renderItems (items: PaletteItem[]) {\n if (!this.hasListTarget) return\n\n this.listTarget.innerHTML = ''\n this.highlightedIndex = -1\n\n if (items.length === 0) {\n this.emptyTarget.hidden = false\n this.listTarget.hidden = true\n return\n }\n\n this.emptyTarget.hidden = true\n this.listTarget.hidden = false\n\n // Group items\n const groups = new Map<string, PaletteItem[]>()\n for (const item of items) {\n const group = item.group || ''\n if (!groups.has(group)) groups.set(group, [])\n groups.get(group)!.push(item) // eslint-disable-line @typescript-eslint/no-non-null-assertion\n }\n\n let index = 0\n for (const [groupName, groupItems] of groups) {\n if (groupName) {\n this.listTarget.appendChild(this.buildGroup(groupName))\n }\n\n for (const item of groupItems) {\n this.listTarget.appendChild(this.buildItem(item, index))\n index++\n }\n }\n\n // Highlight first item\n if (items.length > 0) {\n this.highlightedIndex = 0\n this.updateHighlight()\n }\n }\n\n private buildGroup (name: string): HTMLElement {\n const li = cloneTemplate(this.groupTemplateTarget)\n const h6 = li.querySelector('.midwest-label')\n if (h6) h6.textContent = name\n return li\n }\n\n private buildItem (item: PaletteItem, index: number): HTMLElement {\n const li = cloneTemplate(this.itemTemplateTarget)\n li.dataset.index = String(index)\n\n if (item.url) li.dataset.url = item.url\n if (item.action) li.dataset.paletteAction = item.action\n if (item.method) li.dataset.turboMethod = item.method\n if (item.confirm) li.dataset.turboConfirm = item.confirm\n\n // Icon\n const iconSpan = li.querySelector('.command-palette-item-icon') as HTMLElement\n if (item.icon) {\n iconSpan.innerHTML = this.getIconSvg(item.icon)\n iconSpan.hidden = false\n } else {\n iconSpan.remove()\n }\n\n // Label\n const label = li.querySelector('.command-palette-item-label') as Element\n label.textContent = item.label\n\n // Description\n const desc = li.querySelector('.command-palette-item-description') as HTMLElement\n if (item.description) {\n desc.textContent = item.description\n desc.hidden = false\n } else {\n desc.remove()\n }\n\n // Shortcut\n const shortcutSpan = li.querySelector('.command-palette-item-shortcut') as HTMLElement\n if (item.shortcut) {\n item.shortcut.split('+').forEach(key => {\n const kbd = document.createElement('kbd')\n kbd.className = 'midwest-kbd'\n kbd.textContent = key.trim()\n shortcutSpan.appendChild(kbd)\n })\n shortcutSpan.hidden = false\n } else {\n shortcutSpan.remove()\n }\n\n return li\n }\n\n // ── Selection ───────────────────────────────────────────────────────\n\n private selectItem (item: PaletteItem) {\n if (item.confirm && !window.confirm(item.confirm)) return\n\n this.close()\n\n if (item.url) {\n this.visit(item.url, item.method)\n return\n }\n\n if (item.action) {\n this.element.dispatchEvent(\n new CustomEvent('midwest-command-palette:action', {\n bubbles: true,\n detail: { action: item.action, item }\n })\n )\n }\n }\n\n private visit (url: string, method?: string) {\n if (method && method.toLowerCase() !== 'get') {\n // Non-GET methods: create a temporary link with data-turbo-method\n // and let Turbo handle the request\n const link = document.createElement('a')\n link.href = url\n link.dataset.turboMethod = method\n link.style.display = 'none'\n document.body.appendChild(link)\n link.click()\n link.remove()\n return\n }\n\n const turbo = (window as any).Turbo\n if (turbo?.visit) {\n turbo.visit(url)\n } else {\n window.location.href = url\n }\n }\n\n // ── Highlight ───────────────────────────────────────────────────────\n\n private get visibleItems (): PaletteItem[] {\n if (!this.hasListTarget) return []\n\n const items: PaletteItem[] = []\n const els = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n for (const el of els) {\n items.push({\n label: el.querySelector('.command-palette-item-label')?.textContent || '',\n url: el.dataset.url,\n action: el.dataset.paletteAction,\n method: el.dataset.turboMethod,\n confirm: el.dataset.turboConfirm\n })\n }\n return items\n }\n\n private updateHighlight () {\n if (!this.hasListTarget) return\n\n const items = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n items.forEach((el, i) => {\n el.setAttribute('aria-selected', String(i === this.highlightedIndex))\n })\n\n const highlighted = items[this.highlightedIndex]\n if (highlighted) {\n highlighted.scrollIntoView({ block: 'nearest' })\n this.inputTarget.setAttribute('aria-activedescendant', highlighted.id || '')\n }\n }\n\n // ── Hotkey ──────────────────────────────────────────────────────────\n\n private handleGlobalKeydown = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === this.hotkeyValue) {\n event.preventDefault()\n if (this.element.open) {\n this.close()\n } else {\n this.open()\n }\n }\n }\n\n private handleBackdropClick = (event: Event) => {\n if (event.target === this.element) this.close()\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────\n\n private getIconSvg (name: string): string {\n const existing = document.querySelector(`.Midwest-Icon__Svg[aria-label=\"${name}\"]`)\n if (existing) return existing.outerHTML\n\n const allIcons = document.querySelectorAll('.Midwest-Icon__Svg')\n for (const icon of allIcons) {\n if (icon.getAttribute('aria-label')?.toLowerCase() === name.toLowerCase()) {\n return icon.outerHTML\n }\n }\n\n return ''\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command_palette_component_controller.js","sources":["../../../../../../../app/components/midwest/command_palette_component/command_palette_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\nimport { cloneTemplate } from '../../../assets/javascript/midwest/template_helpers'\nimport { renderMarkdown } from '../../../assets/javascript/midwest/markdown'\n\ninterface ChatMessage {\n role: 'user' | 'assistant'\n content: string\n}\n\ninterface Directive {\n action?: string\n url?: string\n method?: string\n}\n\ninterface AgentEvent {\n type: 'tool' | 'directive'\n label?: string\n icon?: string\n status?: string\n directive?: Directive\n}\n\ninterface SseData {\n choices?: { delta?: { content?: string } }[]\n midwest?: AgentEvent\n}\n\ninterface PaletteItem {\n label: string\n description?: string\n icon?: string\n url?: string\n action?: string\n group?: string\n shortcut?: string\n method?: string\n confirm?: string\n}\n\nexport default class CommandPalette extends Controller<HTMLDialogElement> {\n static targets = [\n 'input', 'list', 'empty', 'body', 'turboList', 'itemTemplate', 'groupTemplate',\n 'modes', 'chat', 'transcript', 'starters', 'messageTemplate', 'actionTemplate'\n ]\n\n static values = {\n hotkey: { type: String, default: 'k' },\n items: { type: Array, default: [] },\n src: { type: String, default: '' },\n turboFrameUrl: { type: String, default: '' },\n chatEnabled: { type: Boolean, default: false },\n chatMode: { type: String, default: 'proxy' },\n chatTrigger: { type: String, default: 'toggle' },\n chatAgentic: { type: Boolean, default: true },\n chatPlaceholder: { type: String, default: 'Ask AI…' },\n chatEndpoint: { type: String, default: '' },\n chatUrl: { type: String, default: '' },\n chatModel: { type: String, default: '' }\n }\n\n declare readonly inputTarget: HTMLInputElement\n declare readonly listTarget: HTMLElement\n declare readonly emptyTarget: HTMLElement\n declare readonly bodyTarget: HTMLElement\n declare readonly turboListTarget: HTMLElement\n declare readonly hasTurboListTarget: boolean\n declare readonly hasListTarget: boolean\n declare readonly itemTemplateTarget: HTMLTemplateElement\n declare readonly groupTemplateTarget: HTMLTemplateElement\n declare readonly modesTarget: HTMLElement\n declare readonly hasModesTarget: boolean\n declare readonly chatTarget: HTMLElement\n declare readonly hasChatTarget: boolean\n declare readonly transcriptTarget: HTMLElement\n declare readonly hasTranscriptTarget: boolean\n declare readonly startersTarget: HTMLElement\n declare readonly hasStartersTarget: boolean\n declare readonly messageTemplateTarget: HTMLTemplateElement\n declare readonly actionTemplateTarget: HTMLTemplateElement\n declare readonly hasActionTemplateTarget: boolean\n declare readonly stopTarget: HTMLElement\n declare readonly hasStopTarget: boolean\n\n declare hotkeyValue: string\n declare itemsValue: PaletteItem[]\n declare srcValue: string\n declare turboFrameUrlValue: string\n declare chatEnabledValue: boolean\n declare chatModeValue: string\n declare chatTriggerValue: string\n declare chatAgenticValue: boolean\n declare chatPlaceholderValue: string\n declare chatEndpointValue: string\n declare chatUrlValue: string\n declare chatModelValue: string\n\n private highlightedIndex = -1\n private fetchAbort: AbortController | null = null\n private searchTimer: number | undefined\n private allItems: PaletteItem[] = []\n private mode: 'command' | 'chat' = 'command'\n private commandPlaceholder = ''\n private messages: ChatMessage[] = []\n private streamAbort: AbortController | null = null\n\n connect () {\n this.allItems = this.itemsValue\n this.commandPlaceholder = this.inputTarget.placeholder\n document.addEventListener('keydown', this.handleGlobalKeydown)\n this.element.addEventListener('click', this.handleBackdropClick)\n\n // Only render client-side items when not in turbo-frame mode\n if (!this.turboFrameUrlValue) {\n this.renderItems(this.allItems)\n }\n }\n\n disconnect () {\n document.removeEventListener('keydown', this.handleGlobalKeydown)\n this.element.removeEventListener('click', this.handleBackdropClick)\n if (this.fetchAbort) this.fetchAbort.abort()\n if (this.streamAbort) this.streamAbort.abort()\n if (this.searchTimer) clearTimeout(this.searchTimer)\n }\n\n // ── Turbo frame lifecycle ───────────────────────────────────────────\n\n turboListTargetConnected (el: HTMLElement) {\n el.addEventListener('turbo:frame-load', this.onFrameLoad)\n }\n\n turboListTargetDisconnected (el: HTMLElement) {\n el.removeEventListener('turbo:frame-load', this.onFrameLoad)\n }\n\n private onFrameLoad = () => {\n if (!this.hasListTarget) return\n\n const items = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n if (items.length > 0) {\n this.highlightedIndex = 0\n this.updateHighlight()\n this.emptyTarget.hidden = true\n if (this.hasListTarget) this.listTarget.hidden = false\n } else {\n this.emptyTarget.hidden = false\n if (this.hasListTarget) this.listTarget.hidden = true\n }\n }\n\n // ── Public actions ──────────────────────────────────────────────────\n\n open () {\n if (this.element.open) return\n this.element.showModal()\n this.inputTarget.value = ''\n this.highlightedIndex = -1\n\n // Chat resets to a fresh conversation in command mode on every open.\n if (this.chatEnabledValue) this.resetChat()\n\n if (this.turboFrameUrlValue) {\n this.navigateFrame('')\n } else {\n this.renderItems(this.allItems)\n }\n\n requestAnimationFrame(() => this.inputTarget.focus())\n }\n\n close () {\n if (!this.element.open) return\n this.element.close()\n }\n\n filter () {\n // In chat mode the input is the composer — typing must not filter commands.\n if (this.mode === 'chat') return\n\n const query = this.inputTarget.value.trim().toLowerCase()\n\n if (this.turboFrameUrlValue) {\n this.debouncedNavigateFrame(query)\n return\n }\n\n if (this.srcValue && query.length > 0) {\n this.fetchRemote(query)\n return\n }\n\n if (query.length === 0) {\n this.renderItems(this.allItems)\n return\n }\n\n const filtered = this.allItems.filter(item => {\n const haystack = `${item.label} ${item.description || ''} ${item.group || ''}`.toLowerCase()\n return haystack.includes(query)\n })\n\n this.renderItems(filtered)\n }\n\n navigate (event: KeyboardEvent) {\n if (this.mode === 'chat') {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault()\n this.send()\n } else if (event.key === 'Escape') {\n event.preventDefault()\n this.close()\n }\n return\n }\n\n // Tab from an empty query enters chat mode (toggle trigger only).\n if (\n event.key === 'Tab' && !event.shiftKey &&\n this.chatEnabledValue && this.chatTriggerValue === 'toggle' &&\n this.inputTarget.value.trim() === ''\n ) {\n event.preventDefault()\n this.setMode('chat')\n return\n }\n\n const items = this.visibleItems\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n this.highlightedIndex = Math.min(this.highlightedIndex + 1, items.length - 1)\n this.updateHighlight()\n break\n case 'ArrowUp':\n event.preventDefault()\n this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0)\n this.updateHighlight()\n break\n case 'Enter':\n event.preventDefault()\n if (this.highlightedIndex >= 0 && this.highlightedIndex < items.length) {\n this.selectItem(items[this.highlightedIndex])\n }\n break\n case 'Escape':\n event.preventDefault()\n this.close()\n break\n }\n }\n\n select (event: Event) {\n const el = (event.target as HTMLElement).closest<HTMLElement>('.command-palette-item')\n if (!el) return\n const index = parseInt(el.dataset.index || '-1', 10)\n const items = this.visibleItems\n if (index >= 0 && index < items.length) {\n this.selectItem(items[index])\n }\n }\n\n // ── Chat mode ───────────────────────────────────────────────────────\n\n switchMode (event: Event) {\n const mode = (event.currentTarget as HTMLElement).dataset.mode === 'chat' ? 'chat' : 'command'\n this.setMode(mode)\n if (mode === 'command') this.filter()\n this.inputTarget.focus()\n }\n\n useStarter (event: Event) {\n this.inputTarget.value = (event.currentTarget as HTMLElement).textContent?.trim() || ''\n this.send()\n }\n\n private resetChat () {\n if (this.streamAbort) this.streamAbort.abort()\n this.messages = []\n if (this.hasTranscriptTarget) this.transcriptTarget.innerHTML = ''\n if (this.hasStartersTarget) this.startersTarget.hidden = false\n this.setBusy(false)\n this.setMode('command')\n }\n\n private setMode (mode: 'command' | 'chat') {\n if (!this.chatEnabledValue) return\n this.mode = mode\n const chat = mode === 'chat'\n this.element.classList.toggle('chat-active', chat)\n\n if (this.hasModesTarget) {\n this.modesTarget.querySelectorAll<HTMLElement>('.command-palette-mode').forEach(el => {\n el.setAttribute('aria-pressed', String(el.dataset.mode === mode))\n })\n }\n\n if (this.hasChatTarget) this.chatTarget.hidden = !chat\n\n if (chat) {\n this.emptyTarget.hidden = true\n if (this.hasListTarget) this.listTarget.hidden = true\n if (this.hasTurboListTarget) this.turboListTarget.hidden = true\n this.inputTarget.placeholder = this.chatPlaceholderValue\n } else {\n this.inputTarget.placeholder = this.commandPlaceholder\n if (this.hasTurboListTarget) this.turboListTarget.hidden = false\n }\n }\n\n stop () {\n if (this.streamAbort) this.streamAbort.abort()\n }\n\n private send () {\n if (this.streamAbort) return // a reply is already streaming\n\n const text = this.inputTarget.value.trim()\n if (!text) return\n\n this.appendMessage('user', text)\n this.messages.push({ role: 'user', content: text })\n this.inputTarget.value = ''\n if (this.hasStartersTarget) this.startersTarget.hidden = true\n\n void this.streamReply()\n }\n\n private async streamReply () {\n const message = this.appendMessage('assistant', '')\n const bubble = message.querySelector('.command-palette-message-bubble') as HTMLElement\n this.setBusy(true)\n this.streamAbort = new AbortController()\n\n let reply = ''\n try {\n const response = await fetch(this.chatRequestUrl(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' },\n body: JSON.stringify(this.chatRequestBody()),\n signal: this.streamAbort.signal\n })\n\n if (!response.ok || !response.body) throw new Error(`Chat request failed (${response.status})`)\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n for (;;) {\n const { value, done } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n\n const events = buffer.split('\\n\\n')\n buffer = events.pop() || ''\n\n for (const event of events) {\n const data = this.parseSseData(event)\n if (!data) continue\n\n const delta = data.choices?.[0]?.delta?.content\n if (delta) {\n reply += delta\n bubble.innerHTML = renderMarkdown(reply)\n this.scrollTranscript()\n } else if (data.midwest) {\n this.handleAgentEvent(data.midwest)\n }\n }\n }\n\n this.messages.push({ role: 'assistant', content: reply })\n } catch (error) {\n if ((error as Error).name === 'AbortError') {\n if (reply) this.messages.push({ role: 'assistant', content: reply })\n } else {\n message.classList.add('is-error')\n bubble.textContent = 'Something went wrong. Please try again.'\n }\n } finally {\n this.streamAbort = null\n this.setBusy(false)\n this.scrollTranscript()\n }\n }\n\n private parseSseData (event: string): SseData | null {\n const data = event\n .split('\\n')\n .filter(line => line.startsWith('data:'))\n .map(line => line.slice(5).trim())\n .join('')\n\n if (!data || data === '[DONE]') return null\n\n try {\n return JSON.parse(data) as SseData\n } catch {\n return null\n }\n }\n\n // Agentic events: the server streams a tool \"action row\" and/or a client\n // directive (navigate / run a palette command). Directives reuse the same\n // execution path as manual selection.\n private handleAgentEvent (event: AgentEvent) {\n if (event.type === 'tool') {\n this.appendActionRow(event)\n } else if (event.type === 'directive' && event.directive) {\n this.performDirective(event.directive)\n }\n }\n\n // Action rows live in the current assistant message's card footer.\n private appendActionRow (event: AgentEvent) {\n if (!this.hasActionTemplateTarget) return\n\n const footer = this.currentActionFooter()\n if (!footer) return\n\n const action = cloneTemplate(this.actionTemplateTarget)\n const label = action.querySelector('.command-palette-action-label')\n if (label) label.textContent = event.label || 'Action'\n\n footer.hidden = false\n footer.appendChild(action)\n this.scrollTranscript()\n }\n\n private currentActionFooter (): HTMLElement | null {\n const messages = this.transcriptTarget.querySelectorAll<HTMLElement>(\n '.command-palette-message.role-assistant'\n )\n const last = messages[messages.length - 1]\n return last ? last.querySelector<HTMLElement>('.command-palette-action-footer') : null\n }\n\n private performDirective (directive: Directive) {\n if (directive.url) {\n this.visit(directive.url, directive.method)\n } else if (directive.action) {\n this.element.dispatchEvent(\n new CustomEvent('midwest-command-palette:action', {\n bubbles: true,\n detail: { action: directive.action }\n })\n )\n }\n }\n\n private chatRequestUrl (): string {\n return this.chatModeValue === 'proxy' ? this.chatEndpointValue : this.chatUrlValue\n }\n\n private chatRequestBody (): Record<string, unknown> {\n const body: Record<string, unknown> = { messages: this.messages, stream: true }\n // In proxy mode the server owns the model; only direct mode sends it.\n if (this.chatModeValue !== 'proxy' && this.chatModelValue) body.model = this.chatModelValue\n // Expose the palette's commands as tools the model can invoke (proxy only).\n if (this.chatModeValue === 'proxy' && this.chatAgenticValue) {\n body.commands = this.allItems.map(item => ({\n label: item.label,\n description: item.description,\n url: item.url,\n action: item.action,\n method: item.method,\n icon: item.icon\n }))\n }\n return body\n }\n\n private setBusy (busy: boolean) {\n this.element.classList.toggle('chat-busy', busy)\n if (this.hasStopTarget) this.stopTarget.hidden = !busy\n // Hold the polite live region until the reply finishes so screen readers\n // announce the completed message instead of every streamed token.\n if (this.hasTranscriptTarget) this.transcriptTarget.setAttribute('aria-busy', String(busy))\n }\n\n private scrollTranscript () {\n if (this.hasTranscriptTarget) this.transcriptTarget.scrollTop = this.transcriptTarget.scrollHeight\n }\n\n private appendMessage (role: 'user' | 'assistant', text: string): HTMLElement {\n const li = cloneTemplate(this.messageTemplateTarget)\n li.classList.add(`role-${role}`)\n if (role === 'user') li.classList.add('is-end') // user messages sit on the trailing side\n\n const roleEl = li.querySelector('.command-palette-message-role')\n if (roleEl) roleEl.textContent = role === 'user' ? 'You' : 'Assistant'\n\n const bubble = li.querySelector('.command-palette-message-bubble') as HTMLElement\n if (text) bubble.textContent = text\n\n this.transcriptTarget.appendChild(li)\n this.scrollTranscript()\n return li\n }\n\n // ── Remote search ───────────────────────────────────────────────────\n\n private fetchRemote (query: string) {\n if (this.fetchAbort) this.fetchAbort.abort()\n if (this.searchTimer) clearTimeout(this.searchTimer)\n\n this.searchTimer = window.setTimeout(async () => {\n this.fetchAbort = new AbortController()\n try {\n const url = new URL(this.srcValue, window.location.origin)\n url.searchParams.set('q', query)\n const response = await fetch(url.toString(), {\n headers: { Accept: 'application/json' },\n signal: this.fetchAbort.signal\n })\n if (response.ok) {\n const data: PaletteItem[] = await response.json()\n this.renderItems(data)\n }\n } catch (e) {\n if ((e as Error).name !== 'AbortError') throw e\n }\n }, 200)\n }\n\n // ── Turbo frame navigation ──────────────────────────────────────────\n\n private navigateFrame (query: string) {\n if (!this.hasTurboListTarget) return\n const url = new URL(this.turboFrameUrlValue, window.location.href)\n if (query) url.searchParams.set('q', query)\n this.turboListTarget.setAttribute('src', url.toString())\n }\n\n private debouncedNavigateFrame (query: string) {\n if (this.searchTimer) clearTimeout(this.searchTimer)\n\n this.searchTimer = window.setTimeout(() => {\n this.navigateFrame(query)\n }, 200)\n }\n\n // ── Rendering ───────────────────────────────────────────────────────\n\n private renderItems (items: PaletteItem[]) {\n if (!this.hasListTarget) return\n\n this.listTarget.innerHTML = ''\n this.highlightedIndex = -1\n\n if (items.length === 0) {\n this.emptyTarget.hidden = false\n this.listTarget.hidden = true\n return\n }\n\n this.emptyTarget.hidden = true\n this.listTarget.hidden = false\n\n // Group items\n const groups = new Map<string, PaletteItem[]>()\n for (const item of items) {\n const group = item.group || ''\n if (!groups.has(group)) groups.set(group, [])\n groups.get(group)!.push(item) // eslint-disable-line @typescript-eslint/no-non-null-assertion\n }\n\n let index = 0\n for (const [groupName, groupItems] of groups) {\n if (groupName) {\n this.listTarget.appendChild(this.buildGroup(groupName))\n }\n\n for (const item of groupItems) {\n this.listTarget.appendChild(this.buildItem(item, index))\n index++\n }\n }\n\n // Highlight first item\n if (items.length > 0) {\n this.highlightedIndex = 0\n this.updateHighlight()\n }\n }\n\n private buildGroup (name: string): HTMLElement {\n const li = cloneTemplate(this.groupTemplateTarget)\n const h6 = li.querySelector('.midwest-label')\n if (h6) h6.textContent = name\n return li\n }\n\n private buildItem (item: PaletteItem, index: number): HTMLElement {\n const li = cloneTemplate(this.itemTemplateTarget)\n li.dataset.index = String(index)\n\n if (item.url) li.dataset.url = item.url\n if (item.action) li.dataset.paletteAction = item.action\n if (item.method) li.dataset.turboMethod = item.method\n if (item.confirm) li.dataset.turboConfirm = item.confirm\n\n // Icon\n const iconSpan = li.querySelector('.command-palette-item-icon') as HTMLElement\n if (item.icon) {\n iconSpan.innerHTML = this.getIconSvg(item.icon)\n iconSpan.hidden = false\n } else {\n iconSpan.remove()\n }\n\n // Label\n const label = li.querySelector('.command-palette-item-label') as Element\n label.textContent = item.label\n\n // Description\n const desc = li.querySelector('.command-palette-item-description') as HTMLElement\n if (item.description) {\n desc.textContent = item.description\n desc.hidden = false\n } else {\n desc.remove()\n }\n\n // Shortcut\n const shortcutSpan = li.querySelector('.command-palette-item-shortcut') as HTMLElement\n if (item.shortcut) {\n item.shortcut.split('+').forEach(key => {\n const kbd = document.createElement('kbd')\n kbd.className = 'midwest-kbd'\n kbd.textContent = key.trim()\n shortcutSpan.appendChild(kbd)\n })\n shortcutSpan.hidden = false\n } else {\n shortcutSpan.remove()\n }\n\n return li\n }\n\n // ── Selection ───────────────────────────────────────────────────────\n\n private selectItem (item: PaletteItem) {\n if (item.confirm && !window.confirm(item.confirm)) return\n\n this.close()\n\n if (item.url) {\n this.visit(item.url, item.method)\n return\n }\n\n if (item.action) {\n this.element.dispatchEvent(\n new CustomEvent('midwest-command-palette:action', {\n bubbles: true,\n detail: { action: item.action, item }\n })\n )\n }\n }\n\n private visit (url: string, method?: string) {\n if (method && method.toLowerCase() !== 'get') {\n // Non-GET methods: create a temporary link with data-turbo-method\n // and let Turbo handle the request\n const link = document.createElement('a')\n link.href = url\n link.dataset.turboMethod = method\n link.style.display = 'none'\n document.body.appendChild(link)\n link.click()\n link.remove()\n return\n }\n\n const turbo = (window as any).Turbo\n if (turbo?.visit) {\n turbo.visit(url)\n } else {\n window.location.href = url\n }\n }\n\n // ── Highlight ───────────────────────────────────────────────────────\n\n private get visibleItems (): PaletteItem[] {\n if (!this.hasListTarget) return []\n\n const items: PaletteItem[] = []\n const els = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n for (const el of els) {\n items.push({\n label: el.querySelector('.command-palette-item-label')?.textContent || '',\n url: el.dataset.url,\n action: el.dataset.paletteAction,\n method: el.dataset.turboMethod,\n confirm: el.dataset.turboConfirm\n })\n }\n return items\n }\n\n private updateHighlight () {\n if (!this.hasListTarget) return\n\n const items = this.listTarget.querySelectorAll<HTMLElement>('.command-palette-item')\n items.forEach((el, i) => {\n el.setAttribute('aria-selected', String(i === this.highlightedIndex))\n })\n\n const highlighted = items[this.highlightedIndex]\n if (highlighted) {\n highlighted.scrollIntoView({ block: 'nearest' })\n this.inputTarget.setAttribute('aria-activedescendant', highlighted.id || '')\n }\n }\n\n // ── Hotkey ──────────────────────────────────────────────────────────\n\n private handleGlobalKeydown = (event: KeyboardEvent) => {\n if ((event.metaKey || event.ctrlKey) && event.key === this.hotkeyValue) {\n event.preventDefault()\n if (this.element.open) {\n this.close()\n } else {\n this.open()\n }\n }\n }\n\n private handleBackdropClick = (event: Event) => {\n if (event.target === this.element) this.close()\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────\n\n private getIconSvg (name: string): string {\n const existing = document.querySelector(`.Midwest-Icon__Svg[aria-label=\"${name}\"]`)\n if (existing) return existing.outerHTML\n\n const allIcons = document.querySelectorAll('.Midwest-Icon__Svg')\n for (const icon of allIcons) {\n if (icon.getAttribute('aria-label')?.toLowerCase() === name.toLowerCase()) {\n return icon.outerHTML\n }\n }\n\n return ''\n }\n}\n"],"names":[],"mappings":"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"}