ALV1's picture
all broken still nothing works check excaildraw github its opensource
1f908a7 verified
Raw
History Blame Contribute Delete
5.18 kB
// Theme & color system with "undefined" tokens and safe fallbacks
(() => {
const DEFAULT_PRIMARY = [59, 130, 246]; // blue-500
const DEFAULT_SECONDARY = [236, 72, 153]; // pink-500
const docEl = document.documentElement;
function toRgbArray(input) {
// Accepts: "59 130 246", "59,130,246", "rgb(59 130 246)", "#3b82f6"
if (!input) return null;
const trimmed = String(input).trim();
// Hex (#RRGGBB or #RGB)
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(trimmed)) {
let hex = trimmed.replace('#', '');
if (hex.length === 3) {
hex = hex.split('').map(c => c + c).join('');
}
const int = parseInt(hex, 16);
return [(int >> 16) & 255, (int >> 8) & 255, int & 255];
}
// rgb(...) or space-separated
const rgbMatch =
trimmed.match(/^rgb\(\s*([0-9]{1,3})\s*[, ]\s*([0-9]{1,3})\s*[, ]\s*([0-9]{1,3})\s*\)$/i) ||
trimmed.match(/^([0-9]{1,3})\s+([0-9]{1,3})\s+([0-9]{1,3})$/);
if (rgbMatch) {
const r = Math.max(0, Math.min(255, parseInt(rgbMatch[1], 10)));
const g = Math.max(0, Math.min(255, parseInt(rgbMatch[2], 10)));
const b = Math.max(0, Math.min(255, parseInt(rgbMatch[3], 10)));
return [r, g, b];
}
// Comma-separated "R,G,B"
const csv = trimmed.split(',').map(n => parseInt(n, 10));
if (csv.length === 3 && csv.every(n => Number.isFinite(n))) {
return csv.map(n => Math.max(0, Math.min(255, n)));
}
return null;
}
function setColorVar(name, rgbArr) {
const val = rgbArr ? `${rgbArr[0]} ${rgbArr[1]} ${rgbArr[2]}` : '';
docEl.style.setProperty(name, val);
}
function applyPrimaryColor(input) {
const arr = toRgbArray(input) || DEFAULT_PRIMARY;
setColorVar('--color-primary', arr);
try {
localStorage.setItem('primary', arr.join(' '));
} catch {}
return arr;
}
function applySecondaryColor(input) {
const arr = toRgbArray(input) || DEFAULT_SECONDARY;
setColorVar('--color-secondary', arr);
try {
localStorage.setItem('secondary', arr.join(' '));
} catch {}
return arr;
}
function applyThemeMode(mode) {
// Accepts "light" or "dark"
const m = mode === 'dark' ? 'dark' : 'light';
docEl.setAttribute('data-theme', m);
try {
localStorage.setItem('theme', m);
} catch {}
return m;
}
function currentTheme() {
const m = docEl.getAttribute('data-theme') || 'light';
return m;
}
function toggleTheme() {
const next = currentTheme() === 'dark' ? 'light' : 'dark';
applyThemeMode(next);
}
function boot() {
// Apply theme preference from URL or localStorage or default to light ("undefined mode")
const params = new URLSearchParams(location.search);
const themeFromUrl = params.get('mode') || params.get('theme');
const theme = themeFromUrl === 'dark' ? 'dark' : 'light';
applyThemeMode(theme);
// Apply colors from URL -> localStorage -> defaults
const primaryFromUrl = params.get('primary') || params.get('primaryColor') || params.get('p');
const secondaryFromUrl = params.get('secondary') || params.get('secondaryColor') || params.get('s');
let primary, secondary;
if (primaryFromUrl) {
primary = applyPrimaryColor(primaryFromUrl);
} else {
try {
const stored = localStorage.getItem('primary');
if (stored) primary = applyPrimaryColor(stored);
} catch {}
if (!primary) primary = applyPrimaryColor(null);
}
if (secondaryFromUrl) {
secondary = applySecondaryColor(secondaryFromUrl);
} else {
try {
const stored = localStorage.getItem('secondary');
if (stored) secondary = applySecondaryColor(stored);
} catch {}
if (!secondary) secondary = applySecondaryColor(null);
}
// UI hooks
const themeToggle = document.getElementById('themeToggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => {
toggleTheme();
});
}
const applyBtn = document.getElementById('applyColorsBtn');
const primaryInput = document.getElementById('primaryColor');
const secondaryInput = document.getElementById('secondaryColor');
if (applyBtn && primaryInput && secondaryInput) {
// Initialize inputs with current values
try {
const sp = getComputedStyle(docEl).getPropertyValue('--color-primary').trim() || DEFAULT_PRIMARY.join(' ');
const ss = getComputedStyle(docEl).getPropertyValue('--color-secondary').trim() || DEFAULT_SECONDARY.join(' ');
primaryInput.value = sp;
secondaryInput.value = ss;
} catch {}
applyBtn.addEventListener('click', () => {
applyPrimaryColor(primaryInput.value);
applySecondaryColor(secondaryInput.value);
});
}
// Expose a tiny API for integration
window.ExcailTheme = {
setPrimary: applyPrimaryColor,
setSecondary: applySecondaryColor,
setMode: applyThemeMode,
toggleTheme,
getMode: currentTheme,
};
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot, { once: true });
} else {
boot();
}
})();