File size: 3,875 Bytes
04ec17f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { box } from "svelte-toolbelt";
import { isBrowser, sanitizeClassNames } from "./utils.js";
import { withoutTransition } from "./without-transition.js";
import { systemPrefersMode, userPrefersMode } from "./mode-states.svelte.js";
import { customTheme } from "./theme-state.svelte.js";
import { untrack } from "svelte";
/**
 * Theme colors for light and dark modes.
 */
export const themeColors = box(undefined);
/**
 * Whether to disable transitions when changing the mode.
 */
export const disableTransitions = box(true);
/**
 * Whether to run the mode changes synchronously instead of using
 * an animation frame. If true, will have an impact on blocking performance
 * due to blocking the main thread.
 */
export const synchronousModeChanges = box(false);
/**
 * The classnames to add to the root `html` element when the mode is dark.
 */
export const darkClassNames = box([]);
/**
 * The classnames to add to the root `html` element when the mode is light.
 */
export const lightClassNames = box([]);
function createDerivedMode() {
    const current = $derived.by(() => {
        if (!isBrowser)
            return undefined;
        const derivedMode = userPrefersMode.current === "system"
            ? systemPrefersMode.current
            : userPrefersMode.current;
        const sanitizedDarkClassNames = sanitizeClassNames(darkClassNames.current);
        const sanitizedLightClassNames = sanitizeClassNames(lightClassNames.current);
        function update() {
            const htmlEl = document.documentElement;
            const themeColorEl = document.querySelector('meta[name="theme-color"]');
            if (derivedMode === "light") {
                if (sanitizedDarkClassNames.length)
                    htmlEl.classList.remove(...sanitizedDarkClassNames);
                if (sanitizedLightClassNames.length)
                    htmlEl.classList.add(...sanitizedLightClassNames);
                htmlEl.style.colorScheme = "light";
                if (themeColorEl && themeColors.current) {
                    themeColorEl.setAttribute("content", themeColors.current.light);
                }
            }
            else {
                if (sanitizedLightClassNames.length)
                    htmlEl.classList.remove(...sanitizedLightClassNames);
                if (sanitizedDarkClassNames.length)
                    htmlEl.classList.add(...sanitizedDarkClassNames);
                htmlEl.style.colorScheme = "dark";
                if (themeColorEl && themeColors.current) {
                    themeColorEl.setAttribute("content", themeColors.current.dark);
                }
            }
        }
        if (disableTransitions.current) {
            withoutTransition(update, synchronousModeChanges.current);
        }
        else {
            update();
        }
        return derivedMode;
    });
    return {
        get current() {
            return current;
        },
    };
}
function createDerivedTheme() {
    const current = $derived.by(() => {
        customTheme.current;
        if (!isBrowser)
            return undefined;
        function update() {
            const htmlEl = document.documentElement;
            htmlEl.setAttribute("data-theme", customTheme.current);
        }
        if (disableTransitions.current) {
            withoutTransition(update, untrack(() => synchronousModeChanges.current));
        }
        else {
            update();
        }
        return customTheme.current;
    });
    return {
        get current() {
            return current;
        },
    };
}
/**
 * Derived store that represents the current mode (`"dark"`, `"light"` or `undefined`)
 */
export const derivedMode = createDerivedMode();
/**
 * Derived store that represents the current custom theme
 */
export const derivedTheme = createDerivedTheme();
export { derivedMode as mode, derivedTheme as theme };