// svrnty_nav.js — injects Adwright + BTE sidebar buttons into hermes-webui's // .sidebar-nav and wraps switchPanel so our panels participate in the existing // main-view show/hide system (showing- on
). // // Each panel module (adwright.js, bte.js) mounts its content inside
// and CSS keys visibility off main.showing-adwright / main.showing-bte. // // IIFE, idempotent — guarded by window.__svrntyNavLoaded. (function () { "use strict"; if (window.__svrntyNavLoaded) return; window.__svrntyNavLoaded = true; const TABS = [ { id: "adwright", label: "Adwright", tooltip: "Adwright — marketing intelligence", // Bullseye / target icon — marketing focus svg: '', }, { id: "bte", label: "BTE", tooltip: "BTE — brand creative studio", // Palette/sparkle icon — creative svg: '', }, ]; function _injectButtons() { const nav = document.querySelector(".sidebar-nav"); if (!nav) return false; TABS.forEach((t) => { if (nav.querySelector('[data-panel="' + t.id + '"]')) return; const btn = document.createElement("button"); btn.className = "nav-tab has-tooltip has-tooltip--bottom svrnty-nav-tab"; btn.setAttribute("data-panel", t.id); btn.setAttribute("data-label", t.label); btn.setAttribute("data-tooltip", t.tooltip); btn.setAttribute("aria-label", t.label); btn.innerHTML = t.svg; btn.addEventListener("click", () => { if (typeof window.switchPanel === "function") { window.switchPanel(t.id, { fromRailClick: true }); } }); nav.appendChild(btn); }); return true; } // Wrap switchPanel to add showing- class on
for our IDs. // We chain the original so all upstream behavior (collapse rail, hide other // panels, toggle data-panel active) keeps working unchanged. function _wrapSwitchPanel() { if (typeof window.switchPanel !== "function") return false; if (window.switchPanel.__svrntyWrapped) return true; const original = window.switchPanel; const OUR_IDS = TABS.map((t) => t.id); async function wrapped(name, opts) { const result = await original(name, opts); const main = document.querySelector("main.main"); if (main) { OUR_IDS.forEach((id) => { main.classList.toggle("svrnty-showing-" + id, name === id); }); } // Notify panel modules so they can lazy-init/refresh. try { window.dispatchEvent( new CustomEvent("svrnty:panel-switch", { detail: { name } }), ); } catch (_) {} return result; } wrapped.__svrntyWrapped = true; window.switchPanel = wrapped; return true; } function _init() { const buttonsOk = _injectButtons(); const wrapOk = _wrapSwitchPanel(); if (!buttonsOk || !wrapOk) { // DOM not ready yet — retry on next paint requestAnimationFrame(_init); } } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", _init); } else { _init(); } // Re-inject buttons if something re-renders the sidebar (defensive). const obs = new MutationObserver(() => { const nav = document.querySelector(".sidebar-nav"); if (!nav) return; const missing = TABS.some((t) => !nav.querySelector('[data-panel="' + t.id + '"]')); if (missing) _injectButtons(); }); if (document.body) { obs.observe(document.body, { childList: true, subtree: true }); } else { document.addEventListener("DOMContentLoaded", () => obs.observe(document.body, { childList: true, subtree: true }), ); } // Expose namespace window.SvrntyNav = { TABS, _injectButtons, _wrapSwitchPanel }; })();