@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
package/dist/analytics.umd.js
CHANGED
package/dist/index.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @vlian/framework v1.2.
|
|
2
|
+
* @vlian/framework v1.2.54
|
|
3
3
|
* Secra Framework - 一个现代化的低代码框架
|
|
4
4
|
* (c) 2026 Secra Framework Contributors
|
|
5
5
|
* Licensed under Apache-2.0
|
|
@@ -12437,6 +12437,182 @@
|
|
|
12437
12437
|
}
|
|
12438
12438
|
}
|
|
12439
12439
|
|
|
12440
|
+
function canUseDom() {
|
|
12441
|
+
return typeof document !== 'undefined';
|
|
12442
|
+
}
|
|
12443
|
+
function resolveThemeMode(theme) {
|
|
12444
|
+
if (theme.mode !== 'system') {
|
|
12445
|
+
return theme.mode;
|
|
12446
|
+
}
|
|
12447
|
+
if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
12448
|
+
return 'dark';
|
|
12449
|
+
}
|
|
12450
|
+
return 'light';
|
|
12451
|
+
}
|
|
12452
|
+
function applyThemeToDocument(nextTheme, prevTheme) {
|
|
12453
|
+
if (!canUseDom()) {
|
|
12454
|
+
return;
|
|
12455
|
+
}
|
|
12456
|
+
const root = document.documentElement;
|
|
12457
|
+
const nextMode = resolveThemeMode(nextTheme);
|
|
12458
|
+
const prevMode = prevTheme ? resolveThemeMode(prevTheme) : undefined;
|
|
12459
|
+
if (!prevMode || prevMode !== nextMode) {
|
|
12460
|
+
root.classList.remove('light', 'dark');
|
|
12461
|
+
root.classList.add(nextMode);
|
|
12462
|
+
}
|
|
12463
|
+
if (!prevTheme || prevTheme.primaryColor !== nextTheme.primaryColor) {
|
|
12464
|
+
if (nextTheme.primaryColor) {
|
|
12465
|
+
root.style.setProperty('--app-primary-color', nextTheme.primaryColor);
|
|
12466
|
+
} else {
|
|
12467
|
+
root.style.removeProperty('--app-primary-color');
|
|
12468
|
+
}
|
|
12469
|
+
}
|
|
12470
|
+
const prevTokens = prevTheme?.tokens || {};
|
|
12471
|
+
const nextTokens = nextTheme.tokens || {};
|
|
12472
|
+
for (const token of Object.keys(prevTokens)){
|
|
12473
|
+
if (!(token in nextTokens)) {
|
|
12474
|
+
root.style.removeProperty(`--${token}`);
|
|
12475
|
+
}
|
|
12476
|
+
}
|
|
12477
|
+
for (const [token, value] of Object.entries(nextTokens)){
|
|
12478
|
+
if (!prevTheme || prevTokens[token] !== value) {
|
|
12479
|
+
root.style.setProperty(`--${token}`, String(value));
|
|
12480
|
+
}
|
|
12481
|
+
}
|
|
12482
|
+
}
|
|
12483
|
+
|
|
12484
|
+
const VALID_THEME_MODES = new Set([
|
|
12485
|
+
'light',
|
|
12486
|
+
'dark',
|
|
12487
|
+
'system'
|
|
12488
|
+
]);
|
|
12489
|
+
const TOKEN_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
12490
|
+
function isPlainObject(value) {
|
|
12491
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
12492
|
+
}
|
|
12493
|
+
function hasOwnProperty(value, key) {
|
|
12494
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
12495
|
+
}
|
|
12496
|
+
function cloneTheme(theme) {
|
|
12497
|
+
return {
|
|
12498
|
+
...theme,
|
|
12499
|
+
...theme.tokens ? {
|
|
12500
|
+
tokens: {
|
|
12501
|
+
...theme.tokens
|
|
12502
|
+
}
|
|
12503
|
+
} : {}
|
|
12504
|
+
};
|
|
12505
|
+
}
|
|
12506
|
+
function sanitizeTokens(tokens) {
|
|
12507
|
+
if (!isPlainObject(tokens)) {
|
|
12508
|
+
return undefined;
|
|
12509
|
+
}
|
|
12510
|
+
const sanitizedTokens = {};
|
|
12511
|
+
for (const [token, tokenValue] of Object.entries(tokens)){
|
|
12512
|
+
if (!TOKEN_NAME_PATTERN.test(token)) {
|
|
12513
|
+
continue;
|
|
12514
|
+
}
|
|
12515
|
+
if (typeof tokenValue === 'string' || typeof tokenValue === 'number') {
|
|
12516
|
+
sanitizedTokens[token] = tokenValue;
|
|
12517
|
+
}
|
|
12518
|
+
}
|
|
12519
|
+
return Object.keys(sanitizedTokens).length > 0 ? sanitizedTokens : undefined;
|
|
12520
|
+
}
|
|
12521
|
+
function normalizeTheme(value, fallback) {
|
|
12522
|
+
const source = isPlainObject(value) ? value : {};
|
|
12523
|
+
const mode = VALID_THEME_MODES.has(source.mode) ? source.mode : fallback.mode;
|
|
12524
|
+
const primaryColor = typeof source.primaryColor === 'string' && source.primaryColor.trim() ? source.primaryColor : fallback.primaryColor;
|
|
12525
|
+
const fallbackTokens = sanitizeTokens(fallback.tokens);
|
|
12526
|
+
const incomingTokens = sanitizeTokens(source.tokens);
|
|
12527
|
+
return {
|
|
12528
|
+
mode,
|
|
12529
|
+
...primaryColor ? {
|
|
12530
|
+
primaryColor
|
|
12531
|
+
} : {},
|
|
12532
|
+
...incomingTokens || fallbackTokens ? {
|
|
12533
|
+
tokens: {
|
|
12534
|
+
...fallbackTokens || {},
|
|
12535
|
+
...incomingTokens || {}
|
|
12536
|
+
}
|
|
12537
|
+
} : {}
|
|
12538
|
+
};
|
|
12539
|
+
}
|
|
12540
|
+
function mergeTheme(current, next) {
|
|
12541
|
+
const mergedTheme = {
|
|
12542
|
+
mode: hasOwnProperty(next, 'mode') && VALID_THEME_MODES.has(next.mode) ? next.mode : current.mode,
|
|
12543
|
+
...hasOwnProperty(next, 'primaryColor') ? typeof next.primaryColor === 'string' && next.primaryColor.trim() ? {
|
|
12544
|
+
primaryColor: next.primaryColor
|
|
12545
|
+
} : {} : current.primaryColor ? {
|
|
12546
|
+
primaryColor: current.primaryColor
|
|
12547
|
+
} : {},
|
|
12548
|
+
...hasOwnProperty(next, 'tokens') ? sanitizeTokens(next.tokens) ? {
|
|
12549
|
+
tokens: sanitizeTokens(next.tokens)
|
|
12550
|
+
} : {} : current.tokens ? {
|
|
12551
|
+
tokens: {
|
|
12552
|
+
...current.tokens
|
|
12553
|
+
}
|
|
12554
|
+
} : {}
|
|
12555
|
+
};
|
|
12556
|
+
return normalizeTheme(mergedTheme, DEFAULT_EMPTY_THEME);
|
|
12557
|
+
}
|
|
12558
|
+
const DEFAULT_EMPTY_THEME = {
|
|
12559
|
+
mode: 'light'
|
|
12560
|
+
};
|
|
12561
|
+
function isThemeEqual(left, right) {
|
|
12562
|
+
if (left.mode !== right.mode || left.primaryColor !== right.primaryColor) {
|
|
12563
|
+
return false;
|
|
12564
|
+
}
|
|
12565
|
+
const leftTokens = left.tokens || {};
|
|
12566
|
+
const rightTokens = right.tokens || {};
|
|
12567
|
+
const leftKeys = Object.keys(leftTokens);
|
|
12568
|
+
const rightKeys = Object.keys(rightTokens);
|
|
12569
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
12570
|
+
return false;
|
|
12571
|
+
}
|
|
12572
|
+
for (const key of leftKeys){
|
|
12573
|
+
if (leftTokens[key] !== rightTokens[key]) {
|
|
12574
|
+
return false;
|
|
12575
|
+
}
|
|
12576
|
+
}
|
|
12577
|
+
return true;
|
|
12578
|
+
}
|
|
12579
|
+
|
|
12580
|
+
const DEFAULT_THEME_CACHE_KEY = 'vlian:kernel:theme';
|
|
12581
|
+
function resolvePersistenceContext(persistence) {
|
|
12582
|
+
if (persistence?.enabled !== true) {
|
|
12583
|
+
return null;
|
|
12584
|
+
}
|
|
12585
|
+
return {
|
|
12586
|
+
key: persistence.key || DEFAULT_THEME_CACHE_KEY
|
|
12587
|
+
};
|
|
12588
|
+
}
|
|
12589
|
+
async function loadThemeFromCache(cacheManager, persistence, fallback) {
|
|
12590
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
12591
|
+
const safeFallback = cloneTheme(fallback);
|
|
12592
|
+
if (!persistenceContext) {
|
|
12593
|
+
return safeFallback;
|
|
12594
|
+
}
|
|
12595
|
+
try {
|
|
12596
|
+
const cached = await cacheManager.get(persistenceContext.key, {
|
|
12597
|
+
defaultValue: safeFallback
|
|
12598
|
+
});
|
|
12599
|
+
return normalizeTheme(cached, safeFallback);
|
|
12600
|
+
} catch {
|
|
12601
|
+
return safeFallback;
|
|
12602
|
+
}
|
|
12603
|
+
}
|
|
12604
|
+
async function saveThemeToCache(cacheManager, persistence, theme) {
|
|
12605
|
+
const persistenceContext = resolvePersistenceContext(persistence);
|
|
12606
|
+
if (!persistenceContext) {
|
|
12607
|
+
return;
|
|
12608
|
+
}
|
|
12609
|
+
try {
|
|
12610
|
+
await cacheManager.set(persistenceContext.key, cloneTheme(theme));
|
|
12611
|
+
} catch {
|
|
12612
|
+
// Ignore persistence failures and keep theme updates in memory.
|
|
12613
|
+
}
|
|
12614
|
+
}
|
|
12615
|
+
|
|
12440
12616
|
function _define_property$2(obj, key, value) {
|
|
12441
12617
|
if (key in obj) {
|
|
12442
12618
|
Object.defineProperty(obj, key, {
|
|
@@ -12450,49 +12626,20 @@
|
|
|
12450
12626
|
}
|
|
12451
12627
|
return obj;
|
|
12452
12628
|
}
|
|
12453
|
-
function applyThemeToDocument(theme) {
|
|
12454
|
-
if (typeof document === 'undefined') {
|
|
12455
|
-
return;
|
|
12456
|
-
}
|
|
12457
|
-
const root = document.documentElement;
|
|
12458
|
-
root.classList.remove('light', 'dark');
|
|
12459
|
-
const resolvedMode = theme.mode === 'system' ? typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' : theme.mode;
|
|
12460
|
-
root.classList.add(resolvedMode);
|
|
12461
|
-
if (theme.primaryColor) {
|
|
12462
|
-
root.style.setProperty('--app-primary-color', theme.primaryColor);
|
|
12463
|
-
}
|
|
12464
|
-
if (theme.tokens) {
|
|
12465
|
-
Object.entries(theme.tokens).forEach(([token, tokenValue])=>{
|
|
12466
|
-
root.style.setProperty(`--${token}`, String(tokenValue));
|
|
12467
|
-
});
|
|
12468
|
-
}
|
|
12469
|
-
}
|
|
12470
12629
|
class ThemeManager {
|
|
12471
12630
|
async initialize(context) {
|
|
12472
12631
|
this.config = context.config.theme;
|
|
12473
|
-
this.
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
};
|
|
12477
|
-
this.cache = context.cacheManager;
|
|
12478
|
-
const { key = "vlian:kernel:theme" } = this.config.persistence || {};
|
|
12479
|
-
const persisted = await this.cache.get(key, {
|
|
12480
|
-
defaultValue: this.theme
|
|
12481
|
-
});
|
|
12482
|
-
if (persisted !== null) {
|
|
12483
|
-
this.theme = {
|
|
12484
|
-
...this.theme,
|
|
12485
|
-
...persisted
|
|
12486
|
-
};
|
|
12487
|
-
} else {
|
|
12488
|
-
await this.cache.set(key, persisted);
|
|
12489
|
-
}
|
|
12632
|
+
this.cacheManager = context.cacheManager;
|
|
12633
|
+
const initialTheme = normalizeTheme(this.config.initial || {}, DEFAULT_THEME);
|
|
12634
|
+
this.theme = await loadThemeFromCache(this.cacheManager, this.config.persistence, initialTheme);
|
|
12490
12635
|
applyThemeToDocument(this.theme);
|
|
12636
|
+
this.initialized = true;
|
|
12491
12637
|
}
|
|
12492
12638
|
getTheme() {
|
|
12493
|
-
return
|
|
12494
|
-
|
|
12495
|
-
|
|
12639
|
+
return cloneTheme(this.theme);
|
|
12640
|
+
}
|
|
12641
|
+
getSnapshot() {
|
|
12642
|
+
return this.getTheme();
|
|
12496
12643
|
}
|
|
12497
12644
|
subscribe(listener) {
|
|
12498
12645
|
this.listeners.add(listener);
|
|
@@ -12500,34 +12647,40 @@
|
|
|
12500
12647
|
this.listeners.delete(listener);
|
|
12501
12648
|
};
|
|
12502
12649
|
}
|
|
12503
|
-
emit(next, prev) {
|
|
12504
|
-
this.listeners.forEach((listener)=>{
|
|
12505
|
-
listener({
|
|
12506
|
-
...next
|
|
12507
|
-
}, {
|
|
12508
|
-
...prev
|
|
12509
|
-
});
|
|
12510
|
-
});
|
|
12511
|
-
}
|
|
12512
12650
|
async setTheme(nextTheme) {
|
|
12513
|
-
|
|
12514
|
-
this.theme
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12651
|
+
this.ensureInitialized();
|
|
12652
|
+
const prevTheme = this.theme;
|
|
12653
|
+
const mergedTheme = mergeTheme(prevTheme, nextTheme);
|
|
12654
|
+
if (isThemeEqual(prevTheme, mergedTheme)) {
|
|
12655
|
+
return;
|
|
12656
|
+
}
|
|
12657
|
+
this.theme = mergedTheme;
|
|
12658
|
+
applyThemeToDocument(this.theme, prevTheme);
|
|
12659
|
+
if (this.cacheManager) {
|
|
12660
|
+
await saveThemeToCache(this.cacheManager, this.config.persistence, this.theme);
|
|
12661
|
+
}
|
|
12662
|
+
this.emit(this.theme, prevTheme);
|
|
12522
12663
|
}
|
|
12523
|
-
|
|
12524
|
-
|
|
12664
|
+
ensureInitialized() {
|
|
12665
|
+
if (!this.initialized) {
|
|
12666
|
+
throw new Error('ThemeManager must be initialized before use.');
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
emit(next, prev) {
|
|
12670
|
+
for (const listener of this.listeners){
|
|
12671
|
+
try {
|
|
12672
|
+
listener(cloneTheme(next), cloneTheme(prev));
|
|
12673
|
+
} catch {
|
|
12674
|
+
// Keep notifying remaining listeners even if one fails.
|
|
12675
|
+
}
|
|
12676
|
+
}
|
|
12525
12677
|
}
|
|
12526
12678
|
constructor(){
|
|
12527
|
-
_define_property$2(this, "theme", DEFAULT_THEME);
|
|
12679
|
+
_define_property$2(this, "theme", cloneTheme(DEFAULT_THEME));
|
|
12528
12680
|
_define_property$2(this, "config", DEFAULT_CONFIG.theme);
|
|
12529
12681
|
_define_property$2(this, "listeners", new Set());
|
|
12530
|
-
_define_property$2(this, "
|
|
12682
|
+
_define_property$2(this, "cacheManager", null);
|
|
12683
|
+
_define_property$2(this, "initialized", false);
|
|
12531
12684
|
}
|
|
12532
12685
|
}
|
|
12533
12686
|
|