@vlian/framework 1.2.51 → 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 +222 -65
- package/dist/index.umd.js.map +1 -1
- package/dist/kernel/kernel.cjs +2 -1
- package/dist/kernel/kernel.cjs.map +1 -1
- package/dist/kernel/kernel.js +2 -1
- package/dist/kernel/kernel.js.map +1 -1
- package/dist/kernel/manager/cacheManager.cjs +8 -6
- package/dist/kernel/manager/cacheManager.cjs.map +1 -1
- package/dist/kernel/manager/cacheManager.d.ts +3 -0
- package/dist/kernel/manager/cacheManager.js +8 -6
- package/dist/kernel/manager/cacheManager.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 -14
- package/dist/kernel/manager/themeManager.js +1 -94
- package/dist/kernel/manager/themeManager.js.map +1 -1
- package/dist/kernel/types.d.ts +2 -0
- package/dist/kernel/types.js.map +1 -1
- package/dist/state.umd.js +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +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
|
|
@@ -12418,20 +12418,198 @@
|
|
|
12418
12418
|
class CacheManager {
|
|
12419
12419
|
initialize(context) {
|
|
12420
12420
|
this.snapshot = context.config.cache;
|
|
12421
|
-
|
|
12421
|
+
this.cacheIn = vlianUtils.createStorage({
|
|
12422
|
+
type: this.snapshot.storageOptions?.type || 'local',
|
|
12422
12423
|
prefix: this.snapshot.storageOptions?.prefix || 'vlian',
|
|
12423
12424
|
defaultExpire: this.snapshot.storageOptions?.defaultExpire || 24 * 60 * 60 * 1000,
|
|
12424
|
-
|
|
12425
|
-
cache: {
|
|
12426
|
-
enabled: this.snapshot.enabled
|
|
12427
|
-
}
|
|
12425
|
+
dbName: this.snapshot.storageOptions?.tableName
|
|
12428
12426
|
});
|
|
12429
12427
|
}
|
|
12428
|
+
get cache() {
|
|
12429
|
+
return this.cacheIn;
|
|
12430
|
+
}
|
|
12430
12431
|
getSnapshot() {
|
|
12431
12432
|
return this.snapshot;
|
|
12432
12433
|
}
|
|
12433
12434
|
constructor(){
|
|
12434
12435
|
_define_property$3(this, "snapshot", DEFAULT_CONFIG.cache);
|
|
12436
|
+
_define_property$3(this, "cacheIn", void 0);
|
|
12437
|
+
}
|
|
12438
|
+
}
|
|
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.
|
|
12435
12613
|
}
|
|
12436
12614
|
}
|
|
12437
12615
|
|
|
@@ -12448,50 +12626,20 @@
|
|
|
12448
12626
|
}
|
|
12449
12627
|
return obj;
|
|
12450
12628
|
}
|
|
12451
|
-
function applyThemeToDocument(theme) {
|
|
12452
|
-
if (typeof document === 'undefined') {
|
|
12453
|
-
return;
|
|
12454
|
-
}
|
|
12455
|
-
const root = document.documentElement;
|
|
12456
|
-
root.classList.remove('light', 'dark');
|
|
12457
|
-
const resolvedMode = theme.mode === 'system' ? typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' : theme.mode;
|
|
12458
|
-
root.classList.add(resolvedMode);
|
|
12459
|
-
if (theme.primaryColor) {
|
|
12460
|
-
root.style.setProperty('--app-primary-color', theme.primaryColor);
|
|
12461
|
-
}
|
|
12462
|
-
if (theme.tokens) {
|
|
12463
|
-
Object.entries(theme.tokens).forEach(([token, tokenValue])=>{
|
|
12464
|
-
root.style.setProperty(`--${token}`, String(tokenValue));
|
|
12465
|
-
});
|
|
12466
|
-
}
|
|
12467
|
-
}
|
|
12468
12629
|
class ThemeManager {
|
|
12469
12630
|
async initialize(context) {
|
|
12470
12631
|
this.config = context.config.theme;
|
|
12471
|
-
this.
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
};
|
|
12475
|
-
const persisted = await readPersistedValue(this.config.persistence);
|
|
12476
|
-
if (persisted !== null) {
|
|
12477
|
-
try {
|
|
12478
|
-
const parsed = JSON.parse(persisted);
|
|
12479
|
-
this.theme = {
|
|
12480
|
-
...this.theme,
|
|
12481
|
-
...parsed
|
|
12482
|
-
};
|
|
12483
|
-
} catch {
|
|
12484
|
-
// ignore parse errors
|
|
12485
|
-
}
|
|
12486
|
-
} else {
|
|
12487
|
-
await writePersistedValue(this.config.persistence, JSON.stringify(this.theme));
|
|
12488
|
-
}
|
|
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);
|
|
12489
12635
|
applyThemeToDocument(this.theme);
|
|
12636
|
+
this.initialized = true;
|
|
12490
12637
|
}
|
|
12491
12638
|
getTheme() {
|
|
12492
|
-
return
|
|
12493
|
-
|
|
12494
|
-
|
|
12639
|
+
return cloneTheme(this.theme);
|
|
12640
|
+
}
|
|
12641
|
+
getSnapshot() {
|
|
12642
|
+
return this.getTheme();
|
|
12495
12643
|
}
|
|
12496
12644
|
subscribe(listener) {
|
|
12497
12645
|
this.listeners.add(listener);
|
|
@@ -12499,32 +12647,40 @@
|
|
|
12499
12647
|
this.listeners.delete(listener);
|
|
12500
12648
|
};
|
|
12501
12649
|
}
|
|
12502
|
-
emit(next, prev) {
|
|
12503
|
-
this.listeners.forEach((listener)=>{
|
|
12504
|
-
listener({
|
|
12505
|
-
...next
|
|
12506
|
-
}, {
|
|
12507
|
-
...prev
|
|
12508
|
-
});
|
|
12509
|
-
});
|
|
12510
|
-
}
|
|
12511
12650
|
async setTheme(nextTheme) {
|
|
12512
|
-
|
|
12513
|
-
this.theme
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
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);
|
|
12520
12663
|
}
|
|
12521
|
-
|
|
12522
|
-
|
|
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
|
+
}
|
|
12523
12677
|
}
|
|
12524
12678
|
constructor(){
|
|
12525
|
-
_define_property$2(this, "theme", DEFAULT_THEME);
|
|
12679
|
+
_define_property$2(this, "theme", cloneTheme(DEFAULT_THEME));
|
|
12526
12680
|
_define_property$2(this, "config", DEFAULT_CONFIG.theme);
|
|
12527
12681
|
_define_property$2(this, "listeners", new Set());
|
|
12682
|
+
_define_property$2(this, "cacheManager", null);
|
|
12683
|
+
_define_property$2(this, "initialized", false);
|
|
12528
12684
|
}
|
|
12529
12685
|
}
|
|
12530
12686
|
|
|
@@ -12798,7 +12954,8 @@
|
|
|
12798
12954
|
}
|
|
12799
12955
|
const context = {
|
|
12800
12956
|
instanceId: this.instanceId,
|
|
12801
|
-
config: this.config
|
|
12957
|
+
config: this.config,
|
|
12958
|
+
cacheManager: this.cacheManager.cache
|
|
12802
12959
|
};
|
|
12803
12960
|
const initPromise = (async ()=>{
|
|
12804
12961
|
await manager.initialize(context);
|