Spaces:
Sleeping
Sleeping
| /** | |
| * 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(); | |