fix command page buttons
This commit is contained in:
parent
4c1c23bd27
commit
0cf7408225
1
TODO.md
1
TODO.md
@ -125,6 +125,7 @@ This file tracks larger Lumi work that cannot safely be completed in one pass. K
|
||||
|
||||
## Done
|
||||
|
||||
- 2026-06-17: Fixed custom command Edit buttons and `/commands` Copy Link / expand buttons with delegated handlers, clipboard fallback, and v0.1.5 patch bump.
|
||||
- 2026-06-17: Fixed repo-based core updates deleting `data/update-cache/repo` during apply, added a verification guard, and bumped core package version to v0.1.4.
|
||||
- 2026-06-17: Bumped core package version to v0.1.3.
|
||||
- 2026-06-17: Completed homepage hero embed pass for Discord widgets, YouTube video playback options, external embed fallback/sandbox controls, admin validation, platform-specific fields, and Test preview behavior.
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "lumi-bot",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "lumi-bot",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.5.12",
|
||||
"better-sqlite3": "^11.5.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lumi-bot",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
|
||||
@ -57,35 +57,36 @@
|
||||
}
|
||||
});
|
||||
|
||||
const editToggles = Array.from(
|
||||
document.querySelectorAll("[data-edit-toggle]")
|
||||
);
|
||||
if (editToggles.length) {
|
||||
const editRows = Array.from(document.querySelectorAll("[data-edit-row]"));
|
||||
const updateToggleStates = () => {
|
||||
editToggles.forEach((button) => {
|
||||
const selectorEscape = (value) => {
|
||||
if (window.CSS?.escape) return CSS.escape(value);
|
||||
return String(value || "").replace(/["\\]/g, "\\$&");
|
||||
};
|
||||
|
||||
const updateEditToggleStates = () => {
|
||||
document.querySelectorAll("[data-edit-toggle]").forEach((button) => {
|
||||
const key = button.dataset.editToggle;
|
||||
const row = editRows.find((item) => item.dataset.editRow === key);
|
||||
const row = key ? document.querySelector(`[data-edit-row="${selectorEscape(key)}"]`) : null;
|
||||
const isOpen = row?.classList.contains("is-open");
|
||||
button.setAttribute("aria-expanded", isOpen ? "true" : "false");
|
||||
});
|
||||
};
|
||||
|
||||
editToggles.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
document.addEventListener("click", (event) => {
|
||||
const button = event.target.closest("[data-edit-toggle]");
|
||||
if (!button) return;
|
||||
event.preventDefault();
|
||||
const key = button.dataset.editToggle;
|
||||
const target = editRows.find((item) => item.dataset.editRow === key);
|
||||
const target = key ? document.querySelector(`[data-edit-row="${selectorEscape(key)}"]`) : null;
|
||||
const willOpen = target ? !target.classList.contains("is-open") : false;
|
||||
editRows.forEach((row) => {
|
||||
document.querySelectorAll("[data-edit-row].is-open").forEach((row) => {
|
||||
row.classList.remove("is-open");
|
||||
});
|
||||
if (target && willOpen) {
|
||||
target.classList.add("is-open");
|
||||
}
|
||||
updateToggleStates();
|
||||
updateEditToggleStates();
|
||||
});
|
||||
});
|
||||
}
|
||||
updateEditToggleStates();
|
||||
|
||||
document.querySelectorAll("[data-table]").forEach((table) => {
|
||||
const tbody = table.tBodies[0];
|
||||
@ -198,8 +199,11 @@
|
||||
setGroupExpanded(group, false);
|
||||
});
|
||||
|
||||
tbody.querySelectorAll("[data-command-toggle]").forEach((button) => {
|
||||
button.addEventListener("click", (event) => {
|
||||
tbody.addEventListener("click", (event) => {
|
||||
const button = event.target.closest("[data-command-toggle]");
|
||||
if (!button || !tbody.contains(button)) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const rootRow = button.closest("tr");
|
||||
if (!rootRow) {
|
||||
@ -213,7 +217,6 @@
|
||||
const expanded = rootRow.dataset.expanded === "true";
|
||||
setGroupExpanded(group, !expanded);
|
||||
});
|
||||
});
|
||||
|
||||
revealAnchorRow();
|
||||
window.addEventListener("hashchange", () => {
|
||||
@ -864,8 +867,31 @@
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-copy]").forEach((button) => {
|
||||
button.addEventListener("click", async () => {
|
||||
const copyText = async (text) => {
|
||||
if (navigator.clipboard?.writeText && window.isSecureContext) {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
}
|
||||
const tempInput = document.createElement("textarea");
|
||||
tempInput.value = text;
|
||||
tempInput.setAttribute("readonly", "");
|
||||
tempInput.style.position = "fixed";
|
||||
tempInput.style.left = "-9999px";
|
||||
tempInput.style.top = "0";
|
||||
document.body.appendChild(tempInput);
|
||||
tempInput.focus();
|
||||
tempInput.select();
|
||||
try {
|
||||
return document.execCommand("copy");
|
||||
} finally {
|
||||
tempInput.remove();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("click", async (event) => {
|
||||
const button = event.target.closest("[data-copy]");
|
||||
if (!button) return;
|
||||
event.preventDefault();
|
||||
const text = button.getAttribute("data-copy") || "";
|
||||
if (!text) {
|
||||
return;
|
||||
@ -873,41 +899,24 @@
|
||||
const label = button.querySelector("[data-copy-label]");
|
||||
const originalLabel = label ? label.textContent : "";
|
||||
|
||||
const markCopied = () => {
|
||||
button.classList.add("copied");
|
||||
const markCopyResult = (copied) => {
|
||||
button.classList.toggle("copied", copied);
|
||||
button.classList.toggle("copy-failed", !copied);
|
||||
if (label) {
|
||||
label.textContent = "Copied";
|
||||
label.textContent = copied ? "Copied" : "Copy failed";
|
||||
}
|
||||
window.setTimeout(() => {
|
||||
button.classList.remove("copied");
|
||||
button.classList.remove("copied", "copy-failed");
|
||||
if (label) {
|
||||
label.textContent = originalLabel;
|
||||
}
|
||||
}, 1200);
|
||||
}, copied ? 1200 : 1800);
|
||||
};
|
||||
|
||||
try {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
await navigator.clipboard.writeText(text);
|
||||
markCopied();
|
||||
return;
|
||||
}
|
||||
markCopyResult(await copyText(text));
|
||||
} catch {
|
||||
// Fall back to legacy copy.
|
||||
markCopyResult(false);
|
||||
}
|
||||
|
||||
const tempInput = document.createElement("input");
|
||||
tempInput.value = text;
|
||||
document.body.appendChild(tempInput);
|
||||
tempInput.select();
|
||||
try {
|
||||
document.execCommand("copy");
|
||||
markCopied();
|
||||
} catch {
|
||||
// Ignore copy errors.
|
||||
} finally {
|
||||
tempInput.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
@ -777,6 +777,23 @@ body {
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.copy-pill.copy-failed {
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.copy-pill.copy-failed::after {
|
||||
content: "Copy failed";
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: -6px;
|
||||
background: var(--danger);
|
||||
color: white;
|
||||
font-size: 0.65rem;
|
||||
padding: 2px 6px;
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.copy-link {
|
||||
min-width: 96px;
|
||||
justify-content: center;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user