85 lines
2.7 KiB
TypeScript
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);
|
||
|
|
}
|