Elysia-Suite's picture
Upload 25 files
0b194e5 verified
/*
ELYSIA MARKDOWN STUDIO v1.0 - Utility Functions
Toast, modals, storage, helpers
*/
const Utils = {
// Toast Notifications
toast: {
show(message, type = "info", duration = 3000) {
const container = document.getElementById("toast-container");
const toast = document.createElement("div");
toast.className = `toast ${type}`;
const icons = {
success: "✅",
error: "❌",
warning: "⚠️",
info: "ℹ️",
loading: "⏳"
};
toast.innerHTML = `
<span class="toast-icon">${icons[type]}</span>
<span class="toast-message">${message}</span>
<button class="toast-close">×</button>
`;
container.appendChild(toast);
const close = () => {
toast.style.animation = "slideOut 0.3s ease";
setTimeout(() => toast.remove(), 300);
};
toast.querySelector(".toast-close").onclick = close;
if (duration > 0) setTimeout(close, duration);
return toast;
},
success: (msg, duration) => Utils.toast.show(msg, "success", duration),
error: (msg, duration) => Utils.toast.show(msg, "error", duration),
warning: (msg, duration) => Utils.toast.show(msg, "warning", duration),
info: (msg, duration) => Utils.toast.show(msg, "info", duration)
},
// Modal Management
modal: {
open(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.add("active");
document.body.style.overflow = "hidden";
}
},
close(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.remove("active");
document.body.style.overflow = "";
}
},
init() {
document.querySelectorAll(".modal").forEach(modal => {
modal.addEventListener("click", e => {
if (e.target === modal) {
Utils.modal.close(modal.id);
}
});
});
document.querySelectorAll(".modal-close, [data-modal]").forEach(btn => {
btn.addEventListener("click", () => {
const modalId = btn.getAttribute("data-modal");
if (modalId) Utils.modal.close(modalId);
});
});
}
},
// Local Storage Wrapper (with encryption for sensitive data)
storage: {
// Simple XOR encryption (basic obfuscation - better than plaintext)
_encrypt(text) {
const key = "ElysiaStudio2025"; // Simple key for obfuscation
let encrypted = "";
for (let i = 0; i < text.length; i++) {
encrypted += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return btoa(encrypted); // Base64 encode
},
_decrypt(encrypted) {
try {
const decoded = atob(encrypted);
const key = "ElysiaStudio2025";
let decrypted = "";
for (let i = 0; i < decoded.length; i++) {
decrypted += String.fromCharCode(decoded.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return decrypted;
} catch {
return null;
}
},
get(key, defaultValue = null) {
try {
const value = localStorage.getItem(key);
if (!value) return defaultValue;
// Decrypt API key if it's stored
if (key === "apiKey") {
const decrypted = this._decrypt(value);
return decrypted || defaultValue;
}
return JSON.parse(value);
} catch {
return defaultValue;
}
},
set(key, value) {
try {
// Encrypt API key before storing
if (key === "apiKey" && value) {
localStorage.setItem(key, this._encrypt(value));
return true;
}
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch {
return false;
}
},
remove(key) {
localStorage.removeItem(key);
},
clear() {
localStorage.clear();
}
},
// Format Date/Time
formatDateTime(date) {
const d = new Date(date);
return d.toLocaleString();
},
// Format Date (short)
formatDate(date) {
const d = new Date(date);
const now = new Date();
const diff = now - d;
if (diff < 60000) return "Just now";
if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
if (diff < 604800000) return `${Math.floor(diff / 86400000)}d ago`;
return d.toLocaleDateString();
},
// Count Words
countWords(text) {
return text.trim() ? text.trim().split(/\s+/).length : 0;
},
// Count Characters
countChars(text) {
return text.length;
},
// Count Lines
countLines(text) {
return text.split("\n").length;
},
// Calculate reading time (average 200 words per minute)
readingTime(wordCount) {
const minutes = Math.ceil(wordCount / 200);
if (minutes < 1) return "< 1 min read";
if (minutes === 1) return "1 min read";
return `${minutes} min read`;
},
// Download File
downloadFile(content, filename, mimeType = "text/plain") {
const blob = new Blob([content], { type: mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
},
// Copy to Clipboard
async copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
Utils.toast.success("Copied to clipboard!");
return true;
} catch (err) {
Utils.toast.error("Failed to copy");
return false;
}
},
// Debounce Function
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
// Generate UUID
uuid() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0;
const v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
},
// Sanitize Filename
sanitizeFilename(name) {
return name.replace(/[^a-z0-9_\-\.]/gi, "_");
},
// Truncate Text
truncate(text, maxLength) {
return text.length > maxLength ? text.substring(0, maxLength) + "..." : text;
},
// Escape HTML
escapeHtml(text) {
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
};
// Initialize modals on load
document.addEventListener("DOMContentLoaded", () => {
Utils.modal.init();
});
export default Utils;