@selenite/commons
Version:
This typescript package provides a set of frequently used utilities, types and svelte actions for building projects with Typescript and Svelte.
111 lines (110 loc) • 3.51 kB
JavaScript
export const modalButtonTypes = ['cancel', 'promptConfirm', 'close', 'submit'];
export function isComponentModalSettings(modal) {
return 'component' in modal;
}
export function isSnippetModalSettings(modal) {
return 'snippet' in modal;
}
export function isPromptModalSettings(modal) {
return 'prompt' in modal;
}
export function modalButtonTypeToButton(type) {
switch (type) {
case 'cancel':
return {
label: 'Cancel',
onclick: () => modals.close()
};
case 'close':
return {
label: 'Close',
level: 'neutral',
onclick: () => modals.close()
};
case 'submit':
return {
label: 'Submit',
level: 'primary',
onclick: async () => {
const contentContainer = Modal.instance.contentContainer;
if (contentContainer) {
const forms = contentContainer.querySelectorAll('form');
for (const form of forms)
if (!form.reportValidity())
return;
}
const r = await Modal.instance.childComponent?.getResponse?.();
Modal.instance.lastModal?.response?.(r);
modals.close();
}
};
case 'promptConfirm':
return {
label: 'Confirm',
level: 'primary',
onclick: () => {
Modal.instance.lastModal?.response?.(Modal.instance.promptInput?.value);
modals.close();
}
};
}
}
/**
* Singleton that manages modals.
*
* The singleton can be accessed with `Modal.instance`.
*/
export class Modal {
static #instance;
static get instance() {
if (!this.#instance) {
this.#instance = new Modal();
}
return this.#instance;
}
queue = $state([]);
lastModal = $derived(this.queue.at(-1));
promptInput = $state();
contentContainer = $state();
childComponent = $state();
resolvedButtons = $derived(this.lastModal?.buttons === undefined
? undefined
: this.lastModal.buttons.map((btn) => {
if (typeof btn === 'string') {
return modalButtonTypeToButton(btn);
}
if ('type' in btn) {
return {
...modalButtonTypeToButton(btn.type),
...btn
};
}
if ('formId' in btn) {
return {
label: 'Submit',
level: 'primary',
onclick: () => {
const form = document.getElementById(btn.formId);
if (form) {
form.requestSubmit();
}
}
};
}
return btn;
}));
constructor() { }
show(params) {
console.debug('Show modal', params);
if ('prompt' in params) {
params.buttons = params.buttons || ['cancel', 'promptConfirm'];
params.title = params.title || params.prompt;
}
this.queue.push(params);
}
close() {
console.debug('Close modal');
this.queue.pop();
}
}
export const modals = Modal.instance;