(function () { "use strict"; if (window.__smolcodeTuiInit) return; window.__smolcodeTuiInit = true; let leaderPending = false; let leaderTimer = null; function click(id) { const root = document.getElementById(id); if (!root) return; const btn = root.tagName === "BUTTON" ? root : root.querySelector("button"); (btn || root).click(); } function setHiddenValue(id, value) { const root = document.getElementById(id); if (!root) return; const el = root.tagName === "TEXTAREA" || root.tagName === "INPUT" ? root : root.querySelector("textarea, input"); if (!el) return; el.value = value; el.dispatchEvent(new Event("input", { bubbles: true })); } window.__smolcodePick = function (idx) { setHiddenValue("sc-picker-pick", String(idx)); click("sc-picker-confirm"); }; function editor() { const root = document.getElementById("sc-editor"); if (root) { if (root.tagName === "TEXTAREA" || root.tagName === "INPUT") return root; const inner = root.querySelector("textarea, input[type='text']"); if (inner) return inner; } const boxes = document.querySelectorAll("[data-testid='textbox']"); return boxes.length ? boxes[boxes.length - 1] : null; } function PopupController(popupEl, kind) { this.popup = popupEl; this.kind = kind || "slash"; this.matches = []; this.sel = 0; } PopupController.prototype.hide = function () { if (this.popup) this.popup.style.display = "none"; this.matches = []; this.sel = 0; }; PopupController.prototype.render = function (matches, ta, replaceFrom) { this.matches = matches; this.sel = 0; this.replaceFrom = replaceFrom; this.ta = ta; if (!this.popup) return; this.popup.innerHTML = ""; const self = this; matches.slice(0, 12).forEach(function (item, i) { const row = document.createElement("div"); row.className = "sc-popup-item" + (i === 0 ? " sc-popup-sel" : ""); row.textContent = item; row.onclick = function () { self.sel = i; self.accept(); }; self.popup.appendChild(row); }); const rect = ta.getBoundingClientRect(); this.popup.style.display = matches.length ? "block" : "none"; this.popup.style.left = rect.left + "px"; this.popup.style.top = Math.max(0, rect.top - 160) + "px"; this.popup.style.width = Math.max(220, rect.width) + "px"; this._highlight(); }; PopupController.prototype._highlight = function () { if (!this.popup) return; const items = this.popup.querySelectorAll(".sc-popup-item"); items.forEach(function (el, i) { el.classList.toggle("sc-popup-sel", i === this.sel); }, this); }; PopupController.prototype.move = function (delta) { if (!this.matches.length) return; this.sel = (this.sel + delta + this.matches.length) % this.matches.length; this._highlight(); }; PopupController.prototype.accept = function () { if (!this.matches.length || !this.ta) return; const val = this.ta.value; if (this.kind === "file") { const atMatch = val.match(/(?:^|\s)@(\S*)$/); if (!atMatch) return; const atPos = val.length - atMatch[0].length + (atMatch[0].charAt(0) === " " ? 1 : 0); const item = this.matches[this.sel]; this.ta.value = val.slice(0, atPos) + "@" + item + " "; } else { const item = this.matches[this.sel]; const rest = val.slice(this.replaceFrom); this.ta.value = item + rest; } this.ta.dispatchEvent(new Event("input", { bubbles: true })); this.hide(); this.ta.focus(); }; PopupController.prototype.tabComplete = function () { if (!this.matches.length) return false; this.accept(); return true; }; PopupController.prototype.visible = function () { return this.popup && this.popup.style.display === "block" && this.matches.length > 0; }; function ensurePopup(cls) { let el = document.querySelector("." + cls); if (!el) { el = document.createElement("div"); el.className = cls + " sc-popup"; document.body.appendChild(el); } return el; } const slashPopup = new PopupController(ensurePopup("sc-slash-popup"), "slash"); const filePopup = new PopupController(ensurePopup("sc-file-popup"), "file"); function hidePopups() { slashPopup.hide(); filePopup.hide(); } function onEditorInput(ta) { const val = ta.value; const cmds = window.__smolcode_commands || []; if (val.startsWith("/") && !val.includes(" ")) { const m = cmds.filter(function (c) { return c.startsWith(val); }); slashPopup.render(m, ta, val.length); filePopup.hide(); return; } slashPopup.hide(); const atMatch = val.match(/(?:^|\s)@(\S*)$/); if (atMatch) { const prefix = atMatch[1]; const files = window.__smolcode_files || []; const m = files.filter(function (f) { return f.startsWith(prefix); }); const atPos = val.length - atMatch[0].length + (atMatch[0].charAt(0) === " " ? 1 : 0); filePopup.render(m, ta, atPos); return; } filePopup.hide(); } function activePopup() { if (slashPopup.visible()) return slashPopup; if (filePopup.visible()) return filePopup; return null; } function onEditorKeyDown(e) { const ta = e.target; const popup = activePopup(); if (popup && (e.key === "ArrowDown" || e.key === "ArrowUp")) { e.preventDefault(); popup.move(e.key === "ArrowDown" ? 1 : -1); return; } if (popup && e.key === "Enter" && !e.shiftKey) { e.preventDefault(); popup.accept(); return; } if (e.key === "Tab" && popup && !e.shiftKey) { e.preventDefault(); popup.tabComplete(); return; } if (e.key === "Enter" && !e.shiftKey && !e.altKey) { e.preventDefault(); hidePopups(); click("sc-submit"); return; } if (e.key === "Escape") { hidePopups(); if (document.querySelector(".sc-overlay")) { click("sc-close-overlay"); } else { click("sc-interrupt"); } return; } if (e.ctrlKey && (e.key === "l" || e.key === "L")) { e.preventDefault(); click("sc-clear"); return; } if (e.ctrlKey && (e.key === "x" || e.key === "X")) { e.preventDefault(); leaderPending = true; if (leaderTimer) clearTimeout(leaderTimer); leaderTimer = setTimeout(function () { leaderPending = false; }, 2000); click("sc-whichkey"); return; } if (leaderPending && !e.ctrlKey && !e.metaKey && e.key.length === 1) { leaderPending = false; if (leaderTimer) clearTimeout(leaderTimer); const map = { m: "sc-open-picker-models", a: "sc-open-picker-agents", t: "sc-open-picker-themes", l: "sc-open-picker-sessions", n: "sc-new-session", b: "sc-toggle-sidebar", s: "sc-toggle-sidebar-view", h: "sc-help", o: "sc-cycle-mode", e: "sc-cycle-think", }; const btn = map[e.key.toLowerCase()]; if (btn) { e.preventDefault(); click(btn); } return; } if (e.key === "Tab" && !e.shiftKey) { if (trySlashTabComplete(ta, e)) return; } if (e.key === "Tab" && !e.shiftKey && !activePopup()) { e.preventDefault(); click("sc-cycle-agent"); return; } if (e.key === "Tab" && e.shiftKey) { e.preventDefault(); click("sc-cycle-mode"); return; } if (e.key === "F2") { e.preventDefault(); click("sc-cycle-model"); return; } if (document.querySelector(".sc-picker") && !ta) { if (e.key === "ArrowDown") { e.preventDefault(); click("sc-picker-down"); } else if (e.key === "ArrowUp") { e.preventDefault(); click("sc-picker-up"); } else if (e.key === "Enter") { e.preventDefault(); click("sc-picker-confirm"); } } } function onGlobalKeyDown(e) { if (document.querySelector(".sc-picker") && document.activeElement !== editor()) { if (e.key === "ArrowDown") { e.preventDefault(); click("sc-picker-down"); } else if (e.key === "ArrowUp") { e.preventDefault(); click("sc-picker-up"); } else if (e.key === "Enter") { e.preventDefault(); click("sc-picker-confirm"); } } } function bindEditor() { const ta = editor(); if (!ta || ta.dataset.scBound) return; ta.dataset.scBound = "1"; ta.addEventListener("input", function () { onEditorInput(ta); }); ta.addEventListener("keydown", onEditorKeyDown); } function bindChips() { /* chips re-render with status HTML; use delegation in init() */ } function onDocumentClick(e) { const chip = e.target.closest("[data-picker]"); if (chip) { const kind = chip.getAttribute("data-picker"); const map = { models: "sc-open-picker-models", agents: "sc-open-picker-agents", themes: "sc-open-picker-themes", sessions: "sc-open-picker-sessions", }; if (map[kind]) { e.preventDefault(); click(map[kind]); } return; } const modeBtn = e.target.closest("[data-action='cycle-mode']"); if (modeBtn) { e.preventDefault(); click("sc-cycle-mode"); } } function slashMatches(val) { if (!val.startsWith("/") || val.includes(" ")) return []; const cmds = window.__smolcode_commands || []; return cmds.filter(function (c) { return c.startsWith(val); }); } function trySlashTabComplete(ta, e) { const val = ta.value; const matches = slashMatches(val); if (!matches.length) return false; e.preventDefault(); const popup = activePopup(); if (popup && popup.kind === "slash" && popup.matches.length) { popup.tabComplete(); return true; } ta.value = matches[0]; ta.dispatchEvent(new Event("input", { bubbles: true })); hidePopups(); return true; } function init() { document.addEventListener("click", onDocumentClick); document.addEventListener("click", function (e) { const overlay = document.querySelector(".sc-overlay"); if (overlay && e.target === overlay) click("sc-close-overlay"); }); document.addEventListener("keydown", onGlobalKeyDown); const obs = new MutationObserver(function () { bindEditor(); }); obs.observe(document.body, { childList: true, subtree: true }); bindEditor(); setTimeout(bindEditor, 300); setTimeout(bindEditor, 1500); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();