const legacyCopy = (value) => { const textarea = document.createElement("textarea"); textarea.value = value; textarea.setAttribute("readonly", ""); textarea.style.position = "fixed"; textarea.style.top = "-9999px"; textarea.style.left = "-9999px"; document.body.append(textarea); textarea.select(); textarea.setSelectionRange(0, textarea.value.length); try { return document.execCommand("copy"); } finally { textarea.remove(); } }; const copyText = async (value) => { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(value); return true; } return legacyCopy(value); }; const showCopyStatus = (button, text, className, duration = 1200) => { const label = button.querySelector("[data-copy-label]"); const oldLabel = label ? label.textContent : ""; button.classList.add(className); if (label) { label.setAttribute("aria-live", "polite"); label.textContent = text; } setTimeout(() => { button.classList.remove(className); if (label) label.textContent = oldLabel; }, duration); }; document.addEventListener("click", async (event) => { document.querySelectorAll("details.copy-menu[open]").forEach((menu) => { if (!menu.contains(event.target)) menu.removeAttribute("open"); }); const toggle = event.target.closest("[data-secret-toggle]"); if (toggle) { const group = toggle.closest(".copy-field"); const field = group ? group.querySelector("[data-secret-input], [data-secret-value]") : null; if (!field) return; if (field.matches("[data-secret-input]")) { const masked = field.type === "password"; field.type = masked ? "text" : "password"; toggle.textContent = masked ? "Hide" : "View"; toggle.setAttribute("aria-label", masked ? "Hide secret value" : "Show secret value"); } else { const masked = field.dataset.secretMasked !== "false"; field.dataset.secretMasked = masked ? "false" : "true"; field.textContent = masked ? (field.dataset.secretValue || "") : "********"; toggle.textContent = masked ? "Hide" : "View"; toggle.setAttribute("aria-label", masked ? "Hide secret value" : "Show secret value"); } return; } const button = event.target.closest("[data-copy]"); if (!button) return; const menu = button.closest("details.copy-menu"); try { const copied = await copyText(button.dataset.copy || ""); if (!copied) throw new Error("copy failed"); showCopyStatus(button, "Copied", "is-copied"); if (menu) { setTimeout(() => { menu.removeAttribute("open"); }, 250); } } catch (_) { showCopyStatus(button, "Copy failed", "is-copy-error", 1800); } }); document.addEventListener("keydown", (event) => { if (event.key !== "Escape") return; document.querySelectorAll("details.copy-menu[open]").forEach((menu) => { menu.removeAttribute("open"); }); });