forked from tsai/budibase
4 changed files with 143 additions and 26 deletions
@ -0,0 +1,43 @@ |
|||||
|
import { get, writable } from "svelte/store" |
||||
|
|
||||
|
export const localStorageStore = (localStorageKey, initialValue) => { |
||||
|
const store = writable(initialValue, () => { |
||||
|
// Hydrate from local storage when we get a new subscriber
|
||||
|
hydrate() |
||||
|
|
||||
|
// Listen for local storage changes and keep store in sync
|
||||
|
const storageListener = ({ key }) => key === localStorageKey && hydrate() |
||||
|
window.addEventListener("storage", storageListener) |
||||
|
return () => window.removeEventListener("storage", storageListener) |
||||
|
}) |
||||
|
|
||||
|
// New store setter which updates the store and localstorage
|
||||
|
const set = value => { |
||||
|
store.set(value) |
||||
|
localStorage.setItem(localStorageKey, JSON.stringify(value)) |
||||
|
} |
||||
|
|
||||
|
// New store updater which updates the store and localstorage
|
||||
|
const update = updaterFn => set(updaterFn(get(store))) |
||||
|
|
||||
|
// Hydrates the store from localstorage
|
||||
|
const hydrate = () => { |
||||
|
const localValue = localStorage.getItem(localStorageKey) |
||||
|
if (localValue == null) { |
||||
|
set(initialValue) |
||||
|
} else { |
||||
|
try { |
||||
|
store.set(JSON.parse(localValue)) |
||||
|
} catch { |
||||
|
set(initialValue) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Patch the default svelte store functions with our overrides
|
||||
|
return { |
||||
|
...store, |
||||
|
set, |
||||
|
update, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
import { localStorageStore } from "./localStorage" |
||||
|
|
||||
|
export const getThemeStore = () => { |
||||
|
const themeElement = document.documentElement |
||||
|
const initialValue = { |
||||
|
darkMode: false, |
||||
|
hue: 208, |
||||
|
saturation: 9, |
||||
|
lightness: 16, |
||||
|
} |
||||
|
|
||||
|
const store = localStorageStore("bb-theme", initialValue) |
||||
|
|
||||
|
// Sets a CSS variable on the root document element
|
||||
|
function setCSSVariable(prop, value) { |
||||
|
themeElement.style.setProperty(prop, value) |
||||
|
} |
||||
|
|
||||
|
// Resets the custom theme to the default dark theme.
|
||||
|
// The reset option is only available when dark theme is on, which is why it
|
||||
|
// sets dark mode to true here
|
||||
|
store.reset = () => { |
||||
|
store.set({ |
||||
|
...initialValue, |
||||
|
darkMode: true, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// Update theme when store changes
|
||||
|
store.subscribe(theme => { |
||||
|
themeElement.classList[theme.darkMode ? "add" : "remove"]("dark") |
||||
|
setCSSVariable("--theme-hue", Math.round(theme.hue)) |
||||
|
setCSSVariable("--theme-saturation", `${Math.round(theme.saturation)}%`) |
||||
|
setCSSVariable("--theme-brightness", `${Math.round(theme.lightness)}%`) |
||||
|
}) |
||||
|
|
||||
|
return store |
||||
|
} |
||||
Loading…
Reference in new issue