Files
DemonGatanjieu-Anomalous_Mo…/web/modules/ui_dialog.js
T
DemonGatanjieuandClaude Opus 5.5 054cb91b9b style: one palette for every page, from the theme tokens
Pages made at different times used their own greys (slate here, neutral
there) and accents (sky, violet, indigo), and most ignored the Abyssal
Scarlet theme. About 1,850 literal colours in web/styles and in CSS and
inline styles written from JS now use the --amb-* tokens by what they are
for: surfaces, text (new --amb-text-soft and --amb-text-dim), borders (new
--amb-border-strong), the primary button, and one accent (new --amb-link,
tinted with color-mix). Both themes define the new tokens.

Literal colours stay where the colour is the meaning: status, prompt
roles, voice emotions, canvas node colours, shadows and overlays; theme
override rules are untouched. The share-code dialogs move from inline
styles to .anomalous-share-* classes. Stylesheet versions are bumped.

Checked: text contrast on every rail page, Prompt Studio, Prompt Notes,
Model Sources, settings, model detail and editor, share codes, in both
themes; structure check and JS tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:19:55 +08:00

263 lines
10 KiB
JavaScript

import { translate } from './locales.js';
const t = (key, params) => translate(key, params);
// Confirmations must remain above the image workbench (z-index: 1000000).
const DIALOG_Z_INDEX = '1000001';
export function anomalousAlert(message, title = 'Anomalous') {
return new Promise((resolve) => {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.inset = '0';
overlay.className = 'anomalous-dialog-overlay';
overlay.style.zIndex = DIALOG_Z_INDEX;
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.background = 'rgba(0, 0, 0, 0.6)';
overlay.style.backdropFilter = 'blur(4px)';
overlay.style.padding = '20px';
overlay.style.boxSizing = 'border-box';
const dialog = document.createElement('div');
dialog.style.background = 'linear-gradient(145deg, rgba(48, 49, 55, 0.98), rgba(27, 28, 33, 0.98))';
dialog.style.border = '1px solid var(--amb-border-strong)';
dialog.style.borderRadius = '16px';
dialog.style.padding = '24px';
dialog.style.maxWidth = '400px';
dialog.style.width = '100%';
dialog.style.maxHeight = '90vh';
dialog.style.overflowY = 'auto';
dialog.style.boxShadow = '0 24px 70px rgba(0, 0, 0, 0.55)';
dialog.style.color = '#f3f4f6';
dialog.style.display = 'flex';
dialog.style.flexDirection = 'column';
dialog.style.gap = '16px';
const heading = document.createElement('h3');
heading.textContent = title;
heading.style.margin = '0';
heading.style.fontSize = '1.25rem';
const text = document.createElement('p');
text.textContent = message;
text.style.margin = '0';
text.style.lineHeight = '1.5';
text.style.whiteSpace = 'pre-wrap';
text.style.color = '#ccc';
const footer = document.createElement('div');
footer.style.display = 'flex';
footer.style.justifyContent = 'flex-end';
footer.style.marginTop = '8px';
const okBtn = document.createElement('button');
okBtn.textContent = t('dialogOk');
okBtn.className = 'anomalous-btn-primary';
okBtn.style.padding = '8px 24px';
const cleanup = () => {
overlay.remove();
resolve();
};
okBtn.onclick = cleanup;
footer.appendChild(okBtn);
dialog.append(heading, text, footer);
overlay.appendChild(dialog);
document.body.appendChild(overlay);
okBtn.focus();
});
}
export function anomalousConfirm(message, title = 'Anomalous', options = {}) {
return new Promise((resolve) => {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.inset = '0';
overlay.className = 'anomalous-dialog-overlay';
overlay.style.zIndex = DIALOG_Z_INDEX;
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.background = 'rgba(0, 0, 0, 0.6)';
overlay.style.backdropFilter = 'blur(4px)';
overlay.style.padding = '20px';
overlay.style.boxSizing = 'border-box';
const dialog = document.createElement('div');
dialog.style.background = 'linear-gradient(145deg, rgba(48, 49, 55, 0.98), rgba(27, 28, 33, 0.98))';
dialog.style.border = '1px solid var(--amb-border-strong)';
dialog.style.borderRadius = '16px';
dialog.style.padding = '24px';
dialog.style.maxWidth = '400px';
dialog.style.width = '100%';
dialog.style.maxHeight = '90vh';
dialog.style.overflowY = 'auto';
dialog.style.boxShadow = '0 24px 70px rgba(0, 0, 0, 0.55)';
dialog.style.color = '#f3f4f6';
dialog.style.display = 'flex';
dialog.style.flexDirection = 'column';
dialog.style.gap = '16px';
const heading = document.createElement('h3');
heading.textContent = title;
heading.style.margin = '0';
heading.style.fontSize = '1.25rem';
const text = document.createElement('p');
text.textContent = message;
text.style.margin = '0';
text.style.lineHeight = '1.5';
text.style.whiteSpace = 'pre-wrap';
text.style.color = '#ccc';
const footer = document.createElement('div');
footer.style.display = 'flex';
footer.style.justifyContent = 'flex-end';
footer.style.gap = '12px';
footer.style.marginTop = '8px';
const cancelBtn = document.createElement('button');
cancelBtn.textContent = options.cancelLabel || t('dialogCancel');
cancelBtn.className = 'anomalous-btn-ghost';
cancelBtn.style.padding = '8px 24px';
const okBtn = document.createElement('button');
okBtn.textContent = options.okLabel || t('dialogOk');
okBtn.className = 'anomalous-btn-danger';
okBtn.style.padding = '8px 24px';
const noBtn = options.noLabel ? document.createElement('button') : null;
if (noBtn) {
noBtn.textContent = options.noLabel;
noBtn.className = 'anomalous-btn-ghost';
noBtn.style.padding = '8px 24px';
}
const finish = (result) => {
overlay.remove();
resolve(result);
};
cancelBtn.onclick = () => finish(null);
noBtn?.addEventListener('click', () => finish(false));
okBtn.onclick = () => finish(true);
footer.append(cancelBtn);
if (noBtn) footer.append(noBtn);
footer.append(okBtn);
dialog.append(heading, text, footer);
overlay.appendChild(dialog);
document.body.appendChild(overlay);
cancelBtn.focus();
});
}
export function anomalousPrompt(message, defaultValue = '', title = 'Anomalous', options = {}) {
return new Promise((resolve) => {
const overlay = document.createElement('div');
overlay.style.position = 'fixed';
overlay.style.inset = '0';
overlay.className = 'anomalous-dialog-overlay';
overlay.style.zIndex = DIALOG_Z_INDEX;
overlay.style.display = 'flex';
overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center';
overlay.style.background = 'rgba(0, 0, 0, 0.6)';
overlay.style.backdropFilter = 'blur(4px)';
overlay.style.padding = '20px';
overlay.style.boxSizing = 'border-box';
const dialog = document.createElement('div');
dialog.style.background = 'linear-gradient(145deg, rgba(48, 49, 55, 0.98), rgba(27, 28, 33, 0.98))';
dialog.style.border = '1px solid var(--amb-border-strong)';
dialog.style.borderRadius = '16px';
dialog.style.padding = '24px';
dialog.style.maxWidth = '420px';
dialog.style.width = '100%';
dialog.style.boxShadow = '0 24px 70px rgba(0, 0, 0, 0.55)';
dialog.style.color = '#f3f4f6';
dialog.style.display = 'flex';
dialog.style.flexDirection = 'column';
dialog.style.gap = '16px';
const heading = document.createElement('h3');
heading.textContent = title;
heading.style.margin = '0';
heading.style.fontSize = '1.25rem';
const text = document.createElement('p');
text.textContent = message;
text.style.margin = '0';
text.style.lineHeight = '1.5';
text.style.color = '#ccc';
const input = document.createElement(options.multiline ? 'textarea' : 'input');
if (!options.multiline) input.type = 'text';
input.value = defaultValue;
input.maxLength = options.maxLength || 200;
if (options.multiline) input.rows = options.rows || 6;
input.style.width = '100%';
input.style.padding = '10px 14px';
input.style.borderRadius = '8px';
input.style.border = '1px solid var(--amb-border-strong)';
input.style.background = 'rgba(0, 0, 0, 0.35)';
input.style.color = '#fff';
input.style.fontSize = '14px';
input.style.boxSizing = 'border-box';
input.style.outline = 'none';
if (options.multiline) input.style.resize = 'vertical';
input.onfocus = () => input.style.borderColor = '#1a73e8';
input.onblur = () => input.style.borderColor = 'var(--amb-border-strong)';
const footer = document.createElement('div');
footer.style.display = 'flex';
footer.style.justifyContent = 'flex-end';
footer.style.gap = '12px';
footer.style.marginTop = '8px';
const cancelBtn = document.createElement('button');
cancelBtn.textContent = t('dialogCancel');
cancelBtn.className = 'anomalous-btn-ghost';
cancelBtn.style.padding = '8px 24px';
const okBtn = document.createElement('button');
okBtn.textContent = t('dialogOk');
okBtn.className = 'anomalous-btn-primary';
okBtn.style.padding = '8px 24px';
const finish = (result) => {
overlay.remove();
resolve(result);
};
cancelBtn.onclick = () => finish(null);
okBtn.onclick = () => {
const val = input.value.trim();
finish(val);
};
input.onkeydown = (e) => {
if (e.key === 'Enter' && (!options.multiline || e.ctrlKey || e.metaKey)) {
e.preventDefault();
okBtn.click();
} else if (e.key === 'Escape') {
e.preventDefault();
cancelBtn.click();
}
};
footer.append(cancelBtn, okBtn);
dialog.append(heading, text, input, footer);
overlay.appendChild(dialog);
document.body.appendChild(overlay);
setTimeout(() => {
input.focus();
input.select();
}, 50);
});
}