rojects/src/components/confirm-dialog/confirm-dialog.ts

85 lines
2.7 KiB
TypeScript

export interface ConfirmDialogOptions {
icon?: string;
title: string;
message: string;
confirmLabel?: string;
cancelLabel?: string;
danger?: boolean;
}
class ConfirmDialog extends HTMLElement {
private resolver: ((value: boolean) => void) | null = null;
connectedCallback(): void {
this.style.display = 'none';
this.innerHTML = `
<div class="cd-backdrop"></div>
<div class="cd-box" role="dialog" aria-modal="true">
<div class="cd-titlebar">
<span class="cd-icon"></span>
<span class="cd-title"></span>
<button class="cd-close" title="Close">✕</button>
</div>
<div class="cd-body">
<p class="cd-message"></p>
</div>
<div class="cd-footer"></div>
</div>
`;
this.querySelector('.cd-backdrop')!.addEventListener('click', () => this.close(false));
this.querySelector('.cd-close')!.addEventListener('click', () => this.close(false));
document.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape' && this.style.display !== 'none') this.close(false);
});
}
show(options: ConfirmDialogOptions): Promise<boolean> {
console.log( "Show dialog" );
this.querySelector('.cd-icon')!.textContent = options.icon ?? '';
this.querySelector('.cd-title')!.textContent = options.title;
this.querySelector('.cd-message')!.textContent = options.message;
const footer = this.querySelector('.cd-footer')!;
footer.innerHTML = '';
if (options.cancelLabel) {
const cancel = document.createElement('button');
cancel.className = 'cd-btn cd-btn-cancel';
cancel.textContent = options.cancelLabel;
cancel.addEventListener('click', () => this.close(false));
footer.appendChild(cancel);
}
const confirm = document.createElement('button');
confirm.className = `cd-btn cd-btn-confirm${options.danger ? ' cd-btn-danger' : ''}`;
confirm.textContent = options.confirmLabel ?? 'OK';
confirm.addEventListener('click', () => this.close(true));
footer.appendChild(confirm);
this.style.display = '';
confirm.focus();
return new Promise<boolean>(resolve => { this.resolver = resolve; });
}
private close(value: boolean): void {
this.style.display = 'none';
console.log( "Closing:", value );
if (this.resolver) { this.resolver(value); this.resolver = null; }
}
}
customElements.define('confirm-dialog', ConfirmDialog);
export function showConfirmDialog(options: ConfirmDialogOptions): Promise<boolean> {
let dialog = document.querySelector('confirm-dialog') as ConfirmDialog | null;
if (!dialog) {
dialog = document.createElement('confirm-dialog') as ConfirmDialog;
document.body.appendChild(dialog);
}
return dialog.show(options);
}