1+ const THEME_KEY = "trackio_theme_preference";
2+
3+ let _listeners = [];
4+
5+ export function onThemeChange(fn) {
6+ _listeners.push(fn);
7+ return () => {
8+ _listeners = _listeners.filter((f) => f !== fn);
9+ };
10+ }
11+
12+ function _notify() {
13+ const dark = isDark();
14+ _listeners.forEach((fn) => fn(dark));
15+ }
16+
117const darkOverrides = {
218 "--neutral-50": "#fafafa",
319 "--neutral-100": "#f4f4f5",
@@ -65,6 +81,7 @@ export function applyTheme(themeName) {
6581 root.style.removeProperty(key);
6682 });
6783 }
84+ _notify();
6885}
6986
7087export function isDark() {
@@ -80,3 +97,53 @@ export function detectSystemTheme() {
8097 }
8198 return "default";
8299}
100+
101+ export function getThemePreference() {
102+ return localStorage.getItem(THEME_KEY) || "system";
103+ }
104+
105+ export function setThemePreference(pref) {
106+ localStorage.setItem(THEME_KEY, pref);
107+ applyThemeFromPreference(pref);
108+ _ensureSystemListener(pref === "system");
109+ }
110+
111+ export function applyThemeFromPreference(pref) {
112+ if (pref === "system") {
113+ applyTheme(detectSystemTheme());
114+ } else if (pref === "dark") {
115+ applyTheme("dark");
116+ } else {
117+ applyTheme("default");
118+ }
119+ }
120+
121+ let _systemListenerAttached = false;
122+
123+ function _onSystemThemeChange() {
124+ if (getThemePreference() === "system") {
125+ applyTheme(detectSystemTheme());
126+ }
127+ }
128+
129+ function _ensureSystemListener(needed) {
130+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
131+ if (needed && !_systemListenerAttached) {
132+ mq.addEventListener("change", _onSystemThemeChange);
133+ _systemListenerAttached = true;
134+ } else if (!needed && _systemListenerAttached) {
135+ mq.removeEventListener("change", _onSystemThemeChange);
136+ _systemListenerAttached = false;
137+ }
138+ }
139+
140+ export function initTheme() {
141+ const urlTheme = new URLSearchParams(window.location.search).get("__theme");
142+ if (urlTheme) {
143+ applyTheme(urlTheme);
144+ return;
145+ }
146+ const pref = getThemePreference();
147+ applyThemeFromPreference(pref);
148+ _ensureSystemListener(pref === "system");
149+ }
0 commit comments