import { emit, on } from "../lib/bus.js";
import { navigateToView, navigateToItem } from "../lib/router.js";
class OpsShell extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this._currentView = "chat";
this._currentParams = {};
this.shadowRoot.innerHTML = `
`;
}
connectedCallback() {
this._unsub = on("sse:status", (s) => {
const el = this.shadowRoot.getElementById("sseStatus");
el.textContent = s.ok ? "SSE: connected" : "SSE: disconnected (retrying…)";
});
// Listen for view switch requests from other components
this._unsubSwitch = on("ui:switchView", ({ view }) => {
if (view) this.setView(view, {}, { updateUrl: true });
});
// Listen for router changes (popstate, initial load)
this._unsubRouter = on("router:change", ({ view, params }) => {
this.setView(view, params, { updateUrl: false });
});
// Navigation - intercept clicks on nav links
const navBtns = this.shadowRoot.querySelectorAll(".nav-btn");
for (const btn of navBtns) {
btn.onclick = (e) => {
e.preventDefault();
const view = btn.dataset.view;
this.setView(view, {}, { updateUrl: true });
};
}
}
disconnectedCallback() {
this._unsub?.();
this._unsubSwitch?.();
this._unsubRouter?.();
}
setView(viewName, params = {}, { updateUrl = true } = {}) {
this._currentView = viewName;
this._currentParams = params;
// Update nav buttons
const navBtns = this.shadowRoot.querySelectorAll(".nav-btn");
for (const btn of navBtns) {
btn.classList.toggle("active", btn.dataset.view === viewName);
}
// Update views
const views = this.shadowRoot.querySelectorAll(".view");
for (const view of views) {
const isActive = view.id === `view${viewName.charAt(0).toUpperCase() + viewName.slice(1)}`;
view.classList.toggle("active", isActive);
}
// Update URL if requested
if (updateUrl) {
if (params.id) {
navigateToItem(viewName, params.id);
} else {
navigateToView(viewName);
}
}
// Emit event for components that need to know about route params
emit("router:viewChanged", { view: viewName, params });
}
}
customElements.define("ops-shell", OpsShell);