@shohojdhara/atomix 0.3.0 → 0.3.2
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 +0 -1
- package/README.md +3 -5
- package/dist/atomix.css +753 -643
- package/dist/atomix.min.css +3 -5
- package/dist/index.d.ts +3075 -247
- package/dist/index.esm.js +20412 -16601
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +20379 -16605
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -11
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +21 -32
- package/src/components/AtomixGlass/AtomixGlass.tsx +55 -42
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +205 -57
- package/src/components/AtomixGlass/GlassFilter.tsx +22 -8
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +221 -0
- package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -3
- package/src/components/AtomixGlass/shader-utils.ts +8 -0
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +319 -100
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +601 -105
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +30 -12
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +173 -38
- package/src/components/AtomixGlass/stories/ShaderVariants.stories.tsx +18 -18
- package/src/components/AtomixGlass/stories/shared-components.tsx +27 -5
- package/src/components/Button/Button.tsx +62 -17
- package/src/components/Callout/Callout.test.tsx +8 -14
- package/src/components/Card/Card.tsx +103 -1
- package/src/components/Card/index.ts +3 -2
- package/src/components/Icon/index.ts +1 -1
- package/src/components/Modal/Modal.stories.tsx +29 -38
- package/src/components/Modal/Modal.tsx +4 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +49 -41
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +63 -24
- package/src/components/Popover/Popover.tsx +1 -1
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +977 -400
- package/src/components/VideoPlayer/VideoPlayer.tsx +1 -6
- package/src/lib/composables/shared-mouse-tracker.ts +133 -0
- package/src/lib/composables/useAtomixGlass.ts +333 -145
- package/src/lib/index.ts +1 -4
- package/src/lib/theme/composeTheme.ts +375 -0
- package/src/lib/theme/config/index.ts +21 -0
- package/src/lib/theme/config/loader.ts +276 -0
- package/src/lib/theme/config/types.ts +98 -0
- package/src/lib/theme/config/validator.ts +326 -0
- package/src/lib/theme/constants.ts +183 -0
- package/src/lib/theme/core/ThemeCache.ts +283 -0
- package/src/lib/theme/core/ThemeEngine.test.ts +146 -0
- package/src/lib/theme/core/ThemeEngine.ts +657 -0
- package/src/lib/theme/core/ThemeRegistry.ts +284 -0
- package/src/lib/theme/core/ThemeValidator.ts +530 -0
- package/src/lib/theme/core/index.ts +24 -0
- package/src/lib/theme/createTheme.ts +521 -0
- package/src/lib/theme/devtools/CLI.ts +279 -0
- package/src/lib/theme/devtools/Inspector.tsx +594 -0
- package/src/lib/theme/devtools/Preview.tsx +392 -0
- package/src/lib/theme/devtools/index.ts +21 -0
- package/src/lib/theme/errors.test.ts +207 -0
- package/src/lib/theme/errors.ts +233 -0
- package/src/lib/theme/generateCSSVariables.ts +797 -0
- package/src/lib/theme/generators/CSSGenerator.ts +311 -0
- package/src/lib/theme/generators/ConfigGenerator.ts +287 -0
- package/src/lib/theme/generators/TypeGenerator.ts +228 -0
- package/src/lib/theme/generators/index.ts +21 -0
- package/src/lib/theme/i18n/index.ts +9 -0
- package/src/lib/theme/i18n/rtl.ts +325 -0
- package/src/lib/theme/index.ts +221 -10
- package/src/lib/theme/monitoring/ThemeAnalytics.ts +409 -0
- package/src/lib/theme/monitoring/index.ts +17 -0
- package/src/lib/theme/overrides/ComponentOverrides.ts +243 -0
- package/src/lib/theme/overrides/index.ts +15 -0
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +233 -0
- package/src/lib/theme/runtime/ThemeManager.test.ts +176 -0
- package/src/lib/theme/runtime/ThemeManager.ts +442 -0
- package/src/lib/theme/runtime/ThemeProvider.tsx +318 -0
- package/src/lib/theme/runtime/index.ts +17 -0
- package/src/lib/theme/runtime/useTheme.ts +52 -0
- package/src/lib/theme/studio/ThemeStudio.tsx +312 -0
- package/src/lib/theme/studio/index.ts +8 -0
- package/src/lib/theme/themeUtils.ts +333 -0
- package/src/lib/theme/types.ts +340 -9
- package/src/lib/theme/utils.ts +23 -22
- package/src/lib/theme/whitelabel/WhiteLabelManager.ts +364 -0
- package/src/lib/theme/whitelabel/index.ts +13 -0
- package/src/lib/types/components.ts +148 -59
- package/src/styles/01-settings/_index.scss +2 -2
- package/src/styles/01-settings/_settings.badge.scss +3 -3
- package/src/styles/01-settings/_settings.border-radius.scss +1 -1
- package/src/styles/01-settings/_settings.callout.scss +1 -1
- package/src/styles/01-settings/_settings.card.scss +1 -1
- package/src/styles/01-settings/{_settings.maps.scss → _settings.design-tokens.scss} +163 -49
- package/src/styles/01-settings/_settings.input.scss +1 -1
- package/src/styles/01-settings/_settings.modal.scss +1 -1
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +14 -13
- package/src/styles/01-settings/_settings.upload.scss +1 -1
- package/src/styles/03-generic/_generic.root.scss +131 -50
- package/src/styles/05-objects/_objects.block.scss +1 -1
- package/src/styles/06-components/_components.atomix-glass.scss +20 -22
- package/src/styles/06-components/_components.badge.scss +2 -2
- package/src/styles/06-components/_components.button.scss +1 -1
- package/src/styles/06-components/_components.callout.scss +1 -1
- package/src/styles/06-components/_components.card.scss +74 -2
- package/src/styles/06-components/_components.chart.scss +3 -3
- package/src/styles/06-components/_components.dropdown.scss +6 -0
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.list-group.scss +1 -1
- package/src/styles/06-components/_components.list.scss +1 -1
- package/src/styles/06-components/_components.menu.scss +1 -1
- package/src/styles/06-components/_components.messages.scss +1 -1
- package/src/styles/06-components/_components.modal.scss +7 -2
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.popover.scss +10 -0
- package/src/styles/06-components/_components.product-review.scss +1 -1
- package/src/styles/06-components/_components.progress.scss +1 -1
- package/src/styles/06-components/_components.rating.scss +1 -1
- package/src/styles/06-components/_components.spinner.scss +1 -1
- package/src/styles/99-utilities/_utilities.background.scss +1 -1
- package/src/styles/99-utilities/_utilities.border.scss +28 -59
- package/src/styles/99-utilities/_utilities.gradient.scss +12 -0
- package/src/styles/99-utilities/_utilities.link.scss +1 -1
- package/src/styles/99-utilities/_utilities.position.scss +8 -15
- package/src/styles/99-utilities/_utilities.scss +2 -0
- package/src/styles/99-utilities/_utilities.spacing.scss +76 -121
- package/src/styles/99-utilities/_utilities.text.scss +31 -50
- package/dist/themes/applemix.css +0 -15411
- package/dist/themes/applemix.min.css +0 -72
- package/dist/themes/boomdevs.css +0 -15001
- package/dist/themes/boomdevs.min.css +0 -405
- package/dist/themes/esrar.css +0 -17195
- package/dist/themes/esrar.min.css +0 -189
- package/dist/themes/flashtrade.css +0 -16408
- package/dist/themes/flashtrade.min.css +0 -192
- package/dist/themes/mashroom.css +0 -29900
- package/dist/themes/mashroom.min.css +0 -403
- package/dist/themes/shaj-default.css +0 -16024
- package/dist/themes/shaj-default.min.css +0 -500
- package/src/lib/theme/ThemeManager.stories.tsx +0 -472
- package/src/lib/theme/ThemeManager.test.ts +0 -186
- package/src/lib/theme/ThemeManager.ts +0 -501
- package/src/lib/theme/ThemeProvider.tsx +0 -227
- package/src/lib/theme/useTheme.test.tsx +0 -66
- package/src/lib/theme/useTheme.ts +0 -80
- package/src/lib/theme/utils.test.ts +0 -140
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Cache
|
|
3
|
+
*
|
|
4
|
+
* Performance caching layer for loaded themes (CSS and JS)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Theme } from '../types';
|
|
8
|
+
import { DEFAULT_CACHE_CONFIG } from '../constants';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Cache entry for CSS theme
|
|
12
|
+
*/
|
|
13
|
+
interface CSSCacheEntry {
|
|
14
|
+
type: 'css' | 'js';
|
|
15
|
+
themeId: string;
|
|
16
|
+
cssContent?: string;
|
|
17
|
+
loaded: boolean;
|
|
18
|
+
loading: Promise<void> | null;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Cache entry for JS theme
|
|
24
|
+
*/
|
|
25
|
+
interface JSCacheEntry {
|
|
26
|
+
type: 'js';
|
|
27
|
+
themeId: string;
|
|
28
|
+
theme: Theme;
|
|
29
|
+
loaded: boolean;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type CacheEntry = CSSCacheEntry | JSCacheEntry;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Theme cache configuration
|
|
37
|
+
*/
|
|
38
|
+
interface CacheConfig {
|
|
39
|
+
/** Maximum cache size (number of themes) */
|
|
40
|
+
maxSize?: number;
|
|
41
|
+
/** Cache TTL in milliseconds (0 = no expiration) */
|
|
42
|
+
ttl?: number;
|
|
43
|
+
/** Enable cache */
|
|
44
|
+
enabled?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Default cache configuration
|
|
49
|
+
*/
|
|
50
|
+
const DEFAULT_CONFIG: Required<CacheConfig> = {
|
|
51
|
+
...DEFAULT_CACHE_CONFIG,
|
|
52
|
+
enabled: true,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Theme Cache
|
|
57
|
+
*
|
|
58
|
+
* Manages caching of loaded themes for performance optimization
|
|
59
|
+
*/
|
|
60
|
+
export class ThemeCache {
|
|
61
|
+
private cache: Map<string, CacheEntry> = new Map();
|
|
62
|
+
private config: Required<CacheConfig>;
|
|
63
|
+
private accessOrder: string[] = []; // For LRU eviction
|
|
64
|
+
|
|
65
|
+
constructor(config: CacheConfig = {}) {
|
|
66
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get cached CSS theme
|
|
71
|
+
*/
|
|
72
|
+
getCSS(themeId: string): CSSCacheEntry | null {
|
|
73
|
+
if (!this.config.enabled) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const entry = this.cache.get(themeId);
|
|
78
|
+
if (!entry || entry.type !== 'css') {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check TTL
|
|
83
|
+
if (this.config.ttl > 0) {
|
|
84
|
+
const age = Date.now() - entry.timestamp;
|
|
85
|
+
if (age > this.config.ttl) {
|
|
86
|
+
this.cache.delete(themeId);
|
|
87
|
+
this.removeFromAccessOrder(themeId);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Update access order (LRU)
|
|
93
|
+
this.updateAccessOrder(themeId);
|
|
94
|
+
|
|
95
|
+
return entry;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get cached JS theme
|
|
100
|
+
*/
|
|
101
|
+
getJS(themeId: string): JSCacheEntry | null {
|
|
102
|
+
if (!this.config.enabled) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const entry = this.cache.get(themeId);
|
|
107
|
+
if (!entry || entry.type !== 'js') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check TTL
|
|
112
|
+
if (this.config.ttl > 0) {
|
|
113
|
+
const age = Date.now() - entry.timestamp;
|
|
114
|
+
if (age > this.config.ttl) {
|
|
115
|
+
this.cache.delete(themeId);
|
|
116
|
+
this.removeFromAccessOrder(themeId);
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Update access order (LRU)
|
|
122
|
+
this.updateAccessOrder(themeId);
|
|
123
|
+
|
|
124
|
+
return entry as JSCacheEntry;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Set CSS theme cache entry
|
|
129
|
+
*/
|
|
130
|
+
setCSS(themeId: string, entry: Partial<CSSCacheEntry>): void {
|
|
131
|
+
if (!this.config.enabled) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Evict if needed
|
|
136
|
+
this.evictIfNeeded();
|
|
137
|
+
|
|
138
|
+
const existing = this.cache.get(themeId);
|
|
139
|
+
const cacheEntry: CSSCacheEntry = {
|
|
140
|
+
type: 'css',
|
|
141
|
+
themeId,
|
|
142
|
+
loaded: false,
|
|
143
|
+
loading: null,
|
|
144
|
+
timestamp: Date.now(),
|
|
145
|
+
...existing,
|
|
146
|
+
...entry,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
this.cache.set(themeId, cacheEntry);
|
|
150
|
+
this.updateAccessOrder(themeId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Set JS theme cache entry
|
|
155
|
+
*/
|
|
156
|
+
setJS(themeId: string, theme: Theme): void {
|
|
157
|
+
if (!this.config.enabled) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Evict if needed
|
|
162
|
+
this.evictIfNeeded();
|
|
163
|
+
|
|
164
|
+
const cacheEntry: JSCacheEntry = {
|
|
165
|
+
type: 'js',
|
|
166
|
+
themeId,
|
|
167
|
+
theme,
|
|
168
|
+
loaded: true,
|
|
169
|
+
timestamp: Date.now(),
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
this.cache.set(themeId, cacheEntry);
|
|
173
|
+
this.updateAccessOrder(themeId);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Check if theme is cached
|
|
178
|
+
*/
|
|
179
|
+
has(themeId: string): boolean {
|
|
180
|
+
if (!this.config.enabled) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const entry = this.cache.get(themeId);
|
|
185
|
+
if (!entry) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Check TTL
|
|
190
|
+
if (this.config.ttl > 0) {
|
|
191
|
+
const age = Date.now() - entry.timestamp;
|
|
192
|
+
if (age > this.config.ttl) {
|
|
193
|
+
this.cache.delete(themeId);
|
|
194
|
+
this.removeFromAccessOrder(themeId);
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Remove theme from cache
|
|
204
|
+
*/
|
|
205
|
+
delete(themeId: string): boolean {
|
|
206
|
+
const deleted = this.cache.delete(themeId);
|
|
207
|
+
if (deleted) {
|
|
208
|
+
this.removeFromAccessOrder(themeId);
|
|
209
|
+
}
|
|
210
|
+
return deleted;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Clear all cache
|
|
215
|
+
*/
|
|
216
|
+
clear(): void {
|
|
217
|
+
this.cache.clear();
|
|
218
|
+
this.accessOrder = [];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get cache statistics
|
|
223
|
+
*/
|
|
224
|
+
getStats(): {
|
|
225
|
+
size: number;
|
|
226
|
+
maxSize: number;
|
|
227
|
+
cssThemes: number;
|
|
228
|
+
jsThemes: number;
|
|
229
|
+
} {
|
|
230
|
+
let cssThemes = 0;
|
|
231
|
+
let jsThemes = 0;
|
|
232
|
+
|
|
233
|
+
for (const entry of this.cache.values()) {
|
|
234
|
+
if (entry.type === 'css') {
|
|
235
|
+
cssThemes++;
|
|
236
|
+
} else {
|
|
237
|
+
jsThemes++;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
size: this.cache.size,
|
|
243
|
+
maxSize: this.config.maxSize,
|
|
244
|
+
cssThemes,
|
|
245
|
+
jsThemes,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Update access order for LRU
|
|
251
|
+
*/
|
|
252
|
+
private updateAccessOrder(themeId: string): void {
|
|
253
|
+
this.removeFromAccessOrder(themeId);
|
|
254
|
+
this.accessOrder.push(themeId);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Remove from access order
|
|
259
|
+
*/
|
|
260
|
+
private removeFromAccessOrder(themeId: string): void {
|
|
261
|
+
const index = this.accessOrder.indexOf(themeId);
|
|
262
|
+
if (index > -1) {
|
|
263
|
+
this.accessOrder.splice(index, 1);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Evict least recently used entries if cache is full
|
|
269
|
+
*/
|
|
270
|
+
private evictIfNeeded(): void {
|
|
271
|
+
if (this.cache.size < this.config.maxSize) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Evict least recently used (first in access order)
|
|
276
|
+
while (this.cache.size >= this.config.maxSize && this.accessOrder.length > 0) {
|
|
277
|
+
const lruThemeId = this.accessOrder.shift();
|
|
278
|
+
if (lruThemeId) {
|
|
279
|
+
this.cache.delete(lruThemeId);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThemeEngine Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the ThemeEngine class
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
|
+
import { ThemeEngine } from './ThemeEngine';
|
|
9
|
+
import { ThemeError, ThemeErrorCode } from '../errors';
|
|
10
|
+
|
|
11
|
+
// Mock dependencies
|
|
12
|
+
vi.mock('./ThemeRegistry');
|
|
13
|
+
vi.mock('./ThemeCache');
|
|
14
|
+
vi.mock('./ThemeValidator');
|
|
15
|
+
vi.mock('../utils', () => ({
|
|
16
|
+
isBrowser: () => true,
|
|
17
|
+
isServer: () => false,
|
|
18
|
+
loadThemeCSS: vi.fn().mockResolvedValue(undefined),
|
|
19
|
+
removeThemeCSS: vi.fn(),
|
|
20
|
+
applyThemeAttributes: vi.fn(),
|
|
21
|
+
}));
|
|
22
|
+
vi.mock('../generateCSSVariables', () => ({
|
|
23
|
+
generateCSSVariables: vi.fn().mockReturnValue(':root { --test: value; }'),
|
|
24
|
+
injectCSS: vi.fn(),
|
|
25
|
+
removeInjectedCSS: vi.fn(),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
describe('ThemeEngine', () => {
|
|
29
|
+
let engine: ThemeEngine;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.clearAllMocks();
|
|
33
|
+
engine = new ThemeEngine({
|
|
34
|
+
basePath: '/themes',
|
|
35
|
+
dataAttribute: 'data-theme',
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
vi.restoreAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('constructor', () => {
|
|
44
|
+
it('should create ThemeEngine with default config', () => {
|
|
45
|
+
const defaultEngine = new ThemeEngine();
|
|
46
|
+
expect(defaultEngine).toBeInstanceOf(ThemeEngine);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should create ThemeEngine with custom config', () => {
|
|
50
|
+
const customEngine = new ThemeEngine({
|
|
51
|
+
basePath: '/custom',
|
|
52
|
+
useMinified: true,
|
|
53
|
+
enableCache: false,
|
|
54
|
+
});
|
|
55
|
+
expect(customEngine).toBeInstanceOf(ThemeEngine);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('initialize', () => {
|
|
60
|
+
it('should initialize engine', async () => {
|
|
61
|
+
await expect(engine.initialize()).resolves.not.toThrow();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('getCurrentTheme', () => {
|
|
66
|
+
it('should return null when no theme is set', () => {
|
|
67
|
+
expect(engine.getCurrentTheme()).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('getActiveTheme', () => {
|
|
72
|
+
it('should return null when no theme is active', () => {
|
|
73
|
+
expect(engine.getActiveTheme()).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('isThemeLoaded', () => {
|
|
78
|
+
it('should return false for unloaded theme', () => {
|
|
79
|
+
expect(engine.isThemeLoaded('non-existent')).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('event listeners', () => {
|
|
84
|
+
it('should add change listener', () => {
|
|
85
|
+
const listener = vi.fn();
|
|
86
|
+
engine.on('change', listener);
|
|
87
|
+
expect(() => engine.on('change', listener)).not.toThrow();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should remove change listener', () => {
|
|
91
|
+
const listener = vi.fn();
|
|
92
|
+
engine.on('change', listener);
|
|
93
|
+
engine.off('change', listener);
|
|
94
|
+
expect(() => engine.off('change', listener)).not.toThrow();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should add load listener', () => {
|
|
98
|
+
const listener = vi.fn();
|
|
99
|
+
engine.on('load', listener);
|
|
100
|
+
expect(() => engine.on('load', listener)).not.toThrow();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should add error listener', () => {
|
|
104
|
+
const listener = vi.fn();
|
|
105
|
+
engine.on('error', listener);
|
|
106
|
+
expect(() => engine.on('error', listener)).not.toThrow();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should add revert listener', () => {
|
|
110
|
+
const listener = vi.fn();
|
|
111
|
+
engine.on('revert', listener);
|
|
112
|
+
expect(() => engine.on('revert', listener)).not.toThrow();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('failed themes tracking', () => {
|
|
117
|
+
it('should clear failed themes', () => {
|
|
118
|
+
engine.clearFailedThemes();
|
|
119
|
+
expect(() => engine.clearFailedThemes()).not.toThrow();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should clear specific failed theme', () => {
|
|
123
|
+
engine.clearFailedTheme('test-theme');
|
|
124
|
+
expect(() => engine.clearFailedTheme('test-theme')).not.toThrow();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should check if theme has failed', () => {
|
|
128
|
+
const hasFailed = engine.hasFailedTheme('test-theme');
|
|
129
|
+
expect(typeof hasFailed).toBe('boolean');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('getRegistry', () => {
|
|
134
|
+
it('should return registry instance', () => {
|
|
135
|
+
const registry = engine.getRegistry();
|
|
136
|
+
expect(registry).toBeDefined();
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('getCache', () => {
|
|
141
|
+
it('should return cache instance', () => {
|
|
142
|
+
const cache = engine.getCache();
|
|
143
|
+
expect(cache).toBeDefined();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|