/** * upaas - Reusable Alpine.js Components * * Small, self-contained components: copy button, confirm dialog, * auto-dismiss alerts, and relative time display. */ document.addEventListener("alpine:init", () => { // ============================================ // Copy Button Component // ============================================ Alpine.data("copyButton", (targetId) => ({ copied: false, async copy() { const target = document.getElementById(targetId); if (!target) return; const text = target.textContent || target.value; const success = await Alpine.store("utils").copyToClipboard(text); if (success) { this.copied = true; setTimeout(() => { this.copied = false; }, 2000); } }, })); // ============================================ // Confirm Action Component // ============================================ Alpine.data("confirmAction", (message) => ({ confirm(event) { if (!window.confirm(message)) { event.preventDefault(); } }, })); // ============================================ // Auto-dismiss Alert Component // ============================================ Alpine.data("autoDismiss", (delay = 5000) => ({ show: true, init() { setTimeout(() => { this.dismiss(); }, delay); }, dismiss() { this.show = false; setTimeout(() => { this.$el.remove(); }, 300); }, })); // ============================================ // Relative Time Component // ============================================ Alpine.data("relativeTime", (isoTime) => ({ display: "", init() { this.update(); // Update every minute setInterval(() => this.update(), 60000); }, update() { this.display = Alpine.store("utils").formatRelativeTime(isoTime); }, })); });