@shohojdhara/atomix 0.3.4 → 0.3.5
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/atomix.css +9 -10
- package/dist/atomix.css.map +1 -0
- package/dist/atomix.min.css +15108 -11
- package/dist/atomix.min.css.map +1 -0
- package/dist/charts.d.ts +1929 -0
- package/dist/charts.js +6482 -0
- package/dist/charts.js.map +1 -0
- package/dist/core.d.ts +1289 -0
- package/dist/core.js +3357 -0
- package/dist/core.js.map +1 -0
- package/dist/forms.d.ts +1085 -0
- package/dist/forms.js +2450 -0
- package/dist/forms.js.map +1 -0
- package/dist/heavy.d.ts +636 -0
- package/dist/heavy.js +4550 -0
- package/dist/heavy.js.map +1 -0
- package/dist/index.d.ts +5161 -4990
- package/dist/index.esm.js +1457 -784
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1473 -790
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.d.ts +300 -0
- package/dist/layout.js +336 -0
- package/dist/layout.js.map +1 -0
- package/dist/theme.d.ts +1992 -0
- package/dist/theme.js +5348 -0
- package/dist/theme.js.map +1 -0
- package/package.json +66 -20
- package/scripts/atomix-cli.js +544 -16
- package/scripts/cli/__tests__/cli-commands.test.js +204 -0
- package/scripts/cli/__tests__/utils.test.js +201 -0
- package/scripts/cli/__tests__/vitest.config.js +26 -0
- package/scripts/cli/interactive-init.js +1 -1
- package/scripts/cli/token-manager.js +32 -7
- package/scripts/cli/utils.js +347 -0
- package/src/components/Accordion/Accordion.tsx +5 -54
- package/src/components/Accordion/index.ts +1 -1
- package/src/components/Avatar/Avatar.tsx +3 -3
- package/src/components/Badge/Badge.tsx +3 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
- package/src/components/Card/ElevationCard.tsx +1 -1
- package/src/components/Chart/AnimatedChart.tsx +19 -17
- package/src/components/Chart/AreaChart.tsx +5 -1
- package/src/components/Chart/BarChart.tsx +1 -0
- package/src/components/Chart/BubbleChart.tsx +6 -5
- package/src/components/Chart/ChartToolbar.tsx +1 -0
- package/src/components/Chart/FunnelChart.tsx +1 -1
- package/src/components/Chart/RadarChart.tsx +19 -12
- package/src/components/Chart/ScatterChart.tsx +3 -3
- package/src/components/Chart/TreemapChart.tsx +2 -1
- package/src/components/Chart/WaterfallChart.tsx +0 -1
- package/src/components/Chart/types.ts +12 -2
- package/src/components/Chart/utils.ts +4 -3
- package/src/components/DataTable/DataTable.tsx +3 -3
- package/src/components/Dropdown/Dropdown.tsx +12 -9
- package/src/components/Footer/FooterSection.tsx +3 -3
- package/src/components/Form/Checkbox.tsx +3 -3
- package/src/components/Form/Input.tsx +4 -2
- package/src/components/Form/Radio.tsx +3 -3
- package/src/components/Form/Select.tsx +3 -3
- package/src/components/Form/Textarea.tsx +4 -2
- package/src/components/List/List.stories.tsx +3 -3
- package/src/components/List/List.tsx +3 -3
- package/src/components/List/ListGroup.tsx +3 -1
- package/src/components/Modal/Modal.tsx +3 -3
- package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
- package/src/components/Navigation/Menu/Menu.tsx +9 -3
- package/src/components/Pagination/Pagination.tsx +6 -5
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
- package/src/components/Popover/Popover.tsx +4 -4
- package/src/components/Progress/Progress.tsx +6 -2
- package/src/components/Rating/Rating.tsx +5 -2
- package/src/components/Slider/Slider.tsx +10 -9
- package/src/components/Spinner/Spinner.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/index.ts +5 -2
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
- package/src/lib/composables/useChartPerformance.ts +102 -78
- package/src/lib/composables/useChartScale.ts +10 -0
- package/src/lib/composables/useHero.ts +9 -2
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
- package/src/lib/composables/useSideMenu.ts +1 -0
- package/src/lib/composables/useVideoPlayer.ts +3 -2
- package/src/lib/config/loader.ts +55 -13
- package/src/lib/hooks/index.ts +0 -1
- package/src/lib/hooks/useComponentCustomization.ts +10 -14
- package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
- package/src/lib/patterns/index.ts +2 -2
- package/src/lib/patterns/slots.tsx +2 -2
- package/src/lib/theme/composeTheme.ts +1 -1
- package/src/lib/theme/core/ThemeEngine.ts +8 -0
- package/src/lib/theme/core/ThemeValidator.ts +5 -2
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +11 -5
- package/src/lib/theme/generateCSSVariables.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +2 -1
- package/src/lib/theme/runtime/ThemeApplicator.ts +28 -11
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +3 -3
- package/src/lib/theme/runtime/ThemeManager.ts +4 -0
- package/src/lib/theme-tools.ts +1 -1
- package/src/lib/types/components.ts +183 -34
- package/src/lib/types/partProps.ts +0 -16
- package/src/lib/utils/fontPreloader.ts +148 -0
- package/src/lib/utils/index.ts +11 -0
- package/src/lib/utils/memoryMonitor.ts +189 -0
- package/src/styles/01-settings/_settings.fonts.scss +2 -5
- package/src/styles/03-generic/_generated-root.css +22 -1
- package/src/styles/06-components/_components.navbar.scss +0 -6
- package/src/themes/themes.config.js +37 -4
- package/scripts/build-themes.js +0 -208
- package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Monitoring Hook
|
|
3
|
+
*
|
|
4
|
+
* Tracks component render times and re-render counts
|
|
5
|
+
* for performance analysis and optimization
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useRef } from 'react';
|
|
9
|
+
|
|
10
|
+
export interface PerformanceMetrics {
|
|
11
|
+
/**
|
|
12
|
+
* Component name
|
|
13
|
+
*/
|
|
14
|
+
componentName: string;
|
|
15
|
+
/**
|
|
16
|
+
* Number of renders
|
|
17
|
+
*/
|
|
18
|
+
renderCount: number;
|
|
19
|
+
/**
|
|
20
|
+
* Average render time in milliseconds
|
|
21
|
+
*/
|
|
22
|
+
averageRenderTime: number;
|
|
23
|
+
/**
|
|
24
|
+
* Total render time in milliseconds
|
|
25
|
+
*/
|
|
26
|
+
totalRenderTime: number;
|
|
27
|
+
/**
|
|
28
|
+
* Maximum render time in milliseconds
|
|
29
|
+
*/
|
|
30
|
+
maxRenderTime: number;
|
|
31
|
+
/**
|
|
32
|
+
* Minimum render time in milliseconds
|
|
33
|
+
*/
|
|
34
|
+
minRenderTime: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for performance monitoring
|
|
39
|
+
*/
|
|
40
|
+
export interface UsePerformanceMonitorOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Component name to track
|
|
43
|
+
*/
|
|
44
|
+
componentName: string;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to log metrics to console (development only)
|
|
47
|
+
*/
|
|
48
|
+
logToConsole?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Threshold in milliseconds to warn about slow renders
|
|
51
|
+
*/
|
|
52
|
+
warnThreshold?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Callback to report metrics (e.g., to analytics)
|
|
55
|
+
*/
|
|
56
|
+
onMetrics?: (metrics: PerformanceMetrics) => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Hook to monitor component performance
|
|
61
|
+
*
|
|
62
|
+
* @param options - Performance monitoring options
|
|
63
|
+
* @returns Performance metrics
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* function MyComponent() {
|
|
68
|
+
* usePerformanceMonitor({
|
|
69
|
+
* componentName: 'MyComponent',
|
|
70
|
+
* warnThreshold: 16, // Warn if render takes > 16ms (1 frame)
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* return <div>Content</div>;
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export function usePerformanceMonitor(options: UsePerformanceMonitorOptions) {
|
|
78
|
+
const {
|
|
79
|
+
componentName,
|
|
80
|
+
logToConsole = process.env.NODE_ENV === 'development',
|
|
81
|
+
warnThreshold = 16,
|
|
82
|
+
onMetrics,
|
|
83
|
+
} = options;
|
|
84
|
+
|
|
85
|
+
const metricsRef = useRef<PerformanceMetrics>({
|
|
86
|
+
componentName,
|
|
87
|
+
renderCount: 0,
|
|
88
|
+
averageRenderTime: 0,
|
|
89
|
+
totalRenderTime: 0,
|
|
90
|
+
maxRenderTime: 0,
|
|
91
|
+
minRenderTime: Infinity,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const renderStartRef = useRef<number>(0);
|
|
95
|
+
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
// Start timing the render
|
|
98
|
+
renderStartRef.current = performance.now();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
// Calculate render time
|
|
103
|
+
const renderTime = performance.now() - renderStartRef.current;
|
|
104
|
+
const metrics = metricsRef.current;
|
|
105
|
+
|
|
106
|
+
// Update metrics
|
|
107
|
+
metrics.renderCount += 1;
|
|
108
|
+
metrics.totalRenderTime += renderTime;
|
|
109
|
+
metrics.averageRenderTime = metrics.totalRenderTime / metrics.renderCount;
|
|
110
|
+
metrics.maxRenderTime = Math.max(metrics.maxRenderTime, renderTime);
|
|
111
|
+
metrics.minRenderTime = Math.min(metrics.minRenderTime, renderTime);
|
|
112
|
+
|
|
113
|
+
// Warn if render is slow
|
|
114
|
+
if (renderTime > warnThreshold && logToConsole) {
|
|
115
|
+
console.warn(
|
|
116
|
+
`[Performance] ${componentName} render took ${renderTime.toFixed(2)}ms ` +
|
|
117
|
+
`(threshold: ${warnThreshold}ms)`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Log metrics in development
|
|
122
|
+
if (logToConsole && metrics.renderCount % 10 === 0) {
|
|
123
|
+
console.log(`[Performance] ${componentName} metrics:`, {
|
|
124
|
+
renderCount: metrics.renderCount,
|
|
125
|
+
averageRenderTime: metrics.averageRenderTime.toFixed(2) + 'ms',
|
|
126
|
+
maxRenderTime: metrics.maxRenderTime.toFixed(2) + 'ms',
|
|
127
|
+
minRenderTime: metrics.minRenderTime.toFixed(2) + 'ms',
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Report metrics via callback
|
|
132
|
+
if (onMetrics) {
|
|
133
|
+
onMetrics({ ...metrics });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return metricsRef.current;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get all performance metrics for all monitored components
|
|
142
|
+
* (useful for debugging and analytics)
|
|
143
|
+
*/
|
|
144
|
+
export function getPerformanceMetrics(): PerformanceMetrics[] {
|
|
145
|
+
// This would need to be implemented with a global store
|
|
146
|
+
// For now, this is a placeholder
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
@@ -11,7 +11,7 @@ export {
|
|
|
11
11
|
createSlotComponent,
|
|
12
12
|
useSlot,
|
|
13
13
|
createSlotProps,
|
|
14
|
-
} from './slots
|
|
14
|
+
} from './slots';
|
|
15
15
|
|
|
16
16
|
export type {
|
|
17
17
|
SlotProps,
|
|
@@ -32,4 +32,4 @@ export type {
|
|
|
32
32
|
DropdownRootSlotProps,
|
|
33
33
|
DropdownToggleSlotProps,
|
|
34
34
|
DropdownMenuSlotProps,
|
|
35
|
-
} from './slots
|
|
35
|
+
} from './slots';
|
|
@@ -59,7 +59,7 @@ export function renderSlot<T>(
|
|
|
59
59
|
// Priority 2: component
|
|
60
60
|
if (slotObj.component) {
|
|
61
61
|
const Component = slotObj.component;
|
|
62
|
-
return <Component {...props} />;
|
|
62
|
+
return <Component {...(props as any)} />;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Priority 3: children
|
|
@@ -133,7 +133,7 @@ export function createSlotComponent<T>(
|
|
|
133
133
|
return <Element {...(props as any)}>{children}</Element>;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
const Component = defaultElement
|
|
136
|
+
const Component = defaultElement as React.ComponentType<any>;
|
|
137
137
|
return <Component {...slotProps}>{children}</Component>;
|
|
138
138
|
};
|
|
139
139
|
}
|
|
@@ -33,7 +33,7 @@ export function deepMerge<T extends Record<string, any>>(...objects: Partial<T>[
|
|
|
33
33
|
if (!source) continue;
|
|
34
34
|
|
|
35
35
|
for (const key in source) {
|
|
36
|
-
if (!
|
|
36
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
|
|
37
37
|
|
|
38
38
|
const targetValue = result[key];
|
|
39
39
|
const sourceValue = source[key];
|
|
@@ -538,9 +538,13 @@ export class ThemeEngine {
|
|
|
538
538
|
/**
|
|
539
539
|
* Add change listener
|
|
540
540
|
*/
|
|
541
|
+
// @ts-ignore - TypeScript overloads are valid, ESLint doesn't understand them
|
|
541
542
|
on(event: 'change', listener: ThemeChangeListener): void;
|
|
543
|
+
// @ts-ignore
|
|
542
544
|
on(event: 'load', listener: ThemeLoadListener): void;
|
|
545
|
+
// @ts-ignore
|
|
543
546
|
on(event: 'error', listener: ThemeErrorListener): void;
|
|
547
|
+
// @ts-ignore
|
|
544
548
|
on(event: 'revert', listener: ThemeRevertListener): void;
|
|
545
549
|
on(
|
|
546
550
|
event: 'change' | 'load' | 'error' | 'revert',
|
|
@@ -560,9 +564,13 @@ export class ThemeEngine {
|
|
|
560
564
|
/**
|
|
561
565
|
* Remove listener
|
|
562
566
|
*/
|
|
567
|
+
// @ts-ignore - TypeScript overloads are valid, ESLint doesn't understand them
|
|
563
568
|
off(event: 'change', listener: ThemeChangeListener): void;
|
|
569
|
+
// @ts-ignore
|
|
564
570
|
off(event: 'load', listener: ThemeLoadListener): void;
|
|
571
|
+
// @ts-ignore
|
|
565
572
|
off(event: 'error', listener: ThemeErrorListener): void;
|
|
573
|
+
// @ts-ignore
|
|
566
574
|
off(event: 'revert', listener: ThemeRevertListener): void;
|
|
567
575
|
off(
|
|
568
576
|
event: 'change' | 'load' | 'error' | 'revert',
|
|
@@ -392,8 +392,11 @@ export class ThemeValidator {
|
|
|
392
392
|
|
|
393
393
|
for (let i = 0; i < numericEntries.length; i++) {
|
|
394
394
|
for (let j = i + 1; j < numericEntries.length; j++) {
|
|
395
|
-
const
|
|
396
|
-
const
|
|
395
|
+
const entryA = numericEntries[i];
|
|
396
|
+
const entryB = numericEntries[j];
|
|
397
|
+
if (!entryA || !entryB) continue;
|
|
398
|
+
const [keyA, valueA] = entryA;
|
|
399
|
+
const [keyB, valueB] = entryB;
|
|
397
400
|
const diff = Math.abs(valueA - valueB);
|
|
398
401
|
if (diff < 10 && diff > 0) {
|
|
399
402
|
warnings.push(
|
|
@@ -90,7 +90,7 @@ export const ThemeInspector: React.FC<ThemeInspectorProps> = ({
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
if (typeof value === 'string') {
|
|
93
|
-
return <span className="value-string"
|
|
93
|
+
return <span className="value-string">"{value}"</span>;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (typeof value === 'number') {
|
|
@@ -59,19 +59,25 @@ export const ThemeLiveEditor: React.FC<ThemeLiveEditorProps> = ({
|
|
|
59
59
|
}
|
|
60
60
|
}, [onChange]);
|
|
61
61
|
|
|
62
|
-
const handleColorChange = useCallback((path: string, value: string) => {
|
|
62
|
+
const handleColorChange = useCallback((path: string, value: string | number) => {
|
|
63
63
|
const newTheme = { ...theme };
|
|
64
64
|
const keys = path.split('.');
|
|
65
65
|
let current: any = newTheme;
|
|
66
66
|
|
|
67
67
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
const key = keys[i];
|
|
69
|
+
if (key && !current[key]) {
|
|
70
|
+
current[key] = {};
|
|
71
|
+
}
|
|
72
|
+
if (key) {
|
|
73
|
+
current = current[key];
|
|
70
74
|
}
|
|
71
|
-
current = current[keys[i]];
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
const lastKey = keys[keys.length - 1];
|
|
78
|
+
if (lastKey) {
|
|
79
|
+
current[lastKey] = value;
|
|
80
|
+
}
|
|
75
81
|
updateTheme(createTheme(newTheme));
|
|
76
82
|
}, [theme, updateTheme]);
|
|
77
83
|
|
|
@@ -47,7 +47,7 @@ function flattenObject(
|
|
|
47
47
|
result: Record<string, string> = {}
|
|
48
48
|
): Record<string, string> {
|
|
49
49
|
for (const key in obj) {
|
|
50
|
-
if (!
|
|
50
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
|
|
51
51
|
|
|
52
52
|
const value = obj[key];
|
|
53
53
|
const newKey = prefix ? `${prefix}-${key}` : key;
|
|
@@ -93,7 +93,8 @@ export class RTLManager {
|
|
|
93
93
|
|
|
94
94
|
// Try navigator.language first
|
|
95
95
|
const lang: string = navigator.language || (navigator.languages && navigator.languages[0]) || 'en';
|
|
96
|
-
|
|
96
|
+
const langParts = String(lang).split('-');
|
|
97
|
+
return langParts[0] ? langParts[0].toLowerCase() : 'en';
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/**
|
|
@@ -47,8 +47,8 @@ export class ThemeApplicator {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Apply component overrides
|
|
50
|
-
if (theme.components) {
|
|
51
|
-
this.applyComponentOverrides(theme.components);
|
|
50
|
+
if ((theme as any).components) {
|
|
51
|
+
this.applyComponentOverrides((theme as any).components);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -76,19 +76,25 @@ export class ThemeApplicator {
|
|
|
76
76
|
|
|
77
77
|
if (typography.fontSize) {
|
|
78
78
|
Object.entries(typography.fontSize).forEach(([key, value]) => {
|
|
79
|
-
|
|
79
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
80
|
+
vars[`--atomix-font-size-${key}`] = value;
|
|
81
|
+
}
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
if (typography.fontWeight) {
|
|
84
86
|
Object.entries(typography.fontWeight).forEach(([key, value]) => {
|
|
85
|
-
|
|
87
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
88
|
+
vars[`--atomix-font-weight-${key}`] = value;
|
|
89
|
+
}
|
|
86
90
|
});
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
if (typography.lineHeight) {
|
|
90
94
|
Object.entries(typography.lineHeight).forEach(([key, value]) => {
|
|
91
|
-
|
|
95
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
96
|
+
vars[`--atomix-line-height-${key}`] = value;
|
|
97
|
+
}
|
|
92
98
|
});
|
|
93
99
|
}
|
|
94
100
|
|
|
@@ -98,12 +104,23 @@ export class ThemeApplicator {
|
|
|
98
104
|
/**
|
|
99
105
|
* Apply spacing system
|
|
100
106
|
*/
|
|
101
|
-
private applySpacing(spacing:
|
|
107
|
+
private applySpacing(spacing: any): void {
|
|
102
108
|
const vars: Record<string, string | number> = {};
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
// Handle spacing function or object
|
|
111
|
+
if (typeof spacing === 'function') {
|
|
112
|
+
// If spacing is a function, we can't iterate it directly
|
|
113
|
+
// Just skip for now as it's a special case
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (typeof spacing === 'object' && spacing !== null) {
|
|
118
|
+
Object.entries(spacing).forEach(([key, value]) => {
|
|
119
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
120
|
+
vars[`--atomix-space-${key}`] = value;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
107
124
|
|
|
108
125
|
this.applyGlobalCSSVars(vars);
|
|
109
126
|
}
|
|
@@ -117,9 +134,9 @@ export class ThemeApplicator {
|
|
|
117
134
|
const vars: Record<string, string | number> = {};
|
|
118
135
|
|
|
119
136
|
Object.entries(palette).forEach(([colorName, colorScale]) => {
|
|
120
|
-
if (colorScale) {
|
|
137
|
+
if (colorScale && typeof colorScale === 'object') {
|
|
121
138
|
Object.entries(colorScale).forEach(([shade, value]) => {
|
|
122
|
-
if (value) {
|
|
139
|
+
if (value && (typeof value === 'string' || typeof value === 'number')) {
|
|
123
140
|
vars[`--atomix-color-${colorName}-${shade}`] = value;
|
|
124
141
|
}
|
|
125
142
|
});
|
|
@@ -148,7 +148,7 @@ export class ThemeErrorBoundary extends Component<
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
|
151
|
+
override componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
|
152
152
|
// Log error
|
|
153
153
|
const themeError = error instanceof ThemeError
|
|
154
154
|
? error
|
|
@@ -187,7 +187,7 @@ export class ThemeErrorBoundary extends Component<
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
componentDidUpdate(prevProps: ThemeErrorBoundaryProps): void {
|
|
190
|
+
override componentDidUpdate(prevProps: ThemeErrorBoundaryProps): void {
|
|
191
191
|
// Reset error if resetOnPropsChange is true and children changed
|
|
192
192
|
if (
|
|
193
193
|
this.props.resetOnPropsChange &&
|
|
@@ -202,7 +202,7 @@ export class ThemeErrorBoundary extends Component<
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
render(): ReactNode {
|
|
205
|
+
override render(): ReactNode {
|
|
206
206
|
if (this.state.hasError && this.state.error && this.state.errorInfo) {
|
|
207
207
|
// Use custom fallback if provided
|
|
208
208
|
if (this.props.fallback) {
|
|
@@ -289,9 +289,11 @@ export class ThemeManager {
|
|
|
289
289
|
/**
|
|
290
290
|
* Add event listener
|
|
291
291
|
*/
|
|
292
|
+
/* eslint-disable no-dupe-class-members */
|
|
292
293
|
on(event: 'themeChange', callback: ThemeChangeCallback): void;
|
|
293
294
|
on(event: 'themeLoad', callback: ThemeLoadCallback): void;
|
|
294
295
|
on(event: 'themeError', callback: ThemeErrorCallback): void;
|
|
296
|
+
/* eslint-enable no-dupe-class-members */
|
|
295
297
|
on(event: ThemeManagerEvent, callback: ThemeChangeCallback | ThemeLoadCallback | ThemeErrorCallback): void {
|
|
296
298
|
if (event === 'themeChange') {
|
|
297
299
|
this.eventListeners.themeChange.push(callback as ThemeChangeCallback);
|
|
@@ -305,9 +307,11 @@ export class ThemeManager {
|
|
|
305
307
|
/**
|
|
306
308
|
* Remove event listener
|
|
307
309
|
*/
|
|
310
|
+
/* eslint-disable no-dupe-class-members */
|
|
308
311
|
off(event: 'themeChange', callback: ThemeChangeCallback): void;
|
|
309
312
|
off(event: 'themeLoad', callback: ThemeLoadCallback): void;
|
|
310
313
|
off(event: 'themeError', callback: ThemeErrorCallback): void;
|
|
314
|
+
/* eslint-enable no-dupe-class-members */
|
|
311
315
|
off(event: ThemeManagerEvent, callback: ThemeChangeCallback | ThemeLoadCallback | ThemeErrorCallback): void {
|
|
312
316
|
if (event === 'themeChange') {
|
|
313
317
|
this.eventListeners.themeChange = this.eventListeners.themeChange.filter(cb => cb !== callback);
|