forked from freifunk/meshviewer
-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy paththeme.ts
More file actions
114 lines (97 loc) · 2.71 KB
/
Copy paththeme.ts
File metadata and controls
114 lines (97 loc) · 2.71 KB
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
109
110
111
112
113
114
export type Theme = "light" | "dark" | "auto";
// Keep STORAGE_KEY and DARK_CLASS in sync with the pre-paint inline script in index.html.
const STORAGE_KEY = "meshviewer.theme";
const DARK_CLASS = "theme_night";
const THEMES: Theme[] = ["light", "dark", "auto"];
let inMemory: Theme = "auto";
const darkQuery =
typeof window !== "undefined" && window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null;
function isTheme(value: string | null): value is Theme {
return value === "light" || value === "dark" || value === "auto";
}
function read(): Theme {
try {
let v = localStorage.getItem(STORAGE_KEY);
if (isTheme(v)) {
return v;
}
} catch (e) {
/* localStorage inaccessible (private mode, sandboxed iframe, file://) */
}
return inMemory;
}
function write(value: Theme): void {
inMemory = value;
try {
localStorage.setItem(STORAGE_KEY, value);
} catch (e) {
/* keep in-memory only */
}
}
export function resolveTheme(): "light" | "dark" {
let current = read();
if (current === "dark") {
return "dark";
}
if (current === "auto" && darkQuery && darkQuery.matches) {
return "dark";
}
return "light";
}
function apply(): void {
let dark = resolveTheme() === "dark";
document.documentElement.classList.toggle(DARK_CLASS, dark);
document.documentElement.dispatchEvent(new CustomEvent("themechange"));
}
export function getTheme(): Theme {
return read();
}
export function cycleTheme(): Theme {
let next = THEMES[(THEMES.indexOf(read()) + 1) % THEMES.length];
write(next);
apply();
return next;
}
export function initTheme(): void {
inMemory = read();
apply();
if (darkQuery) {
darkQuery.addEventListener("change", function () {
if (read() === "auto") {
apply();
}
});
}
}
const SVG_OPEN = '<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">';
const SVG_CLOSE = "</svg>";
const SUN_RAYS =
'<rect x="11" y="1" width="2" height="3" rx="1"/>' +
'<rect x="11" y="20" width="2" height="3" rx="1"/>' +
'<rect x="1" y="11" width="3" height="2" rx="1"/>' +
'<rect x="20" y="11" width="3" height="2" rx="1"/>';
const SUN =
SVG_OPEN +
'<circle cx="12" cy="12" r="5"/>' +
"<g>" +
SUN_RAYS +
"</g>" +
'<g transform="rotate(45 12 12)">' +
SUN_RAYS +
"</g>" +
SVG_CLOSE;
const MOON = SVG_OPEN + '<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/>' + SVG_CLOSE;
const AUTO =
SVG_OPEN +
'<path d="M12 4a8 8 0 000 16V4z"/>' +
'<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.5"/>' +
SVG_CLOSE;
export function themeIconSVG(theme: Theme): string {
if (theme === "dark") {
return MOON;
}
if (theme === "auto") {
return AUTO;
}
return SUN;
}