flex-theme
Version:
A flexible theming system for web applications
134 lines (132 loc) • 4.16 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/theme.ts
var theme_exports = {};
__export(theme_exports, {
ThemeProvider: () => ThemeProvider,
getResolvedTheme: () => getResolvedTheme,
getTheme: () => getTheme,
offThemeChange: () => offThemeChange,
onThemeChange: () => onThemeChange,
setTheme: () => setTheme,
toggleTheme: () => toggleTheme
});
module.exports = __toCommonJS(theme_exports);
var currentTheme = "system";
var listeners = [];
function safeMatchMedia(query) {
if (typeof window === "undefined") return false;
if (typeof window.matchMedia !== "function") return false;
return window.matchMedia(query).matches;
}
function initTheme() {
if (typeof window === "undefined") return;
const savedTheme = localStorage.getItem("theme");
if (savedTheme && ["light", "dark", "system"].includes(savedTheme)) {
currentTheme = savedTheme;
} else {
currentTheme = "system";
}
applyTheme();
}
function applyTheme() {
if (typeof window === "undefined" || !document) return;
let effectiveTheme = currentTheme;
if (effectiveTheme === "system") {
effectiveTheme = safeMatchMedia("(prefers-color-scheme: dark)") ? "dark" : "light";
}
if (effectiveTheme === "dark") {
document.documentElement.classList.add("dark");
document.documentElement.classList.remove("light");
} else {
document.documentElement.classList.add("light");
document.documentElement.classList.remove("dark");
}
if (typeof localStorage !== "undefined") {
localStorage.setItem("theme", currentTheme);
}
}
function getTheme() {
return currentTheme;
}
function getResolvedTheme() {
if (currentTheme === "system") {
return safeMatchMedia("(prefers-color-scheme: dark)") ? "dark" : "light";
}
return currentTheme;
}
function setTheme(theme) {
if (!["light", "dark", "system"].includes(theme)) {
console.error(`Invalid theme: ${theme}. Must be 'light', 'dark', or 'system'`);
return;
}
currentTheme = theme;
applyTheme();
listeners.forEach((listener) => listener(theme));
}
function toggleTheme() {
const newTheme = currentTheme === "light" ? "dark" : "light";
setTheme(newTheme);
}
function onThemeChange(listener) {
listeners.push(listener);
}
function offThemeChange(listener) {
const index = listeners.indexOf(listener);
if (index !== -1) {
listeners.splice(index, 1);
}
}
if (typeof window !== "undefined") {
initTheme();
if (typeof window.matchMedia === "function") {
try {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
if (mediaQuery.addEventListener) {
mediaQuery.addEventListener("change", () => {
if (currentTheme === "system") {
applyTheme();
listeners.forEach((listener) => listener(currentTheme));
}
});
} else if (mediaQuery.addListener) {
mediaQuery.addListener(() => {
if (currentTheme === "system") {
applyTheme();
listeners.forEach((listener) => listener(currentTheme));
}
});
}
} catch (e) {
console.error("Error setting up media query listener:", e);
}
}
}
var ThemeProvider = ({ children }) => {
return children;
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ThemeProvider,
getResolvedTheme,
getTheme,
offThemeChange,
onThemeChange,
setTheme,
toggleTheme
});