@vlian/framework 1.2.54 → 1.2.55
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/dist/analytics.umd.js +1 -1
- package/dist/index.umd.js +213 -60
- package/dist/index.umd.js.map +1 -1
- package/dist/kernel/manager/theme/ThemeManager.cjs +86 -0
- package/dist/kernel/manager/theme/ThemeManager.cjs.map +1 -0
- package/dist/kernel/manager/theme/ThemeManager.d.ts +16 -0
- package/dist/kernel/manager/theme/ThemeManager.js +76 -0
- package/dist/kernel/manager/theme/ThemeManager.js.map +1 -0
- package/dist/kernel/manager/theme/index.cjs +13 -0
- package/dist/kernel/manager/theme/index.cjs.map +1 -0
- package/dist/kernel/manager/theme/index.d.ts +1 -0
- package/dist/kernel/manager/theme/index.js +3 -0
- package/dist/kernel/manager/theme/index.js.map +1 -0
- package/dist/kernel/manager/theme/theme.dom.cjs +63 -0
- package/dist/kernel/manager/theme/theme.dom.cjs.map +1 -0
- package/dist/kernel/manager/theme/theme.dom.d.ts +3 -0
- package/dist/kernel/manager/theme/theme.dom.js +45 -0
- package/dist/kernel/manager/theme/theme.dom.js.map +1 -0
- package/dist/kernel/manager/theme/theme.persistence.cjs +59 -0
- package/dist/kernel/manager/theme/theme.persistence.cjs.map +1 -0
- package/dist/kernel/manager/theme/theme.persistence.d.ts +5 -0
- package/dist/kernel/manager/theme/theme.persistence.js +38 -0
- package/dist/kernel/manager/theme/theme.persistence.js.map +1 -0
- package/dist/kernel/manager/theme/theme.schema.cjs +124 -0
- package/dist/kernel/manager/theme/theme.schema.cjs.map +1 -0
- package/dist/kernel/manager/theme/theme.schema.d.ts +7 -0
- package/dist/kernel/manager/theme/theme.schema.js +97 -0
- package/dist/kernel/manager/theme/theme.schema.js.map +1 -0
- package/dist/kernel/manager/themeManager.cjs +2 -95
- package/dist/kernel/manager/themeManager.cjs.map +1 -1
- package/dist/kernel/manager/themeManager.d.ts +1 -15
- package/dist/kernel/manager/themeManager.js +1 -94
- package/dist/kernel/manager/themeManager.js.map +1 -1
- package/dist/state.umd.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ThemeManager", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ThemeManager;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _constants = require("../../constants");
|
|
12
|
+
const _themedom = require("./theme.dom");
|
|
13
|
+
const _themepersistence = require("./theme.persistence");
|
|
14
|
+
const _themeschema = require("./theme.schema");
|
|
15
|
+
function _define_property(obj, key, value) {
|
|
16
|
+
if (key in obj) {
|
|
17
|
+
Object.defineProperty(obj, key, {
|
|
18
|
+
value: value,
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
obj[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
let ThemeManager = class ThemeManager {
|
|
29
|
+
async initialize(context) {
|
|
30
|
+
this.config = context.config.theme;
|
|
31
|
+
this.cacheManager = context.cacheManager;
|
|
32
|
+
const initialTheme = (0, _themeschema.normalizeTheme)(this.config.initial || {}, _constants.DEFAULT_THEME);
|
|
33
|
+
this.theme = await (0, _themepersistence.loadThemeFromCache)(this.cacheManager, this.config.persistence, initialTheme);
|
|
34
|
+
(0, _themedom.applyThemeToDocument)(this.theme);
|
|
35
|
+
this.initialized = true;
|
|
36
|
+
}
|
|
37
|
+
getTheme() {
|
|
38
|
+
return (0, _themeschema.cloneTheme)(this.theme);
|
|
39
|
+
}
|
|
40
|
+
getSnapshot() {
|
|
41
|
+
return this.getTheme();
|
|
42
|
+
}
|
|
43
|
+
subscribe(listener) {
|
|
44
|
+
this.listeners.add(listener);
|
|
45
|
+
return ()=>{
|
|
46
|
+
this.listeners.delete(listener);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async setTheme(nextTheme) {
|
|
50
|
+
this.ensureInitialized();
|
|
51
|
+
const prevTheme = this.theme;
|
|
52
|
+
const mergedTheme = (0, _themeschema.mergeTheme)(prevTheme, nextTheme);
|
|
53
|
+
if ((0, _themeschema.isThemeEqual)(prevTheme, mergedTheme)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.theme = mergedTheme;
|
|
57
|
+
(0, _themedom.applyThemeToDocument)(this.theme, prevTheme);
|
|
58
|
+
if (this.cacheManager) {
|
|
59
|
+
await (0, _themepersistence.saveThemeToCache)(this.cacheManager, this.config.persistence, this.theme);
|
|
60
|
+
}
|
|
61
|
+
this.emit(this.theme, prevTheme);
|
|
62
|
+
}
|
|
63
|
+
ensureInitialized() {
|
|
64
|
+
if (!this.initialized) {
|
|
65
|
+
throw new Error('ThemeManager must be initialized before use.');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
emit(next, prev) {
|
|
69
|
+
for (const listener of this.listeners){
|
|
70
|
+
try {
|
|
71
|
+
listener((0, _themeschema.cloneTheme)(next), (0, _themeschema.cloneTheme)(prev));
|
|
72
|
+
} catch {
|
|
73
|
+
// Keep notifying remaining listeners even if one fails.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
constructor(){
|
|
78
|
+
_define_property(this, "theme", (0, _themeschema.cloneTheme)(_constants.DEFAULT_THEME));
|
|
79
|
+
_define_property(this, "config", _constants.DEFAULT_CONFIG.theme);
|
|
80
|
+
_define_property(this, "listeners", new Set());
|
|
81
|
+
_define_property(this, "cacheManager", null);
|
|
82
|
+
_define_property(this, "initialized", false);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
//# sourceMappingURL=ThemeManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/ThemeManager.ts"],"sourcesContent":["import type { StorageInstance } from '@vlian/utils';\nimport { DEFAULT_CONFIG, DEFAULT_THEME } from '../../constants';\nimport type { KernelConfig, KernelManager, KernelManagerContext, ThemeSnapshot } from '../../types';\nimport { applyThemeToDocument } from './theme.dom';\nimport { loadThemeFromCache, saveThemeToCache } from './theme.persistence';\nimport { cloneTheme, isThemeEqual, mergeTheme, normalizeTheme, type ThemeListener } from './theme.schema';\n\nexport class ThemeManager implements KernelManager<ThemeSnapshot> {\n private theme: ThemeSnapshot = cloneTheme(DEFAULT_THEME);\n private config: KernelConfig['theme'] = DEFAULT_CONFIG.theme;\n private listeners = new Set<ThemeListener>();\n private cacheManager: StorageInstance | null = null;\n private initialized = false;\n\n public async initialize(context: KernelManagerContext): Promise<void> {\n this.config = context.config.theme;\n this.cacheManager = context.cacheManager;\n\n const initialTheme = normalizeTheme(this.config.initial || {}, DEFAULT_THEME);\n this.theme = await loadThemeFromCache(this.cacheManager, this.config.persistence, initialTheme);\n\n applyThemeToDocument(this.theme);\n this.initialized = true;\n }\n\n public getTheme(): ThemeSnapshot {\n return cloneTheme(this.theme);\n }\n\n public getSnapshot(): ThemeSnapshot {\n return this.getTheme();\n }\n\n public subscribe(listener: ThemeListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n public async setTheme(nextTheme: ThemeSnapshot): Promise<void> {\n this.ensureInitialized();\n\n const prevTheme = this.theme;\n const mergedTheme = mergeTheme(prevTheme, nextTheme);\n\n if (isThemeEqual(prevTheme, mergedTheme)) {\n return;\n }\n\n this.theme = mergedTheme;\n applyThemeToDocument(this.theme, prevTheme);\n\n if (this.cacheManager) {\n await saveThemeToCache(this.cacheManager, this.config.persistence, this.theme);\n }\n\n this.emit(this.theme, prevTheme);\n }\n\n private ensureInitialized(): void {\n if (!this.initialized) {\n throw new Error('ThemeManager must be initialized before use.');\n }\n }\n\n private emit(next: ThemeSnapshot, prev: ThemeSnapshot): void {\n for (const listener of this.listeners) {\n try {\n listener(cloneTheme(next), cloneTheme(prev));\n } catch {\n // Keep notifying remaining listeners even if one fails.\n }\n }\n }\n}\n"],"names":["ThemeManager","initialize","context","config","theme","cacheManager","initialTheme","normalizeTheme","initial","DEFAULT_THEME","loadThemeFromCache","persistence","applyThemeToDocument","initialized","getTheme","cloneTheme","getSnapshot","subscribe","listener","listeners","add","delete","setTheme","nextTheme","ensureInitialized","prevTheme","mergedTheme","mergeTheme","isThemeEqual","saveThemeToCache","emit","Error","next","prev","DEFAULT_CONFIG","Set"],"mappings":";;;;+BAOaA;;;eAAAA;;;2BANiC;0BAET;kCACgB;6BACoC;;;;;;;;;;;;;;AAElF,IAAA,AAAMA,eAAN,MAAMA;IAOX,MAAaC,WAAWC,OAA6B,EAAiB;QACpE,IAAI,CAACC,MAAM,GAAGD,QAAQC,MAAM,CAACC,KAAK;QAClC,IAAI,CAACC,YAAY,GAAGH,QAAQG,YAAY;QAExC,MAAMC,eAAeC,IAAAA,2BAAc,EAAC,IAAI,CAACJ,MAAM,CAACK,OAAO,IAAI,CAAC,GAAGC,wBAAa;QAC5E,IAAI,CAACL,KAAK,GAAG,MAAMM,IAAAA,oCAAkB,EAAC,IAAI,CAACL,YAAY,EAAE,IAAI,CAACF,MAAM,CAACQ,WAAW,EAAEL;QAElFM,IAAAA,8BAAoB,EAAC,IAAI,CAACR,KAAK;QAC/B,IAAI,CAACS,WAAW,GAAG;IACrB;IAEOC,WAA0B;QAC/B,OAAOC,IAAAA,uBAAU,EAAC,IAAI,CAACX,KAAK;IAC9B;IAEOY,cAA6B;QAClC,OAAO,IAAI,CAACF,QAAQ;IACtB;IAEOG,UAAUC,QAAuB,EAAc;QACpD,IAAI,CAACC,SAAS,CAACC,GAAG,CAACF;QAEnB,OAAO;YACL,IAAI,CAACC,SAAS,CAACE,MAAM,CAACH;QACxB;IACF;IAEA,MAAaI,SAASC,SAAwB,EAAiB;QAC7D,IAAI,CAACC,iBAAiB;QAEtB,MAAMC,YAAY,IAAI,CAACrB,KAAK;QAC5B,MAAMsB,cAAcC,IAAAA,uBAAU,EAACF,WAAWF;QAE1C,IAAIK,IAAAA,yBAAY,EAACH,WAAWC,cAAc;YACxC;QACF;QAEA,IAAI,CAACtB,KAAK,GAAGsB;QACbd,IAAAA,8BAAoB,EAAC,IAAI,CAACR,KAAK,EAAEqB;QAEjC,IAAI,IAAI,CAACpB,YAAY,EAAE;YACrB,MAAMwB,IAAAA,kCAAgB,EAAC,IAAI,CAACxB,YAAY,EAAE,IAAI,CAACF,MAAM,CAACQ,WAAW,EAAE,IAAI,CAACP,KAAK;QAC/E;QAEA,IAAI,CAAC0B,IAAI,CAAC,IAAI,CAAC1B,KAAK,EAAEqB;IACxB;IAEQD,oBAA0B;QAChC,IAAI,CAAC,IAAI,CAACX,WAAW,EAAE;YACrB,MAAM,IAAIkB,MAAM;QAClB;IACF;IAEQD,KAAKE,IAAmB,EAAEC,IAAmB,EAAQ;QAC3D,KAAK,MAAMf,YAAY,IAAI,CAACC,SAAS,CAAE;YACrC,IAAI;gBACFD,SAASH,IAAAA,uBAAU,EAACiB,OAAOjB,IAAAA,uBAAU,EAACkB;YACxC,EAAE,OAAM;YACN,wDAAwD;YAC1D;QACF;IACF;;QAnEA,uBAAQ7B,SAAuBW,IAAAA,uBAAU,EAACN,wBAAa;QACvD,uBAAQN,UAAgC+B,yBAAc,CAAC9B,KAAK;QAC5D,uBAAQe,aAAY,IAAIgB;QACxB,uBAAQ9B,gBAAuC;QAC/C,uBAAQQ,eAAc;;AAgExB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { KernelManager, KernelManagerContext, ThemeSnapshot } from '../../types';
|
|
2
|
+
import { type ThemeListener } from './theme.schema';
|
|
3
|
+
export declare class ThemeManager implements KernelManager<ThemeSnapshot> {
|
|
4
|
+
private theme;
|
|
5
|
+
private config;
|
|
6
|
+
private listeners;
|
|
7
|
+
private cacheManager;
|
|
8
|
+
private initialized;
|
|
9
|
+
initialize(context: KernelManagerContext): Promise<void>;
|
|
10
|
+
getTheme(): ThemeSnapshot;
|
|
11
|
+
getSnapshot(): ThemeSnapshot;
|
|
12
|
+
subscribe(listener: ThemeListener): () => void;
|
|
13
|
+
setTheme(nextTheme: ThemeSnapshot): Promise<void>;
|
|
14
|
+
private ensureInitialized;
|
|
15
|
+
private emit;
|
|
16
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
import { DEFAULT_CONFIG, DEFAULT_THEME } from "../../constants";
|
|
15
|
+
import { applyThemeToDocument } from "./theme.dom";
|
|
16
|
+
import { loadThemeFromCache, saveThemeToCache } from "./theme.persistence";
|
|
17
|
+
import { cloneTheme, isThemeEqual, mergeTheme, normalizeTheme } from "./theme.schema";
|
|
18
|
+
export class ThemeManager {
|
|
19
|
+
async initialize(context) {
|
|
20
|
+
this.config = context.config.theme;
|
|
21
|
+
this.cacheManager = context.cacheManager;
|
|
22
|
+
const initialTheme = normalizeTheme(this.config.initial || {}, DEFAULT_THEME);
|
|
23
|
+
this.theme = await loadThemeFromCache(this.cacheManager, this.config.persistence, initialTheme);
|
|
24
|
+
applyThemeToDocument(this.theme);
|
|
25
|
+
this.initialized = true;
|
|
26
|
+
}
|
|
27
|
+
getTheme() {
|
|
28
|
+
return cloneTheme(this.theme);
|
|
29
|
+
}
|
|
30
|
+
getSnapshot() {
|
|
31
|
+
return this.getTheme();
|
|
32
|
+
}
|
|
33
|
+
subscribe(listener) {
|
|
34
|
+
this.listeners.add(listener);
|
|
35
|
+
return ()=>{
|
|
36
|
+
this.listeners.delete(listener);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async setTheme(nextTheme) {
|
|
40
|
+
this.ensureInitialized();
|
|
41
|
+
const prevTheme = this.theme;
|
|
42
|
+
const mergedTheme = mergeTheme(prevTheme, nextTheme);
|
|
43
|
+
if (isThemeEqual(prevTheme, mergedTheme)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.theme = mergedTheme;
|
|
47
|
+
applyThemeToDocument(this.theme, prevTheme);
|
|
48
|
+
if (this.cacheManager) {
|
|
49
|
+
await saveThemeToCache(this.cacheManager, this.config.persistence, this.theme);
|
|
50
|
+
}
|
|
51
|
+
this.emit(this.theme, prevTheme);
|
|
52
|
+
}
|
|
53
|
+
ensureInitialized() {
|
|
54
|
+
if (!this.initialized) {
|
|
55
|
+
throw new Error('ThemeManager must be initialized before use.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
emit(next, prev) {
|
|
59
|
+
for (const listener of this.listeners){
|
|
60
|
+
try {
|
|
61
|
+
listener(cloneTheme(next), cloneTheme(prev));
|
|
62
|
+
} catch {
|
|
63
|
+
// Keep notifying remaining listeners even if one fails.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
constructor(){
|
|
68
|
+
_define_property(this, "theme", cloneTheme(DEFAULT_THEME));
|
|
69
|
+
_define_property(this, "config", DEFAULT_CONFIG.theme);
|
|
70
|
+
_define_property(this, "listeners", new Set());
|
|
71
|
+
_define_property(this, "cacheManager", null);
|
|
72
|
+
_define_property(this, "initialized", false);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=ThemeManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/ThemeManager.ts"],"sourcesContent":["import type { StorageInstance } from '@vlian/utils';\nimport { DEFAULT_CONFIG, DEFAULT_THEME } from '../../constants';\nimport type { KernelConfig, KernelManager, KernelManagerContext, ThemeSnapshot } from '../../types';\nimport { applyThemeToDocument } from './theme.dom';\nimport { loadThemeFromCache, saveThemeToCache } from './theme.persistence';\nimport { cloneTheme, isThemeEqual, mergeTheme, normalizeTheme, type ThemeListener } from './theme.schema';\n\nexport class ThemeManager implements KernelManager<ThemeSnapshot> {\n private theme: ThemeSnapshot = cloneTheme(DEFAULT_THEME);\n private config: KernelConfig['theme'] = DEFAULT_CONFIG.theme;\n private listeners = new Set<ThemeListener>();\n private cacheManager: StorageInstance | null = null;\n private initialized = false;\n\n public async initialize(context: KernelManagerContext): Promise<void> {\n this.config = context.config.theme;\n this.cacheManager = context.cacheManager;\n\n const initialTheme = normalizeTheme(this.config.initial || {}, DEFAULT_THEME);\n this.theme = await loadThemeFromCache(this.cacheManager, this.config.persistence, initialTheme);\n\n applyThemeToDocument(this.theme);\n this.initialized = true;\n }\n\n public getTheme(): ThemeSnapshot {\n return cloneTheme(this.theme);\n }\n\n public getSnapshot(): ThemeSnapshot {\n return this.getTheme();\n }\n\n public subscribe(listener: ThemeListener): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n public async setTheme(nextTheme: ThemeSnapshot): Promise<void> {\n this.ensureInitialized();\n\n const prevTheme = this.theme;\n const mergedTheme = mergeTheme(prevTheme, nextTheme);\n\n if (isThemeEqual(prevTheme, mergedTheme)) {\n return;\n }\n\n this.theme = mergedTheme;\n applyThemeToDocument(this.theme, prevTheme);\n\n if (this.cacheManager) {\n await saveThemeToCache(this.cacheManager, this.config.persistence, this.theme);\n }\n\n this.emit(this.theme, prevTheme);\n }\n\n private ensureInitialized(): void {\n if (!this.initialized) {\n throw new Error('ThemeManager must be initialized before use.');\n }\n }\n\n private emit(next: ThemeSnapshot, prev: ThemeSnapshot): void {\n for (const listener of this.listeners) {\n try {\n listener(cloneTheme(next), cloneTheme(prev));\n } catch {\n // Keep notifying remaining listeners even if one fails.\n }\n }\n }\n}\n"],"names":["DEFAULT_CONFIG","DEFAULT_THEME","applyThemeToDocument","loadThemeFromCache","saveThemeToCache","cloneTheme","isThemeEqual","mergeTheme","normalizeTheme","ThemeManager","initialize","context","config","theme","cacheManager","initialTheme","initial","persistence","initialized","getTheme","getSnapshot","subscribe","listener","listeners","add","delete","setTheme","nextTheme","ensureInitialized","prevTheme","mergedTheme","emit","Error","next","prev","Set"],"mappings":";;;;;;;;;;;;;AACA,SAASA,cAAc,EAAEC,aAAa,QAAQ,kBAAkB;AAEhE,SAASC,oBAAoB,QAAQ,cAAc;AACnD,SAASC,kBAAkB,EAAEC,gBAAgB,QAAQ,sBAAsB;AAC3E,SAASC,UAAU,EAAEC,YAAY,EAAEC,UAAU,EAAEC,cAAc,QAA4B,iBAAiB;AAE1G,OAAO,MAAMC;IAOX,MAAaC,WAAWC,OAA6B,EAAiB;QACpE,IAAI,CAACC,MAAM,GAAGD,QAAQC,MAAM,CAACC,KAAK;QAClC,IAAI,CAACC,YAAY,GAAGH,QAAQG,YAAY;QAExC,MAAMC,eAAeP,eAAe,IAAI,CAACI,MAAM,CAACI,OAAO,IAAI,CAAC,GAAGf;QAC/D,IAAI,CAACY,KAAK,GAAG,MAAMV,mBAAmB,IAAI,CAACW,YAAY,EAAE,IAAI,CAACF,MAAM,CAACK,WAAW,EAAEF;QAElFb,qBAAqB,IAAI,CAACW,KAAK;QAC/B,IAAI,CAACK,WAAW,GAAG;IACrB;IAEOC,WAA0B;QAC/B,OAAOd,WAAW,IAAI,CAACQ,KAAK;IAC9B;IAEOO,cAA6B;QAClC,OAAO,IAAI,CAACD,QAAQ;IACtB;IAEOE,UAAUC,QAAuB,EAAc;QACpD,IAAI,CAACC,SAAS,CAACC,GAAG,CAACF;QAEnB,OAAO;YACL,IAAI,CAACC,SAAS,CAACE,MAAM,CAACH;QACxB;IACF;IAEA,MAAaI,SAASC,SAAwB,EAAiB;QAC7D,IAAI,CAACC,iBAAiB;QAEtB,MAAMC,YAAY,IAAI,CAAChB,KAAK;QAC5B,MAAMiB,cAAcvB,WAAWsB,WAAWF;QAE1C,IAAIrB,aAAauB,WAAWC,cAAc;YACxC;QACF;QAEA,IAAI,CAACjB,KAAK,GAAGiB;QACb5B,qBAAqB,IAAI,CAACW,KAAK,EAAEgB;QAEjC,IAAI,IAAI,CAACf,YAAY,EAAE;YACrB,MAAMV,iBAAiB,IAAI,CAACU,YAAY,EAAE,IAAI,CAACF,MAAM,CAACK,WAAW,EAAE,IAAI,CAACJ,KAAK;QAC/E;QAEA,IAAI,CAACkB,IAAI,CAAC,IAAI,CAAClB,KAAK,EAAEgB;IACxB;IAEQD,oBAA0B;QAChC,IAAI,CAAC,IAAI,CAACV,WAAW,EAAE;YACrB,MAAM,IAAIc,MAAM;QAClB;IACF;IAEQD,KAAKE,IAAmB,EAAEC,IAAmB,EAAQ;QAC3D,KAAK,MAAMZ,YAAY,IAAI,CAACC,SAAS,CAAE;YACrC,IAAI;gBACFD,SAASjB,WAAW4B,OAAO5B,WAAW6B;YACxC,EAAE,OAAM;YACN,wDAAwD;YAC1D;QACF;IACF;;QAnEA,uBAAQrB,SAAuBR,WAAWJ;QAC1C,uBAAQW,UAAgCZ,eAAea,KAAK;QAC5D,uBAAQU,aAAY,IAAIY;QACxB,uBAAQrB,gBAAuC;QAC/C,uBAAQI,eAAc;;AAgExB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ThemeManager", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return _ThemeManager.ThemeManager;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _ThemeManager = require("./ThemeManager");
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/index.ts"],"sourcesContent":["export { ThemeManager } from './ThemeManager';\n"],"names":["ThemeManager"],"mappings":";;;;+BAASA;;;eAAAA,0BAAY;;;8BAAQ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ThemeManager } from './ThemeManager';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/index.ts"],"sourcesContent":["export { ThemeManager } from './ThemeManager';\n"],"names":["ThemeManager"],"mappings":"AAAA,SAASA,YAAY,QAAQ,iBAAiB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get applyThemeToDocument () {
|
|
13
|
+
return applyThemeToDocument;
|
|
14
|
+
},
|
|
15
|
+
get resolveThemeMode () {
|
|
16
|
+
return resolveThemeMode;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
function canUseDom() {
|
|
20
|
+
return typeof document !== 'undefined';
|
|
21
|
+
}
|
|
22
|
+
function resolveThemeMode(theme) {
|
|
23
|
+
if (theme.mode !== 'system') {
|
|
24
|
+
return theme.mode;
|
|
25
|
+
}
|
|
26
|
+
if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
27
|
+
return 'dark';
|
|
28
|
+
}
|
|
29
|
+
return 'light';
|
|
30
|
+
}
|
|
31
|
+
function applyThemeToDocument(nextTheme, prevTheme) {
|
|
32
|
+
if (!canUseDom()) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const root = document.documentElement;
|
|
36
|
+
const nextMode = resolveThemeMode(nextTheme);
|
|
37
|
+
const prevMode = prevTheme ? resolveThemeMode(prevTheme) : undefined;
|
|
38
|
+
if (!prevMode || prevMode !== nextMode) {
|
|
39
|
+
root.classList.remove('light', 'dark');
|
|
40
|
+
root.classList.add(nextMode);
|
|
41
|
+
}
|
|
42
|
+
if (!prevTheme || prevTheme.primaryColor !== nextTheme.primaryColor) {
|
|
43
|
+
if (nextTheme.primaryColor) {
|
|
44
|
+
root.style.setProperty('--app-primary-color', nextTheme.primaryColor);
|
|
45
|
+
} else {
|
|
46
|
+
root.style.removeProperty('--app-primary-color');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const prevTokens = prevTheme?.tokens || {};
|
|
50
|
+
const nextTokens = nextTheme.tokens || {};
|
|
51
|
+
for (const token of Object.keys(prevTokens)){
|
|
52
|
+
if (!(token in nextTokens)) {
|
|
53
|
+
root.style.removeProperty(`--${token}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const [token, value] of Object.entries(nextTokens)){
|
|
57
|
+
if (!prevTheme || prevTokens[token] !== value) {
|
|
58
|
+
root.style.setProperty(`--${token}`, String(value));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=theme.dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/theme.dom.ts"],"sourcesContent":["import type { ThemeSnapshot } from '../../types';\n\nfunction canUseDom(): boolean {\n return typeof document !== 'undefined';\n}\n\nexport function resolveThemeMode(theme: ThemeSnapshot): 'light' | 'dark' {\n if (theme.mode !== 'system') {\n return theme.mode;\n }\n\n if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return 'dark';\n }\n\n return 'light';\n}\n\nexport function applyThemeToDocument(nextTheme: ThemeSnapshot, prevTheme?: ThemeSnapshot): void {\n if (!canUseDom()) {\n return;\n }\n\n const root = document.documentElement;\n const nextMode = resolveThemeMode(nextTheme);\n const prevMode = prevTheme ? resolveThemeMode(prevTheme) : undefined;\n\n if (!prevMode || prevMode !== nextMode) {\n root.classList.remove('light', 'dark');\n root.classList.add(nextMode);\n }\n\n if (!prevTheme || prevTheme.primaryColor !== nextTheme.primaryColor) {\n if (nextTheme.primaryColor) {\n root.style.setProperty('--app-primary-color', nextTheme.primaryColor);\n } else {\n root.style.removeProperty('--app-primary-color');\n }\n }\n\n const prevTokens = prevTheme?.tokens || {};\n const nextTokens = nextTheme.tokens || {};\n\n for (const token of Object.keys(prevTokens)) {\n if (!(token in nextTokens)) {\n root.style.removeProperty(`--${token}`);\n }\n }\n\n for (const [token, value] of Object.entries(nextTokens)) {\n if (!prevTheme || prevTokens[token] !== value) {\n root.style.setProperty(`--${token}`, String(value));\n }\n }\n}\n"],"names":["applyThemeToDocument","resolveThemeMode","canUseDom","document","theme","mode","window","matchMedia","matches","nextTheme","prevTheme","root","documentElement","nextMode","prevMode","undefined","classList","remove","add","primaryColor","style","setProperty","removeProperty","prevTokens","tokens","nextTokens","token","Object","keys","value","entries","String"],"mappings":";;;;;;;;;;;QAkBgBA;eAAAA;;QAZAC;eAAAA;;;AAJhB,SAASC;IACP,OAAO,OAAOC,aAAa;AAC7B;AAEO,SAASF,iBAAiBG,KAAoB;IACnD,IAAIA,MAAMC,IAAI,KAAK,UAAU;QAC3B,OAAOD,MAAMC,IAAI;IACnB;IAEA,IAAI,OAAOC,WAAW,eAAeA,OAAOC,UAAU,CAAC,gCAAgCC,OAAO,EAAE;QAC9F,OAAO;IACT;IAEA,OAAO;AACT;AAEO,SAASR,qBAAqBS,SAAwB,EAAEC,SAAyB;IACtF,IAAI,CAACR,aAAa;QAChB;IACF;IAEA,MAAMS,OAAOR,SAASS,eAAe;IACrC,MAAMC,WAAWZ,iBAAiBQ;IAClC,MAAMK,WAAWJ,YAAYT,iBAAiBS,aAAaK;IAE3D,IAAI,CAACD,YAAYA,aAAaD,UAAU;QACtCF,KAAKK,SAAS,CAACC,MAAM,CAAC,SAAS;QAC/BN,KAAKK,SAAS,CAACE,GAAG,CAACL;IACrB;IAEA,IAAI,CAACH,aAAaA,UAAUS,YAAY,KAAKV,UAAUU,YAAY,EAAE;QACnE,IAAIV,UAAUU,YAAY,EAAE;YAC1BR,KAAKS,KAAK,CAACC,WAAW,CAAC,uBAAuBZ,UAAUU,YAAY;QACtE,OAAO;YACLR,KAAKS,KAAK,CAACE,cAAc,CAAC;QAC5B;IACF;IAEA,MAAMC,aAAab,WAAWc,UAAU,CAAC;IACzC,MAAMC,aAAahB,UAAUe,MAAM,IAAI,CAAC;IAExC,KAAK,MAAME,SAASC,OAAOC,IAAI,CAACL,YAAa;QAC3C,IAAI,CAAEG,CAAAA,SAASD,UAAS,GAAI;YAC1Bd,KAAKS,KAAK,CAACE,cAAc,CAAC,CAAC,EAAE,EAAEI,OAAO;QACxC;IACF;IAEA,KAAK,MAAM,CAACA,OAAOG,MAAM,IAAIF,OAAOG,OAAO,CAACL,YAAa;QACvD,IAAI,CAACf,aAAaa,UAAU,CAACG,MAAM,KAAKG,OAAO;YAC7ClB,KAAKS,KAAK,CAACC,WAAW,CAAC,CAAC,EAAE,EAAEK,OAAO,EAAEK,OAAOF;QAC9C;IACF;AACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function canUseDom() {
|
|
2
|
+
return typeof document !== 'undefined';
|
|
3
|
+
}
|
|
4
|
+
export function resolveThemeMode(theme) {
|
|
5
|
+
if (theme.mode !== 'system') {
|
|
6
|
+
return theme.mode;
|
|
7
|
+
}
|
|
8
|
+
if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
9
|
+
return 'dark';
|
|
10
|
+
}
|
|
11
|
+
return 'light';
|
|
12
|
+
}
|
|
13
|
+
export function applyThemeToDocument(nextTheme, prevTheme) {
|
|
14
|
+
if (!canUseDom()) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const root = document.documentElement;
|
|
18
|
+
const nextMode = resolveThemeMode(nextTheme);
|
|
19
|
+
const prevMode = prevTheme ? resolveThemeMode(prevTheme) : undefined;
|
|
20
|
+
if (!prevMode || prevMode !== nextMode) {
|
|
21
|
+
root.classList.remove('light', 'dark');
|
|
22
|
+
root.classList.add(nextMode);
|
|
23
|
+
}
|
|
24
|
+
if (!prevTheme || prevTheme.primaryColor !== nextTheme.primaryColor) {
|
|
25
|
+
if (nextTheme.primaryColor) {
|
|
26
|
+
root.style.setProperty('--app-primary-color', nextTheme.primaryColor);
|
|
27
|
+
} else {
|
|
28
|
+
root.style.removeProperty('--app-primary-color');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const prevTokens = prevTheme?.tokens || {};
|
|
32
|
+
const nextTokens = nextTheme.tokens || {};
|
|
33
|
+
for (const token of Object.keys(prevTokens)){
|
|
34
|
+
if (!(token in nextTokens)) {
|
|
35
|
+
root.style.removeProperty(`--${token}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const [token, value] of Object.entries(nextTokens)){
|
|
39
|
+
if (!prevTheme || prevTokens[token] !== value) {
|
|
40
|
+
root.style.setProperty(`--${token}`, String(value));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=theme.dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/theme.dom.ts"],"sourcesContent":["import type { ThemeSnapshot } from '../../types';\n\nfunction canUseDom(): boolean {\n return typeof document !== 'undefined';\n}\n\nexport function resolveThemeMode(theme: ThemeSnapshot): 'light' | 'dark' {\n if (theme.mode !== 'system') {\n return theme.mode;\n }\n\n if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return 'dark';\n }\n\n return 'light';\n}\n\nexport function applyThemeToDocument(nextTheme: ThemeSnapshot, prevTheme?: ThemeSnapshot): void {\n if (!canUseDom()) {\n return;\n }\n\n const root = document.documentElement;\n const nextMode = resolveThemeMode(nextTheme);\n const prevMode = prevTheme ? resolveThemeMode(prevTheme) : undefined;\n\n if (!prevMode || prevMode !== nextMode) {\n root.classList.remove('light', 'dark');\n root.classList.add(nextMode);\n }\n\n if (!prevTheme || prevTheme.primaryColor !== nextTheme.primaryColor) {\n if (nextTheme.primaryColor) {\n root.style.setProperty('--app-primary-color', nextTheme.primaryColor);\n } else {\n root.style.removeProperty('--app-primary-color');\n }\n }\n\n const prevTokens = prevTheme?.tokens || {};\n const nextTokens = nextTheme.tokens || {};\n\n for (const token of Object.keys(prevTokens)) {\n if (!(token in nextTokens)) {\n root.style.removeProperty(`--${token}`);\n }\n }\n\n for (const [token, value] of Object.entries(nextTokens)) {\n if (!prevTheme || prevTokens[token] !== value) {\n root.style.setProperty(`--${token}`, String(value));\n }\n }\n}\n"],"names":["canUseDom","document","resolveThemeMode","theme","mode","window","matchMedia","matches","applyThemeToDocument","nextTheme","prevTheme","root","documentElement","nextMode","prevMode","undefined","classList","remove","add","primaryColor","style","setProperty","removeProperty","prevTokens","tokens","nextTokens","token","Object","keys","value","entries","String"],"mappings":"AAEA,SAASA;IACP,OAAO,OAAOC,aAAa;AAC7B;AAEA,OAAO,SAASC,iBAAiBC,KAAoB;IACnD,IAAIA,MAAMC,IAAI,KAAK,UAAU;QAC3B,OAAOD,MAAMC,IAAI;IACnB;IAEA,IAAI,OAAOC,WAAW,eAAeA,OAAOC,UAAU,CAAC,gCAAgCC,OAAO,EAAE;QAC9F,OAAO;IACT;IAEA,OAAO;AACT;AAEA,OAAO,SAASC,qBAAqBC,SAAwB,EAAEC,SAAyB;IACtF,IAAI,CAACV,aAAa;QAChB;IACF;IAEA,MAAMW,OAAOV,SAASW,eAAe;IACrC,MAAMC,WAAWX,iBAAiBO;IAClC,MAAMK,WAAWJ,YAAYR,iBAAiBQ,aAAaK;IAE3D,IAAI,CAACD,YAAYA,aAAaD,UAAU;QACtCF,KAAKK,SAAS,CAACC,MAAM,CAAC,SAAS;QAC/BN,KAAKK,SAAS,CAACE,GAAG,CAACL;IACrB;IAEA,IAAI,CAACH,aAAaA,UAAUS,YAAY,KAAKV,UAAUU,YAAY,EAAE;QACnE,IAAIV,UAAUU,YAAY,EAAE;YAC1BR,KAAKS,KAAK,CAACC,WAAW,CAAC,uBAAuBZ,UAAUU,YAAY;QACtE,OAAO;YACLR,KAAKS,KAAK,CAACE,cAAc,CAAC;QAC5B;IACF;IAEA,MAAMC,aAAab,WAAWc,UAAU,CAAC;IACzC,MAAMC,aAAahB,UAAUe,MAAM,IAAI,CAAC;IAExC,KAAK,MAAME,SAASC,OAAOC,IAAI,CAACL,YAAa;QAC3C,IAAI,CAAEG,CAAAA,SAASD,UAAS,GAAI;YAC1Bd,KAAKS,KAAK,CAACE,cAAc,CAAC,CAAC,EAAE,EAAEI,OAAO;QACxC;IACF;IAEA,KAAK,MAAM,CAACA,OAAOG,MAAM,IAAIF,OAAOG,OAAO,CAACL,YAAa;QACvD,IAAI,CAACf,aAAaa,UAAU,CAACG,MAAM,KAAKG,OAAO;YAC7ClB,KAAKS,KAAK,CAACC,WAAW,CAAC,CAAC,EAAE,EAAEK,OAAO,EAAEK,OAAOF;QAC9C;IACF;AACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get DEFAULT_THEME_CACHE_KEY () {
|
|
13
|
+
return DEFAULT_THEME_CACHE_KEY;
|
|
14
|
+
},
|
|
15
|
+
get loadThemeFromCache () {
|
|
16
|
+
return loadThemeFromCache;
|
|
17
|
+
},
|
|
18
|
+
get saveThemeToCache () {
|
|
19
|
+
return saveThemeToCache;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const _themeschema = require("./theme.schema");
|
|
23
|
+
const DEFAULT_THEME_CACHE_KEY = 'vlian:kernel:theme';
|
|
24
|
+
function resolvePersistenceContext(persistence) {
|
|
25
|
+
if (persistence?.enabled !== true) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
key: persistence.key || DEFAULT_THEME_CACHE_KEY
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function loadThemeFromCache(cacheManager, persistence, fallback) {
|
|
33
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
34
|
+
const safeFallback = (0, _themeschema.cloneTheme)(fallback);
|
|
35
|
+
if (!persistenceContext) {
|
|
36
|
+
return safeFallback;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const cached = await cacheManager.get(persistenceContext.key, {
|
|
40
|
+
defaultValue: safeFallback
|
|
41
|
+
});
|
|
42
|
+
return (0, _themeschema.normalizeTheme)(cached, safeFallback);
|
|
43
|
+
} catch {
|
|
44
|
+
return safeFallback;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function saveThemeToCache(cacheManager, persistence, theme) {
|
|
48
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
49
|
+
if (!persistenceContext) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
await cacheManager.set(persistenceContext.key, (0, _themeschema.cloneTheme)(theme));
|
|
54
|
+
} catch {
|
|
55
|
+
// Ignore persistence failures and keep theme updates in memory.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=theme.persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/theme.persistence.ts"],"sourcesContent":["import type { StorageInstance } from '@vlian/utils';\nimport type { PersistenceOptions, ThemeSnapshot } from '../../types';\nimport { cloneTheme, normalizeTheme } from './theme.schema';\n\nexport const DEFAULT_THEME_CACHE_KEY = 'vlian:kernel:theme';\n\ntype ResolvedPersistenceContext = {\n key: string;\n};\n\nfunction resolvePersistenceContext(\n persistence: PersistenceOptions | undefined\n): ResolvedPersistenceContext | null {\n if (persistence?.enabled !== true) {\n return null;\n }\n\n return {\n key: persistence.key || DEFAULT_THEME_CACHE_KEY,\n };\n}\n\nexport async function loadThemeFromCache(\n cacheManager: StorageInstance,\n persistence: PersistenceOptions | undefined,\n fallback: ThemeSnapshot\n): Promise<ThemeSnapshot> {\n const persistenceContext = resolvePersistenceContext(persistence);\n const safeFallback = cloneTheme(fallback);\n\n if (!persistenceContext) {\n return safeFallback;\n }\n\n try {\n const cached = await cacheManager.get<ThemeSnapshot>(persistenceContext.key, {\n defaultValue: safeFallback,\n });\n return normalizeTheme(cached, safeFallback);\n } catch {\n return safeFallback;\n }\n}\n\nexport async function saveThemeToCache(\n cacheManager: StorageInstance,\n persistence: PersistenceOptions | undefined,\n theme: ThemeSnapshot\n): Promise<void> {\n const persistenceContext = resolvePersistenceContext(persistence);\n\n if (!persistenceContext) {\n return;\n }\n\n try {\n await cacheManager.set(persistenceContext.key, cloneTheme(theme));\n } catch {\n // Ignore persistence failures and keep theme updates in memory.\n }\n}\n"],"names":["DEFAULT_THEME_CACHE_KEY","loadThemeFromCache","saveThemeToCache","resolvePersistenceContext","persistence","enabled","key","cacheManager","fallback","persistenceContext","safeFallback","cloneTheme","cached","get","defaultValue","normalizeTheme","theme","set"],"mappings":";;;;;;;;;;;QAIaA;eAAAA;;QAkBSC;eAAAA;;QAsBAC;eAAAA;;;6BA1CqB;AAEpC,MAAMF,0BAA0B;AAMvC,SAASG,0BACPC,WAA2C;IAE3C,IAAIA,aAAaC,YAAY,MAAM;QACjC,OAAO;IACT;IAEA,OAAO;QACLC,KAAKF,YAAYE,GAAG,IAAIN;IAC1B;AACF;AAEO,eAAeC,mBACpBM,YAA6B,EAC7BH,WAA2C,EAC3CI,QAAuB;IAEvB,MAAMC,qBAAqBN,0BAA0BC;IACrD,MAAMM,eAAeC,IAAAA,uBAAU,EAACH;IAEhC,IAAI,CAACC,oBAAoB;QACvB,OAAOC;IACT;IAEA,IAAI;QACF,MAAME,SAAS,MAAML,aAAaM,GAAG,CAAgBJ,mBAAmBH,GAAG,EAAE;YAC3EQ,cAAcJ;QAChB;QACA,OAAOK,IAAAA,2BAAc,EAACH,QAAQF;IAChC,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAEO,eAAeR,iBACpBK,YAA6B,EAC7BH,WAA2C,EAC3CY,KAAoB;IAEpB,MAAMP,qBAAqBN,0BAA0BC;IAErD,IAAI,CAACK,oBAAoB;QACvB;IACF;IAEA,IAAI;QACF,MAAMF,aAAaU,GAAG,CAACR,mBAAmBH,GAAG,EAAEK,IAAAA,uBAAU,EAACK;IAC5D,EAAE,OAAM;IACN,gEAAgE;IAClE;AACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { StorageInstance } from '@vlian/utils';
|
|
2
|
+
import type { PersistenceOptions, ThemeSnapshot } from '../../types';
|
|
3
|
+
export declare const DEFAULT_THEME_CACHE_KEY = "vlian:kernel:theme";
|
|
4
|
+
export declare function loadThemeFromCache(cacheManager: StorageInstance, persistence: PersistenceOptions | undefined, fallback: ThemeSnapshot): Promise<ThemeSnapshot>;
|
|
5
|
+
export declare function saveThemeToCache(cacheManager: StorageInstance, persistence: PersistenceOptions | undefined, theme: ThemeSnapshot): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { cloneTheme, normalizeTheme } from "./theme.schema";
|
|
2
|
+
export const DEFAULT_THEME_CACHE_KEY = 'vlian:kernel:theme';
|
|
3
|
+
function resolvePersistenceContext(persistence) {
|
|
4
|
+
if (persistence?.enabled !== true) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
key: persistence.key || DEFAULT_THEME_CACHE_KEY
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export async function loadThemeFromCache(cacheManager, persistence, fallback) {
|
|
12
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
13
|
+
const safeFallback = cloneTheme(fallback);
|
|
14
|
+
if (!persistenceContext) {
|
|
15
|
+
return safeFallback;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const cached = await cacheManager.get(persistenceContext.key, {
|
|
19
|
+
defaultValue: safeFallback
|
|
20
|
+
});
|
|
21
|
+
return normalizeTheme(cached, safeFallback);
|
|
22
|
+
} catch {
|
|
23
|
+
return safeFallback;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function saveThemeToCache(cacheManager, persistence, theme) {
|
|
27
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
28
|
+
if (!persistenceContext) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await cacheManager.set(persistenceContext.key, cloneTheme(theme));
|
|
33
|
+
} catch {
|
|
34
|
+
// Ignore persistence failures and keep theme updates in memory.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=theme.persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/theme.persistence.ts"],"sourcesContent":["import type { StorageInstance } from '@vlian/utils';\nimport type { PersistenceOptions, ThemeSnapshot } from '../../types';\nimport { cloneTheme, normalizeTheme } from './theme.schema';\n\nexport const DEFAULT_THEME_CACHE_KEY = 'vlian:kernel:theme';\n\ntype ResolvedPersistenceContext = {\n key: string;\n};\n\nfunction resolvePersistenceContext(\n persistence: PersistenceOptions | undefined\n): ResolvedPersistenceContext | null {\n if (persistence?.enabled !== true) {\n return null;\n }\n\n return {\n key: persistence.key || DEFAULT_THEME_CACHE_KEY,\n };\n}\n\nexport async function loadThemeFromCache(\n cacheManager: StorageInstance,\n persistence: PersistenceOptions | undefined,\n fallback: ThemeSnapshot\n): Promise<ThemeSnapshot> {\n const persistenceContext = resolvePersistenceContext(persistence);\n const safeFallback = cloneTheme(fallback);\n\n if (!persistenceContext) {\n return safeFallback;\n }\n\n try {\n const cached = await cacheManager.get<ThemeSnapshot>(persistenceContext.key, {\n defaultValue: safeFallback,\n });\n return normalizeTheme(cached, safeFallback);\n } catch {\n return safeFallback;\n }\n}\n\nexport async function saveThemeToCache(\n cacheManager: StorageInstance,\n persistence: PersistenceOptions | undefined,\n theme: ThemeSnapshot\n): Promise<void> {\n const persistenceContext = resolvePersistenceContext(persistence);\n\n if (!persistenceContext) {\n return;\n }\n\n try {\n await cacheManager.set(persistenceContext.key, cloneTheme(theme));\n } catch {\n // Ignore persistence failures and keep theme updates in memory.\n }\n}\n"],"names":["cloneTheme","normalizeTheme","DEFAULT_THEME_CACHE_KEY","resolvePersistenceContext","persistence","enabled","key","loadThemeFromCache","cacheManager","fallback","persistenceContext","safeFallback","cached","get","defaultValue","saveThemeToCache","theme","set"],"mappings":"AAEA,SAASA,UAAU,EAAEC,cAAc,QAAQ,iBAAiB;AAE5D,OAAO,MAAMC,0BAA0B,qBAAqB;AAM5D,SAASC,0BACPC,WAA2C;IAE3C,IAAIA,aAAaC,YAAY,MAAM;QACjC,OAAO;IACT;IAEA,OAAO;QACLC,KAAKF,YAAYE,GAAG,IAAIJ;IAC1B;AACF;AAEA,OAAO,eAAeK,mBACpBC,YAA6B,EAC7BJ,WAA2C,EAC3CK,QAAuB;IAEvB,MAAMC,qBAAqBP,0BAA0BC;IACrD,MAAMO,eAAeX,WAAWS;IAEhC,IAAI,CAACC,oBAAoB;QACvB,OAAOC;IACT;IAEA,IAAI;QACF,MAAMC,SAAS,MAAMJ,aAAaK,GAAG,CAAgBH,mBAAmBJ,GAAG,EAAE;YAC3EQ,cAAcH;QAChB;QACA,OAAOV,eAAeW,QAAQD;IAChC,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAEA,OAAO,eAAeI,iBACpBP,YAA6B,EAC7BJ,WAA2C,EAC3CY,KAAoB;IAEpB,MAAMN,qBAAqBP,0BAA0BC;IAErD,IAAI,CAACM,oBAAoB;QACvB;IACF;IAEA,IAAI;QACF,MAAMF,aAAaS,GAAG,CAACP,mBAAmBJ,GAAG,EAAEN,WAAWgB;IAC5D,EAAE,OAAM;IACN,gEAAgE;IAClE;AACF"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get cloneTheme () {
|
|
13
|
+
return cloneTheme;
|
|
14
|
+
},
|
|
15
|
+
get isThemeEqual () {
|
|
16
|
+
return isThemeEqual;
|
|
17
|
+
},
|
|
18
|
+
get mergeTheme () {
|
|
19
|
+
return mergeTheme;
|
|
20
|
+
},
|
|
21
|
+
get normalizeTheme () {
|
|
22
|
+
return normalizeTheme;
|
|
23
|
+
},
|
|
24
|
+
get sanitizeTokens () {
|
|
25
|
+
return sanitizeTokens;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const VALID_THEME_MODES = new Set([
|
|
29
|
+
'light',
|
|
30
|
+
'dark',
|
|
31
|
+
'system'
|
|
32
|
+
]);
|
|
33
|
+
const TOKEN_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
34
|
+
function isPlainObject(value) {
|
|
35
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
36
|
+
}
|
|
37
|
+
function hasOwnProperty(value, key) {
|
|
38
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
39
|
+
}
|
|
40
|
+
function cloneTheme(theme) {
|
|
41
|
+
return {
|
|
42
|
+
...theme,
|
|
43
|
+
...theme.tokens ? {
|
|
44
|
+
tokens: {
|
|
45
|
+
...theme.tokens
|
|
46
|
+
}
|
|
47
|
+
} : {}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function sanitizeTokens(tokens) {
|
|
51
|
+
if (!isPlainObject(tokens)) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const sanitizedTokens = {};
|
|
55
|
+
for (const [token, tokenValue] of Object.entries(tokens)){
|
|
56
|
+
if (!TOKEN_NAME_PATTERN.test(token)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (typeof tokenValue === 'string' || typeof tokenValue === 'number') {
|
|
60
|
+
sanitizedTokens[token] = tokenValue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return Object.keys(sanitizedTokens).length > 0 ? sanitizedTokens : undefined;
|
|
64
|
+
}
|
|
65
|
+
function normalizeTheme(value, fallback) {
|
|
66
|
+
const source = isPlainObject(value) ? value : {};
|
|
67
|
+
const mode = VALID_THEME_MODES.has(source.mode) ? source.mode : fallback.mode;
|
|
68
|
+
const primaryColor = typeof source.primaryColor === 'string' && source.primaryColor.trim() ? source.primaryColor : fallback.primaryColor;
|
|
69
|
+
const fallbackTokens = sanitizeTokens(fallback.tokens);
|
|
70
|
+
const incomingTokens = sanitizeTokens(source.tokens);
|
|
71
|
+
return {
|
|
72
|
+
mode,
|
|
73
|
+
...primaryColor ? {
|
|
74
|
+
primaryColor
|
|
75
|
+
} : {},
|
|
76
|
+
...incomingTokens || fallbackTokens ? {
|
|
77
|
+
tokens: {
|
|
78
|
+
...fallbackTokens || {},
|
|
79
|
+
...incomingTokens || {}
|
|
80
|
+
}
|
|
81
|
+
} : {}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function mergeTheme(current, next) {
|
|
85
|
+
const mergedTheme = {
|
|
86
|
+
mode: hasOwnProperty(next, 'mode') && VALID_THEME_MODES.has(next.mode) ? next.mode : current.mode,
|
|
87
|
+
...hasOwnProperty(next, 'primaryColor') ? typeof next.primaryColor === 'string' && next.primaryColor.trim() ? {
|
|
88
|
+
primaryColor: next.primaryColor
|
|
89
|
+
} : {} : current.primaryColor ? {
|
|
90
|
+
primaryColor: current.primaryColor
|
|
91
|
+
} : {},
|
|
92
|
+
...hasOwnProperty(next, 'tokens') ? sanitizeTokens(next.tokens) ? {
|
|
93
|
+
tokens: sanitizeTokens(next.tokens)
|
|
94
|
+
} : {} : current.tokens ? {
|
|
95
|
+
tokens: {
|
|
96
|
+
...current.tokens
|
|
97
|
+
}
|
|
98
|
+
} : {}
|
|
99
|
+
};
|
|
100
|
+
return normalizeTheme(mergedTheme, DEFAULT_EMPTY_THEME);
|
|
101
|
+
}
|
|
102
|
+
const DEFAULT_EMPTY_THEME = {
|
|
103
|
+
mode: 'light'
|
|
104
|
+
};
|
|
105
|
+
function isThemeEqual(left, right) {
|
|
106
|
+
if (left.mode !== right.mode || left.primaryColor !== right.primaryColor) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const leftTokens = left.tokens || {};
|
|
110
|
+
const rightTokens = right.tokens || {};
|
|
111
|
+
const leftKeys = Object.keys(leftTokens);
|
|
112
|
+
const rightKeys = Object.keys(rightTokens);
|
|
113
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
for (const key of leftKeys){
|
|
117
|
+
if (leftTokens[key] !== rightTokens[key]) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=theme.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/kernel/manager/theme/theme.schema.ts"],"sourcesContent":["import type { ThemeSnapshot } from '../../types';\n\nexport type ThemeListener = (next: ThemeSnapshot, prev: ThemeSnapshot) => void;\n\nconst VALID_THEME_MODES = new Set<ThemeSnapshot['mode']>(['light', 'dark', 'system']);\nconst TOKEN_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\nfunction hasOwnProperty<T extends object>(value: T, key: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\nexport function cloneTheme(theme: ThemeSnapshot): ThemeSnapshot {\n return {\n ...theme,\n ...(theme.tokens ? { tokens: { ...theme.tokens } } : {}),\n };\n}\n\nexport function sanitizeTokens(tokens: unknown): ThemeSnapshot['tokens'] {\n if (!isPlainObject(tokens)) {\n return undefined;\n }\n\n const sanitizedTokens: NonNullable<ThemeSnapshot['tokens']> = {};\n\n for (const [token, tokenValue] of Object.entries(tokens)) {\n if (!TOKEN_NAME_PATTERN.test(token)) {\n continue;\n }\n\n if (typeof tokenValue === 'string' || typeof tokenValue === 'number') {\n sanitizedTokens[token] = tokenValue;\n }\n }\n\n return Object.keys(sanitizedTokens).length > 0 ? sanitizedTokens : undefined;\n}\n\nexport function normalizeTheme(\n value: unknown,\n fallback: ThemeSnapshot\n): ThemeSnapshot {\n const source = isPlainObject(value) ? value : {};\n const mode = VALID_THEME_MODES.has(source.mode as ThemeSnapshot['mode'])\n ? (source.mode as ThemeSnapshot['mode'])\n : fallback.mode;\n const primaryColor = typeof source.primaryColor === 'string' && source.primaryColor.trim()\n ? source.primaryColor\n : fallback.primaryColor;\n const fallbackTokens = sanitizeTokens(fallback.tokens);\n const incomingTokens = sanitizeTokens(source.tokens);\n\n return {\n mode,\n ...(primaryColor ? { primaryColor } : {}),\n ...(incomingTokens || fallbackTokens\n ? { tokens: { ...(fallbackTokens || {}), ...(incomingTokens || {}) } }\n : {}),\n };\n}\n\nexport function mergeTheme(current: ThemeSnapshot, next: Partial<ThemeSnapshot>): ThemeSnapshot {\n const mergedTheme: ThemeSnapshot = {\n mode: hasOwnProperty(next, 'mode') && VALID_THEME_MODES.has(next.mode as ThemeSnapshot['mode'])\n ? (next.mode as ThemeSnapshot['mode'])\n : current.mode,\n ...(hasOwnProperty(next, 'primaryColor')\n ? (typeof next.primaryColor === 'string' && next.primaryColor.trim()\n ? { primaryColor: next.primaryColor }\n : {})\n : (current.primaryColor ? { primaryColor: current.primaryColor } : {})),\n ...(hasOwnProperty(next, 'tokens')\n ? (sanitizeTokens(next.tokens) ? { tokens: sanitizeTokens(next.tokens) } : {})\n : (current.tokens ? { tokens: { ...current.tokens } } : {})),\n };\n\n return normalizeTheme(mergedTheme, DEFAULT_EMPTY_THEME);\n}\n\nconst DEFAULT_EMPTY_THEME: ThemeSnapshot = { mode: 'light' };\n\nexport function isThemeEqual(left: ThemeSnapshot, right: ThemeSnapshot): boolean {\n if (left.mode !== right.mode || left.primaryColor !== right.primaryColor) {\n return false;\n }\n\n const leftTokens = left.tokens || {};\n const rightTokens = right.tokens || {};\n const leftKeys = Object.keys(leftTokens);\n const rightKeys = Object.keys(rightTokens);\n\n if (leftKeys.length !== rightKeys.length) {\n return false;\n }\n\n for (const key of leftKeys) {\n if (leftTokens[key] !== rightTokens[key]) {\n return false;\n }\n }\n\n return true;\n}\n"],"names":["cloneTheme","isThemeEqual","mergeTheme","normalizeTheme","sanitizeTokens","VALID_THEME_MODES","Set","TOKEN_NAME_PATTERN","isPlainObject","value","Object","prototype","toString","call","hasOwnProperty","key","theme","tokens","undefined","sanitizedTokens","token","tokenValue","entries","test","keys","length","fallback","source","mode","has","primaryColor","trim","fallbackTokens","incomingTokens","current","next","mergedTheme","DEFAULT_EMPTY_THEME","left","right","leftTokens","rightTokens","leftKeys","rightKeys"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ThemeSnapshot } from '../../types';
|
|
2
|
+
export type ThemeListener = (next: ThemeSnapshot, prev: ThemeSnapshot) => void;
|
|
3
|
+
export declare function cloneTheme(theme: ThemeSnapshot): ThemeSnapshot;
|
|
4
|
+
export declare function sanitizeTokens(tokens: unknown): ThemeSnapshot['tokens'];
|
|
5
|
+
export declare function normalizeTheme(value: unknown, fallback: ThemeSnapshot): ThemeSnapshot;
|
|
6
|
+
export declare function mergeTheme(current: ThemeSnapshot, next: Partial<ThemeSnapshot>): ThemeSnapshot;
|
|
7
|
+
export declare function isThemeEqual(left: ThemeSnapshot, right: ThemeSnapshot): boolean;
|