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.
- package/CHANGELOG.md +31 -0
- package/README.md +19 -18
- package/docs/images/setup/01-local-sign-in-ready.png +0 -0
- package/docs/images/setup/02-vps-identity-confirmed.png +0 -0
- package/docs/images/setup/03-n8n-detected.png +0 -0
- package/docs/images/setup/04-install-plan.png +0 -0
- package/docs/images/setup/05-bridge-ready.png +0 -0
- package/package.json +1 -1
- package/src/ui/app.js +6 -21
- package/src/ui/icons/monitor.svg +6 -0
- package/src/ui/icons/moon.svg +4 -0
- package/src/ui/icons/sun.svg +12 -0
- package/src/ui/index.html +407 -452
- package/src/ui/styles.css +599 -669
- package/src/ui/theme.js +50 -0
- package/src/web/server.js +16 -10
- package/src/ui/geist-latin.woff2 +0 -0
package/src/ui/theme.js
ADDED
|
@@ -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/
|
|
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
|
-
"/
|
|
191
|
-
"/
|
|
192
|
-
"/
|
|
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(".
|
|
423
|
-
? "font/woff2"
|
|
424
|
-
: path.endsWith(".js")
|
|
428
|
+
path.endsWith(".js")
|
|
425
429
|
? "text/javascript; charset=utf-8"
|
|
426
|
-
: path
|
|
427
|
-
? "
|
|
428
|
-
: "
|
|
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,
|
package/src/ui/geist-latin.woff2
DELETED
|
Binary file
|