@magicvr/schema-ui-theme 0.1.0

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/index.js ADDED
@@ -0,0 +1,71 @@
1
+ function resolveTheme(input) {
2
+ if (input.stored === "dark" || input.stored === "light") {
3
+ return { theme: input.stored, colorScheme: input.stored };
4
+ }
5
+ if (input.systemDefault === "dark" || input.systemDefault === "light") {
6
+ return { theme: input.systemDefault, colorScheme: input.systemDefault };
7
+ }
8
+ const isDark = !input.stored && input.prefersDark;
9
+ const theme = isDark ? "dark" : "light";
10
+ return { theme, colorScheme: theme };
11
+ }
12
+ function applyThemeToElement(el, output) {
13
+ if (output.theme === "dark") {
14
+ el.classList.add("dark");
15
+ } else {
16
+ el.classList.remove("dark");
17
+ }
18
+ el.style.colorScheme = output.colorScheme;
19
+ }
20
+ function initTheme() {
21
+ let stored = null;
22
+ try {
23
+ stored = localStorage.getItem("theme");
24
+ } catch {
25
+ }
26
+ let prefersDark = false;
27
+ try {
28
+ prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
29
+ } catch {
30
+ }
31
+ const output = resolveTheme({ stored, prefersDark });
32
+ applyThemeToElement(document.documentElement, output);
33
+ }
34
+ function applySystemDefaultTheme(systemDefault) {
35
+ let stored = null;
36
+ try {
37
+ stored = localStorage.getItem("theme");
38
+ } catch {
39
+ }
40
+ if (stored === "dark" || stored === "light") {
41
+ return;
42
+ }
43
+ if (systemDefault !== "light" && systemDefault !== "dark") {
44
+ return;
45
+ }
46
+ let prefersDark = false;
47
+ try {
48
+ prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
49
+ } catch {
50
+ }
51
+ const output = resolveTheme({ stored, prefersDark, systemDefault });
52
+ applyThemeToElement(document.documentElement, output);
53
+ }
54
+ function setTheme(theme) {
55
+ try {
56
+ if (theme === null) {
57
+ localStorage.removeItem("theme");
58
+ } else {
59
+ localStorage.setItem("theme", theme);
60
+ }
61
+ } catch {
62
+ }
63
+ initTheme();
64
+ }
65
+ export {
66
+ applySystemDefaultTheme,
67
+ applyThemeToElement,
68
+ initTheme,
69
+ resolveTheme,
70
+ setTheme
71
+ };
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@magicvr/schema-ui-theme",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "schema-ui-core 包面(VP-023 R3 六包化)",
6
+ "main": "index.js",
7
+ "types": "./theme/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./theme/index.d.ts",
11
+ "import": "./index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "index.js",
16
+ "lib",
17
+ "theme",
18
+ "components",
19
+ "app",
20
+ "host",
21
+ "i18n",
22
+ "ui",
23
+ "renderer",
24
+ "render"
25
+ ],
26
+ "license": "UNLICENSED",
27
+ "publishConfig": {
28
+ "access": "public"
29
+ }
30
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @schema-ui/theme 聚合导出:语义 Token 解析与主题应用。
3
+ */
4
+ export * from "./theme";
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Theme pure-logic unit (S1 · C3 + VP-007 S3 system default).
3
+ *
4
+ * `applyTheme` is a side-effect-free function that computes the desired theme
5
+ * and then applies it to the provided document root. Keeping the decision
6
+ * logic in a plain function lets vitest exercise it without a browser.
7
+ *
8
+ * `initTheme` is the top-level boot call used by the synchronous external
9
+ * `/theme-init.js` script in index.html and by main.tsx (the module call is
10
+ * kept as a safety net for test/storybook entry points).
11
+ *
12
+ * VP-007 S3 priority (D-002, user-confirmed): user explicit choice →
13
+ * system default theme (from the public startup configuration, non-auto) →
14
+ * OS preference. The user's explicit choice always wins.
15
+ */
16
+ export type Theme = "light" | "dark";
17
+ export interface ThemeInput {
18
+ /** Value of `localStorage.getItem("theme")` — null when absent. */
19
+ stored: string | null;
20
+ /** `window.matchMedia("(prefers-color-scheme: dark)").matches` */
21
+ prefersDark: boolean;
22
+ /** System default theme from /api/branding (auto/light/dark); null = auto. */
23
+ systemDefault?: string | null;
24
+ }
25
+ export interface ThemeOutput {
26
+ theme: Theme;
27
+ /** CSS `color-scheme` value for the root element. */
28
+ colorScheme: "light" | "dark";
29
+ }
30
+ /**
31
+ * Pure function: decides the effective theme from storage + system default +
32
+ * OS preference. No DOM side-effects — safe to call in vitest.
33
+ */
34
+ export declare function resolveTheme(input: ThemeInput): ThemeOutput;
35
+ /**
36
+ * Applies the resolved theme to a DOM element (typically
37
+ * `document.documentElement`). Adds or removes the `dark` class and sets
38
+ * the `color-scheme` style so native browser controls match.
39
+ */
40
+ export declare function applyThemeToElement(el: HTMLElement, output: ThemeOutput): void;
41
+ /**
42
+ * End-to-end theme boot: reads real browser APIs and mutates the DOM.
43
+ * Called from the synchronous external /theme-init.js script in index.html and from main.tsx.
44
+ *
45
+ * W4 P2-1: localStorage may throw when site storage is disabled (privacy
46
+ * mode). main.tsx calls initTheme at module top level — an uncaught throw
47
+ * would abort module evaluation and the app would never mount (white screen,
48
+ * not even the failure surface). Guard reads/writes exactly like tokens.ts.
49
+ */
50
+ export declare function initTheme(): void;
51
+ /**
52
+ * Applies the system default theme (from the public startup configuration)
53
+ * when the user has no explicit choice. VP-007 S3: the explicit user theme
54
+ * always wins; otherwise the system default (non-auto) beats the OS
55
+ * preference. Called after branding loads on the login page and the shell.
56
+ */
57
+ export declare function applySystemDefaultTheme(systemDefault: string | null | undefined): void;
58
+ /**
59
+ * Sets the user's preferred theme, persists it to localStorage, and applies
60
+ * it immediately. Pass `null` to revert to OS preference. W4 P2-1: storage
61
+ * writes are best-effort — a disabled-storage environment still applies the
62
+ * theme for the current page.
63
+ */
64
+ export declare function setTheme(theme: Theme | null): void;