// SPDX-License-Identifier: GPL-3.0-or-later /* === Command palette (Ctrl/Cmd+K) === One keystroke to jump anywhere: views, actions and findings, filtered as you type. Arrow keys move, Enter runs, Esc closes. Linear's signature, wired to the same functions the toolbar already calls. */ let paletteItems = []; let paletteSel = 0; function isPaletteOpen() { const el = $("#palette"); return !!el && !el.hidden; } /* Every entry is { group, label, hint, run }. Findings come from the report that is already in memory; nothing extra is fetched. */ function paletteCommands() { const cmds = []; for (const v of VIEWS) { const label = v.charAt(0).toUpperCase() + v.slice(1); cmds.push({ group: "Views", label, hint: "Open", run: () => switchView(v) }); } cmds.push({ group: "Actions", label: "Re-run checks", run: () => $("#rerun")?.click() }); cmds.push({ group: "Actions", label: "Toggle theme", run: () => $("#theme")?.click() }); cmds.push({ group: "Actions", label: "Expand all findings", run: () => setAllOpen(true) }); cmds.push({ group: "Actions", label: "Collapse all findings", run: () => setAllOpen(false) }); cmds.push({ group: "Actions", label: "Toggle compact density", run: () => $("#densitybtn")?.click() }); cmds.push({ group: "Actions", label: "Open the all-checks matrix", run: () => $("#checksmatrixbtn")?.click() }); cmds.push({ group: "Actions", label: "Edit thresholds", run: () => $("#threshbtn")?.click() }); cmds.push({ group: "Actions", label: "Export report", run: () => $("#export-trigger")?.click() }); cmds.push({ group: "Actions", label: "Keyboard shortcuts", run: () => openHelp() }); const findings = (typeof lastReportData !== "undefined" && lastReportData && lastReportData.findings) || []; for (const f of findings) { cmds.push({ group: "Findings", label: f.title || f.code || "Finding", hint: (f.code ? f.code + " ยท " : "") + (SEV_NAMES[f.severity] || f.severity || ""), run: () => jumpToFinding(f), }); } return cmds; } function jumpToFinding(f) { switchView("overview"); const el = [...document.querySelectorAll("#report .card")].find((c) => (c.dataset.code || "") === (f.code || "")); if (!el) return; el.setAttribute("open", ""); if (typeof wideModeOn === "function" && wideModeOn() && typeof selectFinding === "function") selectFinding(el); el.scrollIntoView({ block: "center" }); el.focus({ preventScroll: true }); } function paletteFilter(q) { const all = paletteCommands(); const needle = q.trim().toLowerCase(); if (!needle) return all.slice(0, 40); const out = []; for (const c of all) { const hay = (c.label + " " + (c.hint || "") + " " + c.group).toLowerCase(); if (hay.includes(needle)) out.push(c); } return out.slice(0, 40); } function renderPalette(q) { paletteItems = paletteFilter(q); if (paletteSel >= paletteItems.length) paletteSel = 0; const list = $("#palette-list"); if (!list) return; if (!paletteItems.length) { list.innerHTML = '