// Form component utilities and Alpine.js data export function formComponentsData() { return { // Modal states showAlertModal: false, showConfirmModal: false, showContentModal: false, // Toast notification state toasts: [], // Handle confirm modal action handleConfirm() { this.showConfirmModal = false; this.showToast('success', 'Action confirmed!'); }, // Show toast notification showToast(type = 'success', message = null) { const messages = { success: 'Operation completed successfully!', error: 'An error occurred. Please try again.', info: 'Here is some information.', warning: 'Please be careful with this action.' }; const toastMessage = message || messages[type] || messages.success; const toastId = Date.now(); // Add toast to list this.toasts.push({ id: toastId, type: type, message: toastMessage }); // Auto-remove after 5 seconds setTimeout(() => { this.toasts = this.toasts.filter(t => t.id !== toastId); }, 5000); }, // Remove toast manually removeToast(id) { this.toasts = this.toasts.filter(t => t.id !== id); }, // Form validation utilities validateEmail(email) { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(email); }, validatePassword(password) { return password.length >= 8; }, // Auto-expand textarea autoExpandTextarea(event) { const textarea = event.target; textarea.style.height = 'auto'; textarea.style.height = (textarea.scrollHeight) + 'px'; } }; } // Toast container component for Alpine.js export function renderToastContainer(Alpine) { if (!Alpine) return; // This can be used in templates via Alpine window.formUtils = { formatCharCount(current, max) { if (max) { return `${current}/${max}`; } return current; }, isCharCountWarning(current, max) { if (!max) return false; return current > (max * 0.8); }, isCharCountError(current, max) { if (!max) return false; return current >= max; } }; } // Focus Trap for Modals - Week 5 function createFocusTrap(modalElement) { const focusableElements = modalElement.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); if (focusableElements.length === 0) return; const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; modalElement.addEventListener('keydown', (e) => { if (e.key !== 'Tab') return; if (e.shiftKey) { // Shift + Tab if (document.activeElement === firstElement) { e.preventDefault(); lastElement.focus(); } } else { // Tab if (document.activeElement === lastElement) { e.preventDefault(); firstElement.focus(); } } }); // Set initial focus firstElement.focus(); } // Export for use in Alpine.js window.createFocusTrap = createFocusTrap;