@shohojdhara/atomix 0.3.4 → 0.3.6
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/README.md +101 -199
- package/atomix.config.ts +241 -0
- package/dist/atomix.css +269 -189
- package/dist/atomix.css.map +1 -0
- package/dist/atomix.min.css +15179 -11
- package/dist/atomix.min.css.map +1 -0
- package/dist/charts.d.ts +1929 -0
- package/dist/charts.js +6477 -0
- package/dist/charts.js.map +1 -0
- package/dist/core.d.ts +1289 -0
- package/dist/core.js +3373 -0
- package/dist/core.js.map +1 -0
- package/dist/forms.d.ts +1085 -0
- package/dist/forms.js +2466 -0
- package/dist/forms.js.map +1 -0
- package/dist/heavy.d.ts +636 -0
- package/dist/heavy.js +4566 -0
- package/dist/heavy.js.map +1 -0
- package/dist/index.d.ts +5171 -4792
- package/dist/index.esm.js +6098 -4563
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +6291 -4747
- 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 +2122 -0
- package/dist/theme.js +6084 -0
- package/dist/theme.js.map +1 -0
- package/package.json +59 -27
- 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.stories.tsx +50 -17
- package/src/components/Accordion/Accordion.tsx +5 -54
- package/src/components/Accordion/index.ts +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +65 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +11 -4
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -32
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +0 -31
- package/src/components/Avatar/Avatar.stories.tsx +7 -0
- package/src/components/Avatar/Avatar.tsx +3 -3
- package/src/components/Badge/Badge.stories.tsx +91 -13
- package/src/components/Badge/Badge.tsx +3 -3
- package/src/components/Block/Block.stories.tsx +7 -23
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
- package/src/components/Button/Button.stories.tsx +141 -22
- package/src/components/Button/ButtonGroup.stories.tsx +315 -0
- package/src/components/Button/ButtonGroup.tsx +67 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Callout/Callout.stories.tsx +8 -6
- package/src/components/Card/Card.stories.tsx +82 -28
- package/src/components/Card/ElevationCard.tsx +1 -1
- package/src/components/Chart/AnimatedChart.tsx +19 -18
- package/src/components/Chart/AreaChart.tsx +5 -2
- package/src/components/Chart/BarChart.tsx +1 -1
- package/src/components/Chart/BubbleChart.tsx +6 -6
- package/src/components/Chart/CandlestickChart.tsx +0 -1
- package/src/components/Chart/Chart.stories.tsx +5 -7
- package/src/components/Chart/Chart.tsx +0 -16
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/ChartToolbar.tsx +1 -0
- package/src/components/Chart/DonutChart.tsx +0 -1
- package/src/components/Chart/FunnelChart.tsx +1 -2
- package/src/components/Chart/GaugeChart.tsx +0 -1
- package/src/components/Chart/HeatmapChart.tsx +0 -1
- package/src/components/Chart/LineChart.tsx +0 -1
- package/src/components/Chart/MultiAxisChart.tsx +0 -1
- package/src/components/Chart/PieChart.tsx +0 -1
- package/src/components/Chart/RadarChart.tsx +19 -13
- package/src/components/Chart/ScatterChart.tsx +3 -4
- package/src/components/Chart/TreemapChart.tsx +2 -1
- package/src/components/Chart/WaterfallChart.tsx +0 -2
- package/src/components/Chart/types.ts +12 -2
- package/src/components/Chart/utils.ts +4 -3
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
- package/src/components/DataTable/DataTable.stories.tsx +23 -16
- package/src/components/DataTable/DataTable.tsx +3 -3
- package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
- package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
- package/src/components/Dropdown/Dropdown.tsx +12 -9
- package/src/components/EdgePanel/EdgePanel.stories.tsx +1 -0
- package/src/components/Footer/Footer.stories.tsx +8 -6
- package/src/components/Footer/FooterLink.tsx +9 -2
- package/src/components/Footer/FooterSection.tsx +3 -3
- package/src/components/Form/Checkbox.stories.tsx +7 -0
- package/src/components/Form/Checkbox.tsx +3 -3
- package/src/components/Form/Form.stories.tsx +7 -0
- package/src/components/Form/FormGroup.stories.tsx +9 -1
- package/src/components/Form/Input.stories.tsx +69 -16
- package/src/components/Form/Input.tsx +4 -2
- package/src/components/Form/Radio.stories.tsx +9 -1
- package/src/components/Form/Radio.tsx +3 -3
- package/src/components/Form/Select.stories.tsx +9 -1
- package/src/components/Form/Select.tsx +3 -3
- package/src/components/Form/Textarea.stories.tsx +10 -2
- package/src/components/Form/Textarea.tsx +4 -2
- package/src/components/Hero/Hero.stories.tsx +7 -0
- package/src/components/List/List.stories.tsx +10 -3
- package/src/components/List/List.tsx +3 -3
- package/src/components/List/ListGroup.tsx +3 -1
- package/src/components/Messages/Messages.stories.tsx +8 -7
- package/src/components/Modal/Modal.stories.tsx +17 -6
- package/src/components/Modal/Modal.tsx +3 -3
- package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
- package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
- package/src/components/Navigation/Menu/Menu.tsx +9 -3
- package/src/components/Navigation/Nav/Nav.stories.tsx +7 -0
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +1 -0
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +188 -111
- package/src/components/Pagination/Pagination.tsx +88 -7
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
- package/src/components/Popover/Popover.stories.tsx +191 -115
- package/src/components/Popover/Popover.tsx +4 -4
- package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
- package/src/components/Progress/Progress.stories.tsx +79 -49
- package/src/components/Progress/Progress.tsx +6 -2
- package/src/components/Rating/Rating.stories.tsx +109 -84
- package/src/components/Rating/Rating.tsx +5 -2
- package/src/components/River/River.stories.tsx +194 -114
- package/src/components/SectionIntro/SectionIntro.stories.tsx +19 -9
- package/src/components/Slider/Slider.stories.tsx +7 -0
- package/src/components/Slider/Slider.tsx +10 -9
- package/src/components/Spinner/Spinner.stories.tsx +15 -11
- package/src/components/Spinner/Spinner.tsx +3 -3
- package/src/components/Steps/Steps.stories.tsx +132 -98
- package/src/components/Tabs/Tabs.stories.tsx +163 -112
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Testimonial/Testimonial.stories.tsx +114 -68
- package/src/components/Todo/Todo.stories.tsx +38 -12
- package/src/components/Toggle/Toggle.stories.tsx +61 -28
- package/src/components/Tooltip/Tooltip.stories.tsx +318 -200
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/Upload/Upload.stories.tsx +122 -84
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
- package/src/components/index.ts +6 -2
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
- package/src/lib/composables/useAtomixGlass.ts +2 -3
- 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/useNavbar.ts +0 -10
- package/src/lib/composables/useSideMenu.ts +1 -0
- package/src/lib/composables/useVideoPlayer.ts +3 -2
- package/src/lib/config/loader.ts +57 -14
- package/src/lib/constants/components.ts +10 -0
- package/src/lib/hooks/index.ts +0 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -15
- 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/README.md +174 -0
- package/src/lib/theme/adapters/index.ts +31 -0
- package/src/lib/theme/adapters/themeAdapter.ts +287 -0
- package/src/lib/theme/config/__tests__/configLoader.test.ts +207 -0
- package/src/lib/theme/config/configLoader.ts +254 -0
- package/src/lib/theme/config/loader.ts +37 -48
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +15 -91
- package/src/lib/theme/{constants.ts → constants/constants.ts} +0 -18
- package/src/lib/theme/constants/index.ts +8 -0
- package/src/lib/theme/core/ThemeRegistry.ts +19 -6
- package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
- package/src/lib/theme/core/composeTheme.ts +155 -0
- package/src/lib/theme/core/createTheme.ts +94 -0
- package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +10 -6
- package/src/lib/theme/core/index.ts +5 -19
- package/src/lib/theme/devtools/Comparator.tsx +346 -22
- package/src/lib/theme/devtools/IMPROVEMENTS.md +139 -38
- package/src/lib/theme/devtools/Inspector.tsx +335 -51
- package/src/lib/theme/devtools/LiveEditor.tsx +489 -112
- package/src/lib/theme/devtools/Preview.tsx +471 -221
- package/src/lib/theme/{core → devtools}/ThemeValidator.ts +6 -3
- package/src/lib/theme/devtools/index.ts +14 -4
- package/src/lib/theme/devtools/useHistory.ts +130 -0
- package/src/lib/theme/errors/index.ts +12 -0
- package/src/lib/theme/generators/cssFile.ts +79 -0
- package/src/lib/theme/generators/generateCSS.ts +89 -0
- package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +4 -14
- package/src/lib/theme/generators/index.ts +19 -0
- package/src/lib/theme/i18n/rtl.ts +7 -7
- package/src/lib/theme/index.ts +120 -15
- package/src/lib/theme/runtime/ThemeApplicator.ts +53 -95
- package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +4 -4
- package/src/lib/theme/runtime/ThemeProvider.tsx +456 -179
- package/src/lib/theme/runtime/index.ts +1 -2
- package/src/lib/theme/runtime/useTheme.ts +1 -2
- package/src/lib/theme/test/testTheme.ts +385 -0
- package/src/lib/theme/tokens/index.ts +12 -0
- package/src/lib/theme/tokens/tokens.ts +721 -0
- package/src/lib/theme/types.ts +6 -42
- package/src/lib/theme/{utils.ts → utils/domUtils.ts} +2 -2
- package/src/lib/theme/utils/index.ts +11 -0
- package/src/lib/theme/utils/injectCSS.ts +90 -0
- package/src/lib/theme/utils/themeHelpers.ts +78 -0
- package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +1 -1
- package/src/lib/theme-tools.ts +8 -9
- package/src/lib/types/components.ts +93 -34
- package/src/lib/types/partProps.ts +0 -16
- package/src/lib/utils/componentUtils.ts +1 -1
- 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.design-tokens.scss +4 -1
- package/src/styles/01-settings/_settings.fonts.scss +2 -5
- package/src/styles/02-tools/_tools.button.scss +66 -79
- package/src/styles/06-components/_components.atomix-glass.scss +13 -3
- package/src/styles/06-components/_components.navbar.scss +0 -6
- package/src/styles/06-components/_components.pagination.scss +88 -0
- package/scripts/build-themes.js +0 -208
- package/scripts/sync-theme-config.js +0 -309
- package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
- package/src/lib/theme/composeTheme.ts +0 -370
- package/src/lib/theme/core/ThemeCache.ts +0 -283
- package/src/lib/theme/core/ThemeEngine.test.ts +0 -146
- package/src/lib/theme/core/ThemeEngine.ts +0 -657
- package/src/lib/theme/createThemeFromConfig.ts +0 -132
- package/src/lib/theme/devtools/CLI.ts +0 -364
- package/src/lib/theme/runtime/ThemeManager.test.ts +0 -192
- package/src/lib/theme/runtime/ThemeManager.ts +0 -442
- package/src/styles/03-generic/_generated-root.css +0 -5
- package/src/themes/README.md +0 -442
- package/src/themes/themes.config.js +0 -35
- /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
- /package/src/lib/theme/{errors.ts → errors/errors.ts} +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader
|
|
3
|
+
*
|
|
4
|
+
* Load design tokens from atomix.config.ts and convert to flat token format.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DesignTokens } from '../tokens/tokens';
|
|
8
|
+
import type { AtomixConfig, ThemeTokens } from '../../config';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Convert nested config tokens to flat DesignTokens format
|
|
12
|
+
*
|
|
13
|
+
* Handles conversion from atomix.config.ts structure to flat tokens.
|
|
14
|
+
* Maps config structure to actual DesignTokens key names.
|
|
15
|
+
*/
|
|
16
|
+
function flattenConfigTokens(
|
|
17
|
+
tokens: ThemeTokens,
|
|
18
|
+
prefix: string = 'atomix'
|
|
19
|
+
): Partial<DesignTokens> {
|
|
20
|
+
const flat: Partial<DesignTokens> = {};
|
|
21
|
+
|
|
22
|
+
// Colors
|
|
23
|
+
if (tokens.colors) {
|
|
24
|
+
Object.entries(tokens.colors).forEach(([key, value]) => {
|
|
25
|
+
if (typeof value === 'string') {
|
|
26
|
+
// Simple color: 'primary': '#7AFFD7'
|
|
27
|
+
// Map directly to DesignTokens keys (e.g., 'primary', 'secondary', 'error')
|
|
28
|
+
// Only map if it's a valid semantic color key
|
|
29
|
+
if (['primary', 'secondary', 'success', 'info', 'warning', 'error', 'light', 'dark'].includes(key)) {
|
|
30
|
+
flat[key as keyof DesignTokens] = value;
|
|
31
|
+
}
|
|
32
|
+
} else if (value && typeof value === 'object') {
|
|
33
|
+
// Color scale or palette
|
|
34
|
+
if ('main' in value) {
|
|
35
|
+
// PaletteColorOptions: { main: '#7AFFD7', light?: '#...', dark?: '#...' }
|
|
36
|
+
const palette = value as { main: string; light?: string; dark?: string };
|
|
37
|
+
const baseKey = key as keyof DesignTokens;
|
|
38
|
+
|
|
39
|
+
// Map main to base color (e.g., primary, secondary, error)
|
|
40
|
+
if (['primary', 'secondary', 'success', 'info', 'warning', 'error', 'light', 'dark'].includes(key)) {
|
|
41
|
+
flat[baseKey] = palette.main;
|
|
42
|
+
|
|
43
|
+
// Map light/dark to appropriate scale values
|
|
44
|
+
// light typically maps to step 3, dark to step 9
|
|
45
|
+
if (palette.light) {
|
|
46
|
+
flat[`${key}-3` as keyof DesignTokens] = palette.light;
|
|
47
|
+
}
|
|
48
|
+
if (palette.dark) {
|
|
49
|
+
flat[`${key}-9` as keyof DesignTokens] = palette.dark;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
// Color scale: { 1: '#fff', 2: '#eee', ..., 6: '#main', ... }
|
|
54
|
+
// Or full scale: { 1: '#...', 2: '#...', ..., 10: '#...' }
|
|
55
|
+
Object.entries(value).forEach(([scaleKey, scaleValue]) => {
|
|
56
|
+
if (typeof scaleValue === 'string') {
|
|
57
|
+
// Map scale keys to DesignTokens format
|
|
58
|
+
if (scaleKey === 'main' || scaleKey === '6') {
|
|
59
|
+
// Main color maps to base key (e.g., 'primary')
|
|
60
|
+
if (['primary', 'secondary', 'success', 'info', 'warning', 'error', 'light', 'dark'].includes(key)) {
|
|
61
|
+
flat[key as keyof DesignTokens] = scaleValue;
|
|
62
|
+
}
|
|
63
|
+
// Also map to step 6 if it's a scale color
|
|
64
|
+
if (['primary', 'red', 'green', 'blue', 'yellow', 'gray'].includes(key)) {
|
|
65
|
+
flat[`${key}-6` as keyof DesignTokens] = scaleValue;
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
// Map scale numbers (1-10) to DesignTokens format
|
|
69
|
+
const scaleNum = parseInt(scaleKey, 10);
|
|
70
|
+
if (!isNaN(scaleNum) && scaleNum >= 1 && scaleNum <= 10) {
|
|
71
|
+
flat[`${key}-${scaleKey}` as keyof DesignTokens] = scaleValue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Spacing
|
|
82
|
+
if (tokens.spacing) {
|
|
83
|
+
Object.entries(tokens.spacing).forEach(([key, value]) => {
|
|
84
|
+
flat[`spacing-${key}` as keyof DesignTokens] = String(value);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Border Radius
|
|
89
|
+
if (tokens.borderRadius) {
|
|
90
|
+
Object.entries(tokens.borderRadius).forEach(([key, value]) => {
|
|
91
|
+
// Map to DesignTokens format
|
|
92
|
+
if (key === 'sm' || key === 'base' || key === '') {
|
|
93
|
+
flat['border-radius-sm' as keyof DesignTokens] = String(value);
|
|
94
|
+
} else if (key === 'md' || key === 'default') {
|
|
95
|
+
flat['border-radius' as keyof DesignTokens] = String(value);
|
|
96
|
+
} else if (key === 'lg') {
|
|
97
|
+
flat['border-radius-lg' as keyof DesignTokens] = String(value);
|
|
98
|
+
} else {
|
|
99
|
+
flat[`border-radius-${key}` as keyof DesignTokens] = String(value);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Typography
|
|
105
|
+
if (tokens.typography) {
|
|
106
|
+
// Font Families
|
|
107
|
+
if (tokens.typography.fontFamilies) {
|
|
108
|
+
Object.entries(tokens.typography.fontFamilies).forEach(([key, value]) => {
|
|
109
|
+
// Map to DesignTokens format
|
|
110
|
+
if (key === 'sans' || key === 'base') {
|
|
111
|
+
flat['font-sans-serif' as keyof DesignTokens] = String(value);
|
|
112
|
+
flat['body-font-family' as keyof DesignTokens] = String(value);
|
|
113
|
+
} else if (key === 'mono') {
|
|
114
|
+
flat['font-monospace' as keyof DesignTokens] = String(value);
|
|
115
|
+
} else {
|
|
116
|
+
flat[`font-family-${key}` as keyof DesignTokens] = String(value);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Font Sizes
|
|
122
|
+
if (tokens.typography.fontSizes) {
|
|
123
|
+
Object.entries(tokens.typography.fontSizes).forEach(([key, value]) => {
|
|
124
|
+
flat[`font-size-${key}` as keyof DesignTokens] = String(value);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Font Weights
|
|
129
|
+
if (tokens.typography.fontWeights) {
|
|
130
|
+
Object.entries(tokens.typography.fontWeights).forEach(([key, value]) => {
|
|
131
|
+
flat[`font-weight-${key}` as keyof DesignTokens] = String(value);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Line Heights
|
|
136
|
+
if (tokens.typography.lineHeights) {
|
|
137
|
+
Object.entries(tokens.typography.lineHeights).forEach(([key, value]) => {
|
|
138
|
+
if (key === 'base' || key === 'default') {
|
|
139
|
+
flat['line-height-base' as keyof DesignTokens] = String(value);
|
|
140
|
+
} else {
|
|
141
|
+
flat[`line-height-${key}` as keyof DesignTokens] = String(value);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Shadows
|
|
148
|
+
if (tokens.shadows) {
|
|
149
|
+
Object.entries(tokens.shadows).forEach(([key, value]) => {
|
|
150
|
+
flat[`shadow-${key}` as keyof DesignTokens] = String(value);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Z-Index
|
|
155
|
+
if (tokens.zIndex) {
|
|
156
|
+
Object.entries(tokens.zIndex).forEach(([key, value]) => {
|
|
157
|
+
flat[`z-index-${key}` as keyof DesignTokens] = String(value);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Transitions
|
|
162
|
+
if (tokens.transitions) {
|
|
163
|
+
if (tokens.transitions.durations) {
|
|
164
|
+
Object.entries(tokens.transitions.durations).forEach(([key, value]) => {
|
|
165
|
+
flat[`transition-${key}` as keyof DesignTokens] = String(value);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return flat;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Load theme tokens from atomix.config.ts
|
|
175
|
+
*
|
|
176
|
+
* Loads atomix.config.ts and extracts theme tokens.
|
|
177
|
+
* Config file is required - throws error if not found.
|
|
178
|
+
*
|
|
179
|
+
* @param configPath - Optional custom config path (default: 'atomix.config.ts')
|
|
180
|
+
* @returns Partial DesignTokens from config
|
|
181
|
+
* @throws Error if config file is not found or cannot be loaded
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const tokens = await loadThemeFromConfig();
|
|
186
|
+
* const css = createTheme(tokens);
|
|
187
|
+
* injectTheme(css);
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export async function loadThemeFromConfig(
|
|
191
|
+
configPath: string = 'atomix.config.ts'
|
|
192
|
+
): Promise<Partial<DesignTokens>> {
|
|
193
|
+
// In browser environments, config loading is not supported
|
|
194
|
+
if (typeof window !== 'undefined') {
|
|
195
|
+
throw new Error('loadThemeFromConfig: Not available in browser environment. Config loading requires Node.js/SSR environment.');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Load config using the existing loader (required)
|
|
199
|
+
const { loadAtomixConfig } = await import('../../config/loader');
|
|
200
|
+
const config = loadAtomixConfig({ configPath, required: true });
|
|
201
|
+
|
|
202
|
+
if (!config || !config.theme) {
|
|
203
|
+
throw new Error(`Config file ${configPath} does not contain theme configuration.`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Extract tokens from config
|
|
207
|
+
const tokens = config.theme.tokens || config.theme.extend || {};
|
|
208
|
+
|
|
209
|
+
if (Object.keys(tokens).length === 0) {
|
|
210
|
+
throw new Error(`Config file ${configPath} has empty theme configuration.`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Convert nested structure to flat tokens
|
|
214
|
+
return flattenConfigTokens(tokens, config.prefix || 'atomix');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Load theme tokens from atomix.config.ts (synchronous version)
|
|
219
|
+
*
|
|
220
|
+
* Synchronous version that uses require() instead of dynamic import.
|
|
221
|
+
* Only works in Node.js environment.
|
|
222
|
+
* Config file is required - throws error if not found.
|
|
223
|
+
*
|
|
224
|
+
* @param configPath - Optional custom config path
|
|
225
|
+
* @returns Partial DesignTokens from config
|
|
226
|
+
* @throws Error if config file is not found or cannot be loaded
|
|
227
|
+
*/
|
|
228
|
+
export function loadThemeFromConfigSync(
|
|
229
|
+
configPath: string = 'atomix.config.ts'
|
|
230
|
+
): Partial<DesignTokens> {
|
|
231
|
+
// In browser environments, config loading is not supported
|
|
232
|
+
if (typeof window !== 'undefined') {
|
|
233
|
+
throw new Error('loadThemeFromConfigSync: Not available in browser environment. Config loading requires Node.js/SSR environment.');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
237
|
+
const { loadAtomixConfig } = require('../../config/loader');
|
|
238
|
+
const config = loadAtomixConfig({ configPath, required: true });
|
|
239
|
+
|
|
240
|
+
if (!config || !config.theme) {
|
|
241
|
+
throw new Error(`Config file ${configPath} does not contain theme configuration.`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Extract tokens from config
|
|
245
|
+
const tokens = config.theme.tokens || config.theme.extend || {};
|
|
246
|
+
|
|
247
|
+
if (Object.keys(tokens).length === 0) {
|
|
248
|
+
throw new Error(`Config file ${configPath} has empty theme configuration.`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Convert nested structure to flat tokens
|
|
252
|
+
return flattenConfigTokens(tokens, config.prefix || 'atomix');
|
|
253
|
+
}
|
|
254
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme Configuration Loader
|
|
3
3
|
*
|
|
4
|
-
* Loads and validates the theme configuration from
|
|
4
|
+
* Loads and validates the theme configuration from atomix.config.ts
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type {
|
|
@@ -10,12 +10,10 @@ import type {
|
|
|
10
10
|
ConfigValidationResult,
|
|
11
11
|
} from './types';
|
|
12
12
|
import { validateConfig } from './validator';
|
|
13
|
-
import { ThemeError, ThemeErrorCode, getLogger } from '../errors';
|
|
13
|
+
import { ThemeError, ThemeErrorCode, getLogger } from '../errors/errors';
|
|
14
14
|
import {
|
|
15
|
-
DEFAULT_CONFIG_PATH,
|
|
16
15
|
DEFAULT_ATOMIX_CONFIG_PATH,
|
|
17
16
|
DEFAULT_CONFIG_RELATIVE_PATH,
|
|
18
|
-
DEFAULT_LEGACY_CONFIG_RELATIVE_PATH,
|
|
19
17
|
DEFAULT_BASE_PATH,
|
|
20
18
|
DEFAULT_STORAGE_KEY,
|
|
21
19
|
DEFAULT_DATA_ATTRIBUTE,
|
|
@@ -24,7 +22,7 @@ import {
|
|
|
24
22
|
DEFAULT_BUILD_OUTPUT_DIR,
|
|
25
23
|
DEFAULT_SASS_CONFIG,
|
|
26
24
|
ENV_DEFAULTS,
|
|
27
|
-
} from '../constants';
|
|
25
|
+
} from '../constants/constants';
|
|
28
26
|
|
|
29
27
|
/**
|
|
30
28
|
* Cache for loaded configuration
|
|
@@ -37,7 +35,7 @@ let cachedConfig: LoadedThemeConfig | null = null;
|
|
|
37
35
|
const logger = getLogger();
|
|
38
36
|
|
|
39
37
|
/**
|
|
40
|
-
* Load theme configuration from
|
|
38
|
+
* Load theme configuration from atomix.config.ts
|
|
41
39
|
*
|
|
42
40
|
* @param options - Loader options
|
|
43
41
|
* @returns Loaded and validated theme configuration
|
|
@@ -97,30 +95,25 @@ export function loadThemeConfig(
|
|
|
97
95
|
try {
|
|
98
96
|
configModule = nodeRequire(DEFAULT_CONFIG_RELATIVE_PATH) as ConfigModule;
|
|
99
97
|
} catch {
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
} catch {
|
|
104
|
-
// If relative paths fail, try to resolve from process.cwd()
|
|
105
|
-
const path = nodeRequire('path') as typeof import('path');
|
|
106
|
-
const fs = nodeRequire('fs') as typeof import('fs');
|
|
98
|
+
// If relative path fails, try to resolve from process.cwd()
|
|
99
|
+
const path = nodeRequire('path') as typeof import('path');
|
|
100
|
+
const fs = nodeRequire('fs') as typeof import('fs');
|
|
107
101
|
|
|
108
|
-
|
|
102
|
+
let configFilePath = path.resolve(process.cwd(), configPath);
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
// If atomix.config.ts not found at the root, use the default path
|
|
105
|
+
if (!fs.existsSync(configFilePath) && configPath === DEFAULT_ATOMIX_CONFIG_PATH) {
|
|
106
|
+
configFilePath = path.resolve(process.cwd(), DEFAULT_ATOMIX_CONFIG_PATH);
|
|
107
|
+
}
|
|
114
108
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
configModule = nodeRequire(configFilePath) as ConfigModule;
|
|
121
|
-
} else {
|
|
122
|
-
throw new Error(`Config file not found: ${configFilePath}`);
|
|
109
|
+
if (fs.existsSync(configFilePath)) {
|
|
110
|
+
const resolvedPath = nodeRequire.resolve(configFilePath);
|
|
111
|
+
if (nodeRequire.cache && nodeRequire.cache[resolvedPath]) {
|
|
112
|
+
delete nodeRequire.cache[resolvedPath];
|
|
123
113
|
}
|
|
114
|
+
configModule = nodeRequire(configFilePath) as ConfigModule;
|
|
115
|
+
} else {
|
|
116
|
+
throw new Error(`Config file not found: ${configFilePath}`);
|
|
124
117
|
}
|
|
125
118
|
}
|
|
126
119
|
} catch (requireError) {
|
|
@@ -136,36 +129,30 @@ export function loadThemeConfig(
|
|
|
136
129
|
|
|
137
130
|
const rawConfig = configModule.default || configModule;
|
|
138
131
|
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
__extend: rawConfig.theme.extend,
|
|
152
|
-
};
|
|
153
|
-
} else {
|
|
154
|
-
// Legacy ThemeConfig structure
|
|
155
|
-
processedConfig = { ...rawConfig };
|
|
156
|
-
}
|
|
132
|
+
// Process the AtomixConfig structure
|
|
133
|
+
const processedConfig: LoadedThemeConfig = {
|
|
134
|
+
themes: rawConfig.theme?.themes || {},
|
|
135
|
+
build: rawConfig.build || {},
|
|
136
|
+
runtime: rawConfig.runtime || {},
|
|
137
|
+
integration: rawConfig.integration || {},
|
|
138
|
+
dependencies: rawConfig.dependencies || {},
|
|
139
|
+
validated: false, // Will be set after validation
|
|
140
|
+
// Store tokens for generator
|
|
141
|
+
__tokens: rawConfig.theme?.tokens,
|
|
142
|
+
__extend: rawConfig.theme?.extend,
|
|
143
|
+
};
|
|
157
144
|
|
|
158
145
|
// Apply environment-specific overrides
|
|
159
|
-
|
|
146
|
+
const finalConfig = applyEnvOverrides(processedConfig, env);
|
|
160
147
|
|
|
161
148
|
// Validate if requested
|
|
162
149
|
let validationResult: ConfigValidationResult | null = null;
|
|
163
150
|
if (validate) {
|
|
164
|
-
validationResult = validateConfig(
|
|
151
|
+
validationResult = validateConfig(finalConfig);
|
|
165
152
|
}
|
|
166
153
|
|
|
167
154
|
config = {
|
|
168
|
-
...
|
|
155
|
+
...finalConfig,
|
|
169
156
|
validated: validate,
|
|
170
157
|
errors: validationResult?.errors,
|
|
171
158
|
warnings: validationResult?.warnings,
|
|
@@ -212,6 +199,8 @@ export function loadThemeConfig(
|
|
|
212
199
|
validated: false,
|
|
213
200
|
errors: [`Failed to load config: ${error instanceof Error ? error.message : String(error)}`],
|
|
214
201
|
warnings: [],
|
|
202
|
+
__tokens: {},
|
|
203
|
+
__extend: {},
|
|
215
204
|
};
|
|
216
205
|
}
|
|
217
206
|
|
|
@@ -307,4 +296,4 @@ export function reloadThemeConfig(
|
|
|
307
296
|
): LoadedThemeConfig {
|
|
308
297
|
clearConfigCache();
|
|
309
298
|
return loadThemeConfig(options);
|
|
310
|
-
}
|
|
299
|
+
}
|
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
* Configuration loader options
|
|
19
19
|
*/
|
|
20
20
|
export interface ConfigLoaderOptions {
|
|
21
|
-
/** Path to theme config file (default: '
|
|
21
|
+
/** Path to theme config file (default: 'atomix.config.ts') */
|
|
22
22
|
configPath?: string;
|
|
23
23
|
/** Enable validation */
|
|
24
24
|
validate?: boolean;
|
|
@@ -109,4 +109,4 @@ export type {
|
|
|
109
109
|
BuildConfig,
|
|
110
110
|
RuntimeConfig,
|
|
111
111
|
IntegrationConfig,
|
|
112
|
-
};
|
|
112
|
+
};
|
|
@@ -4,13 +4,7 @@
|
|
|
4
4
|
* Validates theme configuration structure and values
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
AtomixConfig,
|
|
9
|
-
ThemeDefinition,
|
|
10
|
-
CSSThemeDefinition,
|
|
11
|
-
JSThemeDefinition,
|
|
12
|
-
ConfigValidationResult,
|
|
13
|
-
} from './types';
|
|
7
|
+
import type { ConfigValidationResult } from './types';
|
|
14
8
|
|
|
15
9
|
/**
|
|
16
10
|
* Validate theme configuration
|
|
@@ -37,31 +31,25 @@ export function validateConfig(config: any): ConfigValidationResult {
|
|
|
37
31
|
warnings.push(...themeErrors.warnings);
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
// Validate build config
|
|
34
|
+
// Validate build config (only if provided)
|
|
41
35
|
if (config.build) {
|
|
42
36
|
const buildErrors = validateBuildConfig(config.build);
|
|
43
37
|
errors.push(...buildErrors.errors);
|
|
44
38
|
warnings.push(...buildErrors.warnings);
|
|
45
|
-
} else {
|
|
46
|
-
warnings.push('No build configuration provided, using defaults');
|
|
47
39
|
}
|
|
48
40
|
|
|
49
|
-
// Validate runtime config
|
|
41
|
+
// Validate runtime config (only if provided)
|
|
50
42
|
if (config.runtime) {
|
|
51
43
|
const runtimeErrors = validateRuntimeConfig(config.runtime);
|
|
52
44
|
errors.push(...runtimeErrors.errors);
|
|
53
45
|
warnings.push(...runtimeErrors.warnings);
|
|
54
|
-
} else {
|
|
55
|
-
warnings.push('No runtime configuration provided, using defaults');
|
|
56
46
|
}
|
|
57
47
|
|
|
58
|
-
// Validate integration config
|
|
48
|
+
// Validate integration config (only if provided)
|
|
59
49
|
if (config.integration) {
|
|
60
50
|
const integrationErrors = validateIntegrationConfig(config.integration);
|
|
61
51
|
errors.push(...integrationErrors.errors);
|
|
62
52
|
warnings.push(...integrationErrors.warnings);
|
|
63
|
-
} else {
|
|
64
|
-
warnings.push('No integration configuration provided, using defaults');
|
|
65
53
|
}
|
|
66
54
|
|
|
67
55
|
// Validate dependencies
|
|
@@ -127,23 +115,9 @@ function validateThemes(themes: Record<string, any>): ConfigValidationResult {
|
|
|
127
115
|
warnings.push(...jsErrors.warnings);
|
|
128
116
|
}
|
|
129
117
|
|
|
130
|
-
// Validate
|
|
131
|
-
if (theme.
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (theme.status && !['stable', 'beta', 'experimental', 'deprecated'].includes(theme.status)) {
|
|
136
|
-
warnings.push(`Theme "${themeId}" has invalid status: ${theme.status}`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Validate color format
|
|
140
|
-
if (theme.color && !isValidColor(theme.color)) {
|
|
141
|
-
warnings.push(`Theme "${themeId}" has invalid color format: ${theme.color}`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Validate accessibility
|
|
145
|
-
if (theme.a11y) {
|
|
146
|
-
if (theme.a11y.contrastTarget && (theme.a11y.contrastTarget < 1 || theme.a11y.contrastTarget > 21)) {
|
|
118
|
+
// Validate accessibility (only critical checks)
|
|
119
|
+
if (theme.a11y?.contrastTarget) {
|
|
120
|
+
if (typeof theme.a11y.contrastTarget !== 'number' || theme.a11y.contrastTarget < 1 || theme.a11y.contrastTarget > 21) {
|
|
147
121
|
warnings.push(`Theme "${themeId}" has invalid contrast target: ${theme.a11y.contrastTarget}`);
|
|
148
122
|
}
|
|
149
123
|
}
|
|
@@ -187,23 +161,13 @@ function validateBuildConfig(build: any): ConfigValidationResult {
|
|
|
187
161
|
const errors: string[] = [];
|
|
188
162
|
const warnings: string[] = [];
|
|
189
163
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (!build.output.directory || typeof build.output.directory !== 'string') {
|
|
194
|
-
errors.push('Build output must have a "directory" string');
|
|
195
|
-
}
|
|
196
|
-
if (!build.output.formats || typeof build.output.formats !== 'object') {
|
|
197
|
-
errors.push('Build output must have a "formats" object');
|
|
198
|
-
}
|
|
164
|
+
// Only validate structure if provided
|
|
165
|
+
if (build.output && typeof build.output !== 'object') {
|
|
166
|
+
errors.push('Build output must be an object');
|
|
199
167
|
}
|
|
200
168
|
|
|
201
|
-
if (
|
|
202
|
-
errors.push('Build config must
|
|
203
|
-
} else {
|
|
204
|
-
if (build.sass.style && !['expanded', 'compressed', 'compact', 'nested'].includes(build.sass.style)) {
|
|
205
|
-
warnings.push(`Invalid Sass style: ${build.sass.style}`);
|
|
206
|
-
}
|
|
169
|
+
if (build.sass && typeof build.sass !== 'object') {
|
|
170
|
+
errors.push('Build sass config must be an object');
|
|
207
171
|
}
|
|
208
172
|
|
|
209
173
|
return { valid: errors.length === 0, errors, warnings };
|
|
@@ -242,15 +206,9 @@ function validateIntegrationConfig(integration: any): ConfigValidationResult {
|
|
|
242
206
|
const errors: string[] = [];
|
|
243
207
|
const warnings: string[] = [];
|
|
244
208
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!integration.classNames.theme || typeof integration.classNames.theme !== 'string') {
|
|
249
|
-
errors.push('Integration classNames must have a "theme" string');
|
|
250
|
-
}
|
|
251
|
-
if (!integration.classNames.colorMode || typeof integration.classNames.colorMode !== 'string') {
|
|
252
|
-
errors.push('Integration classNames must have a "colorMode" string');
|
|
253
|
-
}
|
|
209
|
+
// Only validate structure if provided
|
|
210
|
+
if (integration.classNames && typeof integration.classNames !== 'object') {
|
|
211
|
+
errors.push('Integration classNames must be an object');
|
|
254
212
|
}
|
|
255
213
|
|
|
256
214
|
return { valid: errors.length === 0, errors, warnings };
|
|
@@ -290,37 +248,3 @@ function validateDependencies(
|
|
|
290
248
|
return { valid: errors.length === 0, errors, warnings };
|
|
291
249
|
}
|
|
292
250
|
|
|
293
|
-
/**
|
|
294
|
-
* Check if string is valid semver
|
|
295
|
-
*/
|
|
296
|
-
function isValidSemver(version: string): boolean {
|
|
297
|
-
const semverRegex = /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/;
|
|
298
|
-
return semverRegex.test(version);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Check if string is valid color
|
|
303
|
-
*/
|
|
304
|
-
function isValidColor(color: string): boolean {
|
|
305
|
-
// Hex color
|
|
306
|
-
if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(color)) {
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
// RGB/RGBA
|
|
310
|
-
if (/^rgba?\(/.test(color)) {
|
|
311
|
-
return true;
|
|
312
|
-
}
|
|
313
|
-
// HSL/HSLA
|
|
314
|
-
if (/^hsla?\(/.test(color)) {
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
// Named colors (basic check)
|
|
318
|
-
const namedColors = [
|
|
319
|
-
'black', 'white', 'red', 'green', 'blue', 'yellow', 'cyan', 'magenta',
|
|
320
|
-
'transparent', 'currentColor',
|
|
321
|
-
];
|
|
322
|
-
if (namedColors.includes(color.toLowerCase())) {
|
|
323
|
-
return true;
|
|
324
|
-
}
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
@@ -24,14 +24,6 @@ export const DEFAULT_BASE_PATH = '/themes';
|
|
|
24
24
|
*/
|
|
25
25
|
export const DEFAULT_STYLE_ID = 'atomix-js-theme-styles';
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Default cache configuration
|
|
29
|
-
*/
|
|
30
|
-
export const DEFAULT_CACHE_CONFIG = {
|
|
31
|
-
maxSize: 50,
|
|
32
|
-
ttl: 0, // No expiration by default
|
|
33
|
-
} as const;
|
|
34
|
-
|
|
35
27
|
/**
|
|
36
28
|
* Default engine cache configuration
|
|
37
29
|
*/
|
|
@@ -58,21 +50,11 @@ export const CSS_EXTENSIONS = {
|
|
|
58
50
|
*/
|
|
59
51
|
export const DEFAULT_ATOMIX_CONFIG_PATH = 'atomix.config.ts';
|
|
60
52
|
|
|
61
|
-
/**
|
|
62
|
-
* Default config file path (legacy)
|
|
63
|
-
*/
|
|
64
|
-
export const DEFAULT_CONFIG_PATH = 'theme.config.ts';
|
|
65
|
-
|
|
66
53
|
/**
|
|
67
54
|
* Default config file path (relative)
|
|
68
55
|
*/
|
|
69
56
|
export const DEFAULT_CONFIG_RELATIVE_PATH = '../../../../atomix.config';
|
|
70
57
|
|
|
71
|
-
/**
|
|
72
|
-
* Default legacy config file path (relative)
|
|
73
|
-
*/
|
|
74
|
-
export const DEFAULT_LEGACY_CONFIG_RELATIVE_PATH = '../../../../theme.config';
|
|
75
|
-
|
|
76
58
|
/**
|
|
77
59
|
* Validation thresholds
|
|
78
60
|
*/
|
|
@@ -71,6 +71,8 @@ export class ThemeRegistry {
|
|
|
71
71
|
validated: false,
|
|
72
72
|
errors: [],
|
|
73
73
|
warnings: [],
|
|
74
|
+
__tokens: {},
|
|
75
|
+
__extend: {},
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
} else {
|
|
@@ -160,23 +162,34 @@ export class ThemeRegistry {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
/**
|
|
163
|
-
*
|
|
165
|
+
* Check if a theme is loaded
|
|
164
166
|
*/
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
isThemeLoaded(themeId: string): boolean {
|
|
168
|
+
const entry = this.entries.get(themeId);
|
|
169
|
+
return entry ? entry.loaded : false;
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
/**
|
|
170
|
-
*
|
|
173
|
+
* Mark a theme as loaded
|
|
171
174
|
*/
|
|
172
|
-
|
|
175
|
+
markLoaded(themeId: string, theme?: Theme): void {
|
|
173
176
|
const entry = this.entries.get(themeId);
|
|
174
177
|
if (entry) {
|
|
175
|
-
entry.theme = theme;
|
|
176
178
|
entry.loaded = true;
|
|
179
|
+
if (theme) {
|
|
180
|
+
entry.theme = theme;
|
|
181
|
+
}
|
|
177
182
|
}
|
|
178
183
|
}
|
|
179
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Get theme object (for JS themes)
|
|
187
|
+
*/
|
|
188
|
+
getTheme(themeId: string): Theme | undefined {
|
|
189
|
+
const entry = this.entries.get(themeId);
|
|
190
|
+
return entry?.loaded ? entry.theme : undefined;
|
|
191
|
+
}
|
|
192
|
+
|
|
180
193
|
/**
|
|
181
194
|
* Get dependencies for a theme
|
|
182
195
|
*/
|