import { h, replace } from "./dom.js"; import { activeTasks, findTask, onEach, state } from "./state.js"; export function mountNavbar(root, showInbox) { const crumb = h("button", { class: "crumb", title: "Switch task (⌘K)" }); crumb.onclick = openSwitcher; const inbox = h("button", { class: "inbox-count" }); inbox.onclick = showInbox; const conn = h("span", { class: "connection down", title: "connecting" }); const me = h("span", { class: "me" }); const render = () => { const task = state.selectedTaskId ? findTask(state.selectedTaskId) : undefined; const project = task ? state.projects.find((p) => p.id === task.project_id) : undefined; replace(crumb, task ? `${project?.name ?? ""} ▸ ${task.title}` : "No task", " ▾"); const blocked = state.inbox.filter((i) => i.priority === "blocked").length; inbox.className = blocked > 0 ? "inbox-count urgent" : "inbox-count"; replace(inbox, `Inbox ${state.inbox.length}`, blocked > 0 && h("span", { class: "blocked-count" }, ` · ${blocked} blocked`)); conn.className = state.connected ? "connection up" : "connection down"; conn.title = state.connected ? "live" : "reconnecting"; replace(me, state.me?.display_name ?? ""); }; onEach(["me", "projects", "tasks", "inbox", "selection", "connection"], render); replace(root, h("a", { href: "#/", class: "brand" }, "byre"), crumb, h("span", { class: "spacer" }), inbox, conn, me); render(); addEventListener("keydown", (e) => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); openSwitcher(); } }); } function openSwitcher() { if (document.querySelector(".switcher")) { return; } const input = h("input", { placeholder: "Go to task…", autocomplete: "off" }); const list = h("ul", { class: "switcher-list" }); const backdrop = h("div", { class: "switcher-backdrop" }); const box = h("div", { class: "switcher" }, input, list); let selected = 0; let matches = []; const close = () => { backdrop.remove(); box.remove(); }; const go = (taskId) => { close(); location.hash = `#/task/${taskId}`; }; const render = () => { const q = input.value.trim().toLowerCase(); matches = activeTasks().filter(({ project, task }) => `${project.name} ${task.title}`.toLowerCase().includes(q)); selected = Math.min(selected, Math.max(matches.length - 1, 0)); replace(list, ...matches.map(({ project, task }, i) => { const li = h("li", { class: i === selected ? "selected" : "" }, h("span", { class: "project-name" }, project.name), " ", task.title); li.onmousedown = (e) => { e.preventDefault(); go(task.id); }; return li; }), matches.length === 0 && h("li", { class: "empty-row" }, "No matching tasks.")); }; input.oninput = () => { selected = 0; render(); }; input.onkeydown = (e) => { if (e.key === "Escape") { close(); } else if (e.key === "ArrowDown") { e.preventDefault(); selected = Math.min(selected + 1, matches.length - 1); render(); } else if (e.key === "ArrowUp") { e.preventDefault(); selected = Math.max(selected - 1, 0); render(); } else if (e.key === "Enter") { const match = matches[selected]; if (match) { go(match.task.id); } } }; backdrop.onclick = close; document.body.append(backdrop, box); render(); input.focus(); } //# sourceMappingURL=navbar.js.map