relmio 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ const colorModes = new Set(["system", "light", "dark"]);
2
+ const storageKey = "relmio-color-mode";
3
+
4
+ function applyMode(mode) {
5
+ if (mode === "light" || mode === "dark") {
6
+ document.documentElement.dataset.theme = mode;
7
+ } else {
8
+ delete document.documentElement.dataset.theme;
9
+ }
10
+
11
+ document
12
+ .querySelectorAll('input[name="color-theme"]')
13
+ .forEach((input) => {
14
+ input.checked = input.value === mode;
15
+ });
16
+ }
17
+
18
+ let initialMode = "system";
19
+
20
+ try {
21
+ const savedMode = window.localStorage.getItem(storageKey);
22
+ if (colorModes.has(savedMode)) {
23
+ initialMode = savedMode;
24
+ }
25
+ } catch {
26
+ // System mode remains available when browser storage is unavailable.
27
+ }
28
+
29
+ applyMode(initialMode);
30
+
31
+ document
32
+ .querySelectorAll('input[name="color-theme"]')
33
+ .forEach((input) => {
34
+ input.addEventListener("change", () => {
35
+ if (!input.checked || !colorModes.has(input.value)) return;
36
+
37
+ applyMode(input.value);
38
+ try {
39
+ window.localStorage.setItem(storageKey, input.value);
40
+ } catch {
41
+ // The selection still applies for this page view.
42
+ }
43
+ });
44
+ });
45
+
46
+ window.addEventListener("storage", (event) => {
47
+ if (event.key === storageKey) {
48
+ applyMode(colorModes.has(event.newValue) ? event.newValue : "system");
49
+ }
50
+ });
package/src/web/server.js CHANGED
@@ -179,17 +179,23 @@ async function loadDefaultUiFiles() {
179
179
  const files = await Promise.all([
180
180
  readFile(new URL("../ui/index.html", import.meta.url), "utf8"),
181
181
  readFile(new URL("../ui/app.js", import.meta.url), "utf8"),
182
+ readFile(new URL("../ui/theme.js", import.meta.url), "utf8"),
182
183
  readFile(new URL("../ui/time.js", import.meta.url), "utf8"),
183
184
  readFile(new URL("../ui/styles.css", import.meta.url), "utf8"),
184
- readFile(new URL("../ui/geist-latin.woff2", import.meta.url)),
185
+ readFile(new URL("../ui/icons/monitor.svg", import.meta.url), "utf8"),
186
+ readFile(new URL("../ui/icons/sun.svg", import.meta.url), "utf8"),
187
+ readFile(new URL("../ui/icons/moon.svg", import.meta.url), "utf8"),
185
188
  ]);
186
189
 
187
190
  return {
188
191
  "/": files[0],
189
192
  "/app.js": files[1],
190
- "/time.js": files[2],
191
- "/styles.css": files[3],
192
- "/geist-latin.woff2": files[4],
193
+ "/theme.js": files[2],
194
+ "/time.js": files[3],
195
+ "/styles.css": files[4],
196
+ "/icons/monitor.svg": files[5],
197
+ "/icons/sun.svg": files[6],
198
+ "/icons/moon.svg": files[7],
193
199
  };
194
200
  }
195
201
 
@@ -419,13 +425,13 @@ function createRequestHandler(state) {
419
425
  }
420
426
 
421
427
  const contentType =
422
- path.endsWith(".woff2")
423
- ? "font/woff2"
424
- : path.endsWith(".js")
428
+ path.endsWith(".js")
425
429
  ? "text/javascript; charset=utf-8"
426
- : path === "/styles.css"
427
- ? "text/css; charset=utf-8"
428
- : "text/html; charset=utf-8";
430
+ : path.endsWith(".svg")
431
+ ? "image/svg+xml; charset=utf-8"
432
+ : path === "/styles.css"
433
+ ? "text/css; charset=utf-8"
434
+ : "text/html; charset=utf-8";
429
435
  const contents = state.uiFiles[path];
430
436
  response.writeHead(200, {
431
437
  "Content-Type": contentType,
Binary file