@lucsoft/webgen
Version:
Collection of lucsofts Components
106 lines (105 loc) • 4.36 kB
JavaScript
import { custom, draw, span } from "../components/Components";
import { Button } from "../components/generic/Button";
import { Horizontal } from "../components/generic/Stacks";
import '../css/dialog.webgen.static.css';
import { View } from "./View";
const dialogShell = custom('div', undefined, 'dialog-shell');
document.body.append(dialogShell);
export function Dialog(render) {
const dialogBackdrop = custom('div', undefined, 'dialog-backdrop');
dialogShell.append(dialogBackdrop);
let isLoading = false;
let onCloseAction = null;
let title = null;
let firstRun = true;
let allowUserClose = false;
const dialog = custom('div', undefined, 'dialog');
let view = View(render)
.addClass('dialog-content')
.appendOn(dialog);
document.addEventListener('keyup', closeDialogFromKeyboard);
dialogBackdrop.addEventListener('click', closeDialogFromBackdrop);
const buttons = [];
const settings = {
addButton: (label, action, color = "grayscaled" /* Grayscaled */, state) => {
buttons.push({ label, action, color, state });
return settings;
},
addClass: (...classes) => { dialog.classList.add(...classes); return settings; },
setTitle: (text) => { title = text; return settings; },
allowUserClose: () => {
allowUserClose = true;
return settings;
},
onClose: (action) => {
onCloseAction = action;
return settings;
},
remove: () => {
document.removeEventListener('keyup', closeDialogFromKeyboard);
dialogBackdrop.removeEventListener('click', closeDialogFromBackdrop);
dialogBackdrop.remove();
},
close: () => {
dialogBackdrop.classList.remove('open');
document.body.style.overflowY = "unset";
onCloseAction?.();
return settings;
},
unsafeViewOptions: () => {
return view.unsafeViewOptions();
},
open: () => {
if (firstRun) {
if (title)
dialog.prepend(span(title, 'dialog-title'));
if (buttons.length > 0) {
const list = draw(Horizontal({ align: 'flex-end', margin: "0.7rem", gap: "0.5rem" }, ...buttons.map(({ action, color, label, state }, i) => Button({
text: label,
state: state ?? (buttons.length - 1 == i ? "normal" /* Normal */ : "inline" /* Inline */),
color,
pressOn: async ({ changeState }) => {
if (isLoading)
return;
isLoading = true;
if (action === 'close')
settings.close();
else if (action === 'remove')
settings.close().remove();
else {
changeState("spinner" /* Spinner */);
const data = await action();
if (data !== undefined)
settings.close();
if (data === "remove")
settings.remove();
changeState(state ?? (buttons.length - 1 == i ? "normal" /* Normal */ : "inline" /* Inline */));
}
isLoading = false;
}
}))));
dialog.append(list);
}
firstRun = false;
dialogBackdrop.append(dialog);
}
dialogBackdrop.classList.add('open');
document.body.style.overflowY = "hidden";
return settings;
}
};
return settings;
function closeDialogFromBackdrop(e) {
if (!allowUserClose)
return;
if (e.target != dialogBackdrop || isLoading)
return;
settings.close();
}
function closeDialogFromKeyboard(e) {
if (!allowUserClose)
return;
if (e.key == "Escape" && dialogBackdrop.classList.contains('open') && !isLoading)
settings.close();
}
}