feat: introduce overlay dialog component

This commit is contained in:
2025-10-16 22:00:19 +02:00
parent 478d23b805
commit 79a28bae22
7 changed files with 584 additions and 25 deletions

View File

@@ -0,0 +1,126 @@
// Overlay Dialog Component - Reusable confirmation dialog
class OverlayDialogComponent extends Component {
constructor(container, viewModel, eventBus) {
super(container, viewModel, eventBus);
this.isVisible = false;
this.onConfirm = null;
this.onCancel = null;
this.title = '';
this.message = '';
this.confirmText = 'Yes';
this.cancelText = 'No';
}
mount() {
super.mount();
this.setupEventListeners();
}
setupEventListeners() {
// Close overlay when clicking outside or pressing escape
this.addEventListener(this.container, 'click', (e) => {
if (!this.isVisible) return;
if (e.target === this.container) {
this.hide();
}
});
this.addEventListener(document, 'keydown', (e) => {
if (e.key === 'Escape' && this.isVisible) {
this.hide();
}
});
}
show(options = {}) {
const {
title = 'Confirm Action',
message = 'Are you sure you want to proceed?',
confirmText = 'Yes',
cancelText = 'No',
onConfirm = null,
onCancel = null
} = options;
this.title = title;
this.message = message;
this.confirmText = confirmText;
this.cancelText = cancelText;
this.onConfirm = onConfirm;
this.onCancel = onCancel;
this.render();
this.container.classList.add('visible');
this.isVisible = true;
}
hide() {
this.container.classList.remove('visible');
this.isVisible = false;
// Call cancel callback if provided
if (this.onCancel) {
this.onCancel();
}
}
handleConfirm() {
this.hide();
// Call confirm callback if provided
if (this.onConfirm) {
this.onConfirm();
}
}
render() {
this.container.innerHTML = `
<div class="overlay-dialog-content">
<div class="overlay-dialog-header">
<h3 class="overlay-dialog-title">${this.title}</h3>
<button class="overlay-dialog-close" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20">
<path d="M18 6L6 18M6 6l12 12"/>
</svg>
</button>
</div>
<div class="overlay-dialog-body">
<div class="overlay-dialog-message">${this.message}</div>
</div>
<div class="overlay-dialog-footer">
<button class="overlay-dialog-btn overlay-dialog-btn-cancel" type="button">
${this.cancelText}
</button>
<button class="overlay-dialog-btn overlay-dialog-btn-confirm" type="button">
${this.confirmText}
</button>
</div>
</div>
`;
// Add event listeners to buttons
const closeBtn = this.container.querySelector('.overlay-dialog-close');
const cancelBtn = this.container.querySelector('.overlay-dialog-btn-cancel');
const confirmBtn = this.container.querySelector('.overlay-dialog-btn-confirm');
if (closeBtn) {
this.addEventListener(closeBtn, 'click', () => this.hide());
}
if (cancelBtn) {
this.addEventListener(cancelBtn, 'click', () => this.hide());
}
if (confirmBtn) {
this.addEventListener(confirmBtn, 'click', () => this.handleConfirm());
}
}
unmount() {
// Clean up event listeners
this.removeAllEventListeners();
// Call parent unmount
super.unmount();
}
}