@shohojdhara/atomix 0.3.8 → 0.3.10
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 +22 -1
- package/dist/core.d.ts +2 -2
- package/dist/index.esm.js +104 -119
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +121 -130
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.js +55 -20
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/theme/runtime/ThemeProvider.tsx +43 -44
package/package.json
CHANGED
|
@@ -9,19 +9,20 @@ import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'
|
|
|
9
9
|
import { ThemeContext } from './ThemeContext';
|
|
10
10
|
import type { ThemeProviderProps, ThemeLoadOptions } from '../types';
|
|
11
11
|
import type { DesignTokens } from '../tokens/tokens';
|
|
12
|
+
import { createTokens } from '../tokens/tokens';
|
|
12
13
|
import { getLogger } from '../errors';
|
|
13
14
|
import { createTheme } from '../core';
|
|
14
15
|
import { injectCSS, removeCSS } from '../utils/injectCSS';
|
|
15
16
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
isServer,
|
|
18
|
+
createLocalStorageAdapter,
|
|
19
|
+
applyThemeAttributes,
|
|
20
|
+
buildThemePath,
|
|
20
21
|
} from '../utils/domUtils';
|
|
21
22
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
DEFAULT_STORAGE_KEY,
|
|
24
|
+
DEFAULT_DATA_ATTRIBUTE,
|
|
25
|
+
DEFAULT_BASE_PATH,
|
|
25
26
|
} from '../constants/constants';
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -114,11 +115,10 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
114
115
|
// If it's DesignTokens, we'll handle it in useEffect
|
|
115
116
|
return 'tokens-theme';
|
|
116
117
|
});
|
|
117
|
-
|
|
118
|
+
|
|
118
119
|
const [activeTokens, setActiveTokens] = useState<DesignTokens | null>(() => {
|
|
119
120
|
// If defaultTheme is DesignTokens, store them
|
|
120
121
|
if (defaultTheme && typeof defaultTheme !== 'string') {
|
|
121
|
-
const { createTokens } = require('../tokens/tokens');
|
|
122
122
|
return createTokens(defaultTheme);
|
|
123
123
|
}
|
|
124
124
|
return null;
|
|
@@ -163,7 +163,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
163
163
|
abortControllerRef.current.abort();
|
|
164
164
|
abortControllerRef.current = null;
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
// Clean up completed promises (keep only pending ones)
|
|
168
168
|
// In practice, completed promises are automatically garbage collected,
|
|
169
169
|
// but we can clear the ref to be explicit
|
|
@@ -187,17 +187,17 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
187
187
|
if (abortControllerRef.current) {
|
|
188
188
|
abortControllerRef.current.abort();
|
|
189
189
|
}
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
// Create new AbortController for this theme load
|
|
192
192
|
const abortController = new AbortController();
|
|
193
193
|
abortControllerRef.current = abortController;
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
setIsLoading(true);
|
|
196
196
|
setError(null);
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
try {
|
|
199
199
|
let themeName: string;
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
if (typeof theme === 'string') {
|
|
202
202
|
themeName = theme;
|
|
203
203
|
} else {
|
|
@@ -205,32 +205,31 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
205
205
|
if (abortController.signal.aborted) {
|
|
206
206
|
return;
|
|
207
207
|
}
|
|
208
|
-
|
|
208
|
+
|
|
209
209
|
// For DesignTokens, create CSS and inject it
|
|
210
210
|
const { createTheme } = await import('../core');
|
|
211
211
|
const css = createTheme(theme);
|
|
212
212
|
const themeId = 'tokens-theme';
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
// Check if aborted after async operation
|
|
215
215
|
if (abortController.signal.aborted) {
|
|
216
216
|
return;
|
|
217
217
|
}
|
|
218
|
-
|
|
218
|
+
|
|
219
219
|
// Remove any previously loaded theme CSS
|
|
220
220
|
removeCSS(`theme-${currentTheme}`);
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
// Inject new theme CSS
|
|
223
223
|
injectCSS(css, `theme-${themeId}`);
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
// Store tokens for reference
|
|
226
|
-
const { createTokens } = await import('../tokens/tokens');
|
|
227
226
|
const fullTokens = createTokens(theme);
|
|
228
|
-
|
|
227
|
+
|
|
229
228
|
// Check if aborted before state update
|
|
230
229
|
if (abortController.signal.aborted) {
|
|
231
230
|
return;
|
|
232
231
|
}
|
|
233
|
-
|
|
232
|
+
|
|
234
233
|
setActiveTokens(fullTokens);
|
|
235
234
|
setCurrentTheme(themeId);
|
|
236
235
|
handleThemeChange(fullTokens);
|
|
@@ -266,9 +265,9 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
266
265
|
resolve();
|
|
267
266
|
return;
|
|
268
267
|
}
|
|
269
|
-
|
|
268
|
+
|
|
270
269
|
const themeMetadata = themes[theme];
|
|
271
|
-
|
|
270
|
+
|
|
272
271
|
if (themeMetadata) {
|
|
273
272
|
// Build CSS path using utility function
|
|
274
273
|
const cssPath = buildThemePath(
|
|
@@ -277,28 +276,28 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
277
276
|
useMinified,
|
|
278
277
|
cdnPath
|
|
279
278
|
);
|
|
280
|
-
|
|
279
|
+
|
|
281
280
|
// Check if aborted
|
|
282
281
|
if (abortController.signal.aborted) {
|
|
283
282
|
resolve();
|
|
284
283
|
return;
|
|
285
284
|
}
|
|
286
|
-
|
|
285
|
+
|
|
287
286
|
// Load CSS file (using loadThemeCSS from domUtils)
|
|
288
287
|
const { loadThemeCSS } = await import('../utils/domUtils');
|
|
289
288
|
await loadThemeCSS(cssPath, `theme-${theme}`);
|
|
290
|
-
|
|
289
|
+
|
|
291
290
|
// Check if aborted after async operation
|
|
292
291
|
if (abortController.signal.aborted) {
|
|
293
292
|
resolve();
|
|
294
293
|
return;
|
|
295
294
|
}
|
|
296
|
-
|
|
295
|
+
|
|
297
296
|
// Remove any previously loaded theme CSS
|
|
298
297
|
removeCSS(`theme-${String(currentTheme)}`);
|
|
299
|
-
|
|
298
|
+
|
|
300
299
|
loadedThemesRef.current.add(theme);
|
|
301
|
-
|
|
300
|
+
|
|
302
301
|
setCurrentTheme(theme);
|
|
303
302
|
setActiveTokens(null);
|
|
304
303
|
handleThemeChange(theme);
|
|
@@ -312,7 +311,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
312
311
|
resolve();
|
|
313
312
|
return;
|
|
314
313
|
}
|
|
315
|
-
|
|
314
|
+
|
|
316
315
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
317
316
|
setError(error);
|
|
318
317
|
handleError(error, String(theme));
|
|
@@ -321,13 +320,13 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
321
320
|
});
|
|
322
321
|
|
|
323
322
|
themePromisesRef.current[theme] = themeLoadPromise;
|
|
324
|
-
|
|
323
|
+
|
|
325
324
|
try {
|
|
326
325
|
await themeLoadPromise;
|
|
327
326
|
} catch {
|
|
328
327
|
// Error already handled in promise
|
|
329
328
|
}
|
|
330
|
-
|
|
329
|
+
|
|
331
330
|
// Clean up completed promise after a delay to prevent memory leak
|
|
332
331
|
setTimeout(() => {
|
|
333
332
|
if (themePromisesRef.current[theme] === themeLoadPromise) {
|
|
@@ -339,7 +338,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
339
338
|
if (abortController.signal.aborted) {
|
|
340
339
|
return;
|
|
341
340
|
}
|
|
342
|
-
|
|
341
|
+
|
|
343
342
|
// For string theme that isn't in our themes record, just set the name
|
|
344
343
|
setCurrentTheme(themeName);
|
|
345
344
|
setActiveTokens(null);
|
|
@@ -350,7 +349,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
350
349
|
if (abortController.signal.aborted) {
|
|
351
350
|
return;
|
|
352
351
|
}
|
|
353
|
-
|
|
352
|
+
|
|
354
353
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
355
354
|
setError(error);
|
|
356
355
|
handleError(error, String(theme));
|
|
@@ -382,7 +381,7 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
382
381
|
useMinified,
|
|
383
382
|
cdnPath
|
|
384
383
|
);
|
|
385
|
-
|
|
384
|
+
|
|
386
385
|
// Preload CSS by fetching it
|
|
387
386
|
await fetch(cssPath);
|
|
388
387
|
loadedThemesRef.current.add(themeName);
|
|
@@ -401,11 +400,11 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
401
400
|
// For now, we'll create a mock implementation that satisfies the type
|
|
402
401
|
return {
|
|
403
402
|
// Mock implementation - in a real app this would be a full ThemeManager
|
|
404
|
-
}
|
|
403
|
+
};
|
|
405
404
|
}, []);
|
|
406
405
|
|
|
407
406
|
// Memoize available themes to prevent unnecessary recalculations
|
|
408
|
-
const availableThemes = useMemo(() =>
|
|
407
|
+
const availableThemes = useMemo(() =>
|
|
409
408
|
Object.entries(themes).map(([name, metadata]) => ({
|
|
410
409
|
...metadata,
|
|
411
410
|
name: name, // Ensure name is set from the key
|
|
@@ -425,13 +424,13 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
425
424
|
preloadTheme,
|
|
426
425
|
themeManager,
|
|
427
426
|
}), [
|
|
428
|
-
currentTheme,
|
|
429
|
-
activeTokens,
|
|
430
|
-
setTheme,
|
|
427
|
+
currentTheme,
|
|
428
|
+
activeTokens,
|
|
429
|
+
setTheme,
|
|
431
430
|
availableThemes, // Use memoized value
|
|
432
|
-
isLoading,
|
|
433
|
-
error,
|
|
434
|
-
isThemeLoaded,
|
|
431
|
+
isLoading,
|
|
432
|
+
error,
|
|
433
|
+
isThemeLoaded,
|
|
435
434
|
preloadTheme,
|
|
436
435
|
themeManager
|
|
437
436
|
]);
|