UNPKG

@lucsoft/webgen

Version:

Collection of lucsofts Components

106 lines (105 loc) 4.36 kB
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(); } }