Files
ausboss-ComfyUI-AusBoss/js/shared/discard_prompt.mjs
T
ausboss 235225000c Editors: Cancel with a discard-changes prompt
The Crop + Rotate + Pad editor gains Cancel beside Save & close; Escape
now cancels. Changed edits ask first (shared js/shared/discard_prompt.mjs)
and Discard restores the node to its state when the editor opened. The
Workflow Note editor asks before Cancel, Escape or a backdrop click drops
edits, and a JSON edit carried back to the form no longer outlives Cancel.
2026-09-26 17:59:48 -05:00

85 lines
4.1 KiB
JavaScript

// Shared "discard changes?" prompt for the pack's large editors. Closing an
// editor without saving must never lose edits silently: every editor with
// a Cancel path asks this first when something changed. In-page, never
// window.confirm - it matches the editors and keeps keys away from the canvas.
//
// Resolves true when the user chose to discard, false to keep editing.
// "Keep editing" is the focused default, so a stray Enter or Escape is safe.
import { BRAND } from "./index.mjs";
const STYLE_ID = "ausboss-discard-prompt-style";
function ensureCss() {
if (document.getElementById(STYLE_ID)) return;
const style = document.createElement("style");
style.id = STYLE_ID;
style.textContent = `
.ausboss-discard-backdrop{position:fixed;inset:0;z-index:100010;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.5)}
.ausboss-discard-box{width:min(360px,92vw);padding:16px;border:1px solid #3a4047;border-radius:9px;background:#1c1f23;box-shadow:0 12px 40px rgba(0,0,0,.6);color:#d7dde2;font:13px/1.45 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
.ausboss-discard-box strong{display:block;margin:0 0 6px;color:#fff;font-size:14px}
.ausboss-discard-box p{margin:0 0 14px;color:#9ba2aa}
.ausboss-discard-actions{display:flex;justify-content:flex-end;gap:8px}
.ausboss-discard-actions button{height:28px;padding:0 12px;border:1px solid #3a4047;border-radius:5px;background:#23272c;color:#d7dde2;font:12px/1 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;cursor:pointer}
.ausboss-discard-actions button:hover,.ausboss-discard-actions button:focus-visible{border-color:${BRAND};color:#fff;outline:none}
.ausboss-discard-actions button.danger{background:#4a1717;border-color:#a13a3a;color:#ffd9d9}
.ausboss-discard-actions button.danger:hover,.ausboss-discard-actions button.danger:focus-visible{background:#6b1f1f;border-color:#c74e4e;color:#fff}
`;
document.head.appendChild(style);
}
export function confirmDiscard({
title = "Discard changes?",
detail = "You have unsaved changes. Closing without saving puts everything back the way it was when the editor opened.",
} = {}) {
ensureCss();
return new Promise((resolve) => {
const backdrop = document.createElement("div");
backdrop.className = "ausboss-discard-backdrop";
const box = document.createElement("div");
box.className = "ausboss-discard-box";
box.setAttribute("role", "alertdialog");
box.setAttribute("aria-modal", "true");
const heading = document.createElement("strong");
heading.textContent = title;
const text = document.createElement("p");
text.textContent = detail;
const actions = document.createElement("div");
actions.className = "ausboss-discard-actions";
const keep = document.createElement("button");
keep.type = "button";
keep.textContent = "Keep editing";
const discard = document.createElement("button");
discard.type = "button";
discard.className = "danger";
discard.textContent = "Discard changes";
actions.append(keep, discard);
box.append(heading, text, actions);
backdrop.append(box);
const previousFocus = document.activeElement;
const finish = (answer) => {
backdrop.remove();
previousFocus?.focus?.({ preventScroll: true });
resolve(answer);
};
keep.addEventListener("click", () => finish(false));
discard.addEventListener("click", () => finish(true));
// The prompt owns the keyboard while it is up: nothing reaches the
// editor underneath or the canvas shortcuts.
backdrop.addEventListener("keydown", (event) => {
event.stopPropagation();
if (event.key === "Escape") { event.preventDefault(); finish(false); }
if (event.key === "Tab") { event.preventDefault(); (document.activeElement === keep ? discard : keep).focus(); }
});
backdrop.addEventListener("keyup", (event) => event.stopPropagation());
backdrop.addEventListener("pointerdown", (event) => {
event.stopPropagation();
if (event.target === backdrop) finish(false);
});
backdrop.addEventListener("wheel", (event) => event.stopPropagation());
document.body.append(backdrop);
keep.focus();
});
}