|
|
import { PersistedState, watch } from "runed"; |
|
|
import { isBrowser, noopStorage } from "./utils.js"; |
|
|
import { modeStorageKey } from "./storage-keys.svelte.js"; |
|
|
import { isValidMode } from "./modes.js"; |
|
|
import { MediaQuery } from "svelte/reactivity"; |
|
|
export class UserPrefersMode { |
|
|
#defaultValue = "system"; |
|
|
#storage = isBrowser ? localStorage : noopStorage; |
|
|
#initialValue = this.#storage.getItem(modeStorageKey.current); |
|
|
#value = isValidMode(this.#initialValue) ? this.#initialValue : this.#defaultValue; |
|
|
#persisted = $state(this.#makePersisted()); |
|
|
#makePersisted(value = this.#value) { |
|
|
return new PersistedState(modeStorageKey.current, value, { |
|
|
serializer: { |
|
|
serialize: (v) => v, |
|
|
deserialize: (v) => { |
|
|
if (isValidMode(v)) |
|
|
return v; |
|
|
return this.#defaultValue; |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
} |
|
|
constructor() { |
|
|
$effect.root(() => { |
|
|
return watch.pre(() => modeStorageKey.current, (_, prevStorageKey) => { |
|
|
const currModeValue = this.#persisted.current; |
|
|
this.#persisted = this.#makePersisted(currModeValue); |
|
|
if (prevStorageKey) { |
|
|
localStorage.removeItem(prevStorageKey); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
get current() { |
|
|
return this.#persisted.current; |
|
|
} |
|
|
set current(newValue) { |
|
|
this.#persisted.current = newValue; |
|
|
} |
|
|
} |
|
|
export class SystemPrefersMode { |
|
|
#defaultValue = undefined; |
|
|
#track = true; |
|
|
#current = $state(this.#defaultValue); |
|
|
#mediaQueryState = typeof window !== "undefined" && typeof window.matchMedia === "function" |
|
|
? new MediaQuery("prefers-color-scheme: light") |
|
|
: { current: false }; |
|
|
query() { |
|
|
if (!isBrowser) |
|
|
return; |
|
|
this.#current = this.#mediaQueryState.current ? "light" : "dark"; |
|
|
} |
|
|
tracking(active) { |
|
|
this.#track = active; |
|
|
} |
|
|
constructor() { |
|
|
$effect.root(() => { |
|
|
$effect.pre(() => { |
|
|
if (!this.#track) |
|
|
return; |
|
|
this.query(); |
|
|
}); |
|
|
}); |
|
|
this.query = this.query.bind(this); |
|
|
this.tracking = this.tracking.bind(this); |
|
|
} |
|
|
get current() { |
|
|
return this.#current; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const userPrefersMode = new UserPrefersMode(); |
|
|
|
|
|
|
|
|
|
|
|
export const systemPrefersMode = new SystemPrefersMode(); |
|
|
|