// vibeproxy admin UI — minimal vanilla JS, no framework. (function () { "use strict"; // Light/dark theme toggle, persisted in localStorage. var themeBtn = document.querySelector("[data-theme-toggle]"); if (themeBtn) { var icon = themeBtn.querySelector("i"); function syncIcon() { var isLight = document.documentElement.getAttribute("data-bs-theme") === "light"; icon.className = isLight ? "bi bi-sun" : "bi bi-moon-stars"; } syncIcon(); themeBtn.addEventListener("click", function () { var current = document.documentElement.getAttribute("data-bs-theme") === "light" ? "light" : "dark"; var next = current === "dark" ? "light" : "dark"; document.documentElement.setAttribute("data-bs-theme", next); localStorage.setItem("vp-theme", next); syncIcon(); }); } // Generic delete-confirmation modal. Any element with // data-confirm-delete-form="
" and data-confirm-message="..." // opens #confirmDeleteModal and, on confirm, submits the named form. document.addEventListener("click", function (e) { var trigger = e.target.closest("[data-confirm-delete-form]"); if (!trigger) return; e.preventDefault(); var formId = trigger.getAttribute("data-confirm-delete-form"); var message = trigger.getAttribute("data-confirm-message") || "Are you sure? This cannot be undone."; var modalEl = document.getElementById("confirmDeleteModal"); if (!modalEl) return; modalEl.querySelector(".modal-body").textContent = message; var confirmBtn = modalEl.querySelector("[data-confirm-action]"); confirmBtn.onclick = function () { var form = document.getElementById(formId); if (form) form.submit(); }; var modal = bootstrap.Modal.getOrCreateInstance(modalEl); modal.show(); }); // Dynamic add/remove rows for repeatable form sections (backends, // custom headers), driven by a