feat: introduce overlay dialog component
This commit is contained in:
126
public/scripts/components/OverlayDialogComponent.js
Normal file
126
public/scripts/components/OverlayDialogComponent.js
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user