Spaces:
Sleeping
Sleeping
File size: 5,908 Bytes
4bea261 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | /**
* TxaModal - Premium Modal System
* Migration: TPHIMX V2 (Vite Compatible)
*/
export class TxaModal {
constructor() {
this.containerCreated = false;
this.container = null;
this.overlay = null;
this.modal = null;
}
createContainer() {
if (this.containerCreated && document.getElementById('txamodal-container')) {
this.container = document.getElementById('txamodal-container');
this.overlay = document.getElementById('txamodal-overlay');
this.modal = document.getElementById('txamodal-content');
return true;
}
const container = document.createElement('div');
container.id = 'txamodal-container';
container.style.cssText = `position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; align-items: center; justify-content: center; z-index: 2147483640; padding: 20px;`;
const overlay = document.createElement('div');
overlay.id = 'txamodal-overlay';
overlay.style.cssText = `position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(10, 15, 25, 0.7); backdrop-filter: blur(12px); opacity: 0; transition: opacity 0.3s ease;`;
const modal = document.createElement('div');
modal.id = 'txamodal-content';
modal.style.cssText = `position: relative; background: rgba(30, 41, 59, 0.7); backdrop-filter: blur(24px); width: 100%; max-width: 500px; border-radius: 28px; border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.8); transform: scale(0.9) translateY(30px); opacity: 0; transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); overflow: hidden; display: flex; flex-direction: column;`;
container.appendChild(overlay);
container.appendChild(modal);
document.body.appendChild(container);
this.container = container;
this.overlay = overlay;
this.modal = modal;
this.containerCreated = true;
return true;
}
show({ title, message, type = 'info', confirmText = 'Xác nhận', cancelText = 'Hủy', onConfirm = null, onCancel = null, input = null, inputPlaceholder = '', inputType = 'text' }) {
if (!this.createContainer()) return;
let icon = '<i class="fas fa-info-circle text-indigo-500"></i>';
let btnConfirmStyle = 'background: linear-gradient(135deg, #6366f1, #a855f7); color: #fff;';
if (type === 'danger') {
icon = '<i class="fas fa-exclamation-triangle text-red-500"></i>';
btnConfirmStyle = 'background: #ef4444; color: #fff;';
} else if (type === 'warning') {
icon = '<i class="fas fa-exclamation-circle text-amber-500"></i>';
btnConfirmStyle = 'background: linear-gradient(135deg, #f59e0b, #ea580c); color: #fff;';
} else if (type === 'success') {
icon = '<i class="fas fa-check-circle text-emerald-500"></i>';
btnConfirmStyle = 'background: #10b981; color: #fff;';
}
let inputHtml = '';
if (input) {
inputHtml = `
<div style="margin-top: 24px;">
<input id="txamodal-input" type="${inputType}" placeholder="${inputPlaceholder}"
style="width: 100%; background: rgba(0,0,0,0.4); border: 1px solid rgba(255,255,255,0.1); padding: 14px 20px; border-radius: 16px; color: #fff; outline: none; font-family: inherit;">
</div>
`;
}
this.modal.innerHTML = `
<div style="padding: 40px 30px; text-align: center;">
<div style="font-size: 64px; margin-bottom: 24px;">${icon}</div>
<h3 style="margin: 0 0 16px 0; font-size: 24px; font-weight: 800; color: #fff;">${title}</h3>
<div style="color: #94a3b8; line-height: 1.6;">${message}</div>
${inputHtml}
</div>
<div style="padding: 24px 30px; background: rgba(0, 0, 0, 0.3); display: flex; gap: 12px;">
<button id="txamodal-cancel" style="flex: 1; padding: 14px; border-radius: 16px; border: 1px solid rgba(255, 255, 255, 0.1); background: rgba(255, 255, 255, 0.05); color: #94a3b8; font-weight: 600; cursor: pointer; transition: all 0.2s;">${cancelText}</button>
<button id="txamodal-confirm" style="flex: 1; padding: 14px; border-radius: 16px; border: none; ${btnConfirmStyle} font-weight: 700; cursor: pointer; transition: all 0.2s; box-shadow: 0 4px 15px rgba(0,0,0,0.3);">${confirmText}</button>
</div>
`;
this.container.style.display = 'flex';
setTimeout(() => {
this.overlay.style.opacity = '1';
this.modal.style.opacity = '1';
this.modal.style.transform = 'scale(1) translateY(0)';
if (input) document.getElementById('txamodal-input').focus();
}, 10);
document.getElementById('txamodal-confirm').onclick = async () => {
let result = true;
if (input) {
const val = document.getElementById('txamodal-input').value;
if (onConfirm) result = await onConfirm(val);
} else {
if (onConfirm) result = await onConfirm();
}
if (result !== false) this.hide();
};
document.getElementById('txamodal-cancel').onclick = () => {
if (typeof onCancel === 'function') {
try { onCancel(); } catch (_) { /* noop */ }
}
this.hide();
};
}
hide() {
if (!this.container) return;
this.overlay.style.opacity = '0';
this.modal.style.opacity = '0';
this.modal.style.transform = 'scale(0.95) translateY(20px)';
setTimeout(() => { this.container.style.display = 'none'; }, 400);
}
}
window.txamodal = new TxaModal();
|