@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,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Adapters
|
|
3
|
+
*
|
|
4
|
+
* Adapters for converting between Theme objects and DesignTokens
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
themeToDesignTokens,
|
|
9
|
+
designTokensToCSSVars,
|
|
10
|
+
createDesignTokensFromTheme,
|
|
11
|
+
designTokensToTheme,
|
|
12
|
+
} from './themeAdapter';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
generateCSSVariableName,
|
|
16
|
+
generateComponentCSSVars,
|
|
17
|
+
mapSCSSTokensToCSSVars,
|
|
18
|
+
applyCSSVariables,
|
|
19
|
+
removeCSSVariables,
|
|
20
|
+
getCSSVariable,
|
|
21
|
+
cssVarsToStyle,
|
|
22
|
+
mergeCSSVars,
|
|
23
|
+
isValidCSSVariableName,
|
|
24
|
+
extractComponentName,
|
|
25
|
+
} from './cssVariableMapper';
|
|
26
|
+
|
|
27
|
+
export type {
|
|
28
|
+
CSSVariableConfig,
|
|
29
|
+
CSSVariableNamingOptions,
|
|
30
|
+
} from './cssVariableMapper';
|
|
31
|
+
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Adapter
|
|
3
|
+
*
|
|
4
|
+
* Converts between Theme objects and DesignTokens.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Theme } from '../types';
|
|
8
|
+
import type { DesignTokens } from '../tokens/tokens';
|
|
9
|
+
import { createTokens } from '../tokens/tokens';
|
|
10
|
+
import { hexToRgb } from '../utils/themeUtils';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convert Theme object to DesignTokens
|
|
14
|
+
*
|
|
15
|
+
* Extracts values from a Theme object and converts them to flat DesignTokens format.
|
|
16
|
+
*
|
|
17
|
+
* @param theme - Theme object to convert
|
|
18
|
+
* @returns Partial DesignTokens object
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const theme = createTheme({ palette: { primary: { main: '#7c3aed' } } });
|
|
23
|
+
* const tokens = themeToDesignTokens(theme);
|
|
24
|
+
* // Returns: { 'primary': '#7c3aed', ... }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function themeToDesignTokens(theme: Theme): Partial<DesignTokens> {
|
|
28
|
+
const tokens: Partial<DesignTokens> = {};
|
|
29
|
+
|
|
30
|
+
// Convert palette colors
|
|
31
|
+
if (theme.palette) {
|
|
32
|
+
// Primary colors
|
|
33
|
+
if (theme.palette.primary) {
|
|
34
|
+
tokens['primary'] = theme.palette.primary.main;
|
|
35
|
+
if (theme.palette.primary.light) {
|
|
36
|
+
tokens['primary-3'] = theme.palette.primary.light;
|
|
37
|
+
}
|
|
38
|
+
if (theme.palette.primary.dark) {
|
|
39
|
+
tokens['primary-9'] = theme.palette.primary.dark;
|
|
40
|
+
}
|
|
41
|
+
// Extract RGB if available
|
|
42
|
+
if (theme.palette.primary.main) {
|
|
43
|
+
const rgb = hexToRgb(theme.palette.primary.main);
|
|
44
|
+
if (rgb) {
|
|
45
|
+
tokens['primary-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Secondary colors
|
|
51
|
+
if (theme.palette.secondary) {
|
|
52
|
+
tokens['secondary'] = theme.palette.secondary.main;
|
|
53
|
+
if (theme.palette.secondary.light) {
|
|
54
|
+
tokens['gray-1'] = theme.palette.secondary.light;
|
|
55
|
+
}
|
|
56
|
+
if (theme.palette.secondary.dark) {
|
|
57
|
+
tokens['gray-3'] = theme.palette.secondary.dark;
|
|
58
|
+
}
|
|
59
|
+
const rgb = hexToRgb(theme.palette.secondary.main);
|
|
60
|
+
if (rgb) {
|
|
61
|
+
tokens['secondary-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Error colors
|
|
66
|
+
if (theme.palette.error) {
|
|
67
|
+
tokens['error'] = theme.palette.error.main;
|
|
68
|
+
tokens['red-6'] = theme.palette.error.main;
|
|
69
|
+
if (theme.palette.error.light) {
|
|
70
|
+
tokens['red-4'] = theme.palette.error.light;
|
|
71
|
+
}
|
|
72
|
+
if (theme.palette.error.dark) {
|
|
73
|
+
tokens['red-9'] = theme.palette.error.dark;
|
|
74
|
+
}
|
|
75
|
+
const rgb = hexToRgb(theme.palette.error.main);
|
|
76
|
+
if (rgb) {
|
|
77
|
+
tokens['error-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Success colors
|
|
82
|
+
if (theme.palette.success) {
|
|
83
|
+
tokens['success'] = theme.palette.success.main;
|
|
84
|
+
tokens['green-6'] = theme.palette.success.main;
|
|
85
|
+
if (theme.palette.success.light) {
|
|
86
|
+
tokens['green-4'] = theme.palette.success.light;
|
|
87
|
+
}
|
|
88
|
+
if (theme.palette.success.dark) {
|
|
89
|
+
tokens['green-9'] = theme.palette.success.dark;
|
|
90
|
+
}
|
|
91
|
+
const rgb = hexToRgb(theme.palette.success.main);
|
|
92
|
+
if (rgb) {
|
|
93
|
+
tokens['success-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Warning colors
|
|
98
|
+
if (theme.palette.warning) {
|
|
99
|
+
tokens['warning'] = theme.palette.warning.main;
|
|
100
|
+
tokens['yellow-6'] = theme.palette.warning.main;
|
|
101
|
+
if (theme.palette.warning.light) {
|
|
102
|
+
tokens['yellow-4'] = theme.palette.warning.light;
|
|
103
|
+
}
|
|
104
|
+
if (theme.palette.warning.dark) {
|
|
105
|
+
tokens['yellow-9'] = theme.palette.warning.dark;
|
|
106
|
+
}
|
|
107
|
+
const rgb = hexToRgb(theme.palette.warning.main);
|
|
108
|
+
if (rgb) {
|
|
109
|
+
tokens['warning-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Info colors
|
|
114
|
+
if (theme.palette.info) {
|
|
115
|
+
tokens['info'] = theme.palette.info.main;
|
|
116
|
+
tokens['blue-6'] = theme.palette.info.main;
|
|
117
|
+
if (theme.palette.info.light) {
|
|
118
|
+
tokens['blue-4'] = theme.palette.info.light;
|
|
119
|
+
}
|
|
120
|
+
if (theme.palette.info.dark) {
|
|
121
|
+
tokens['blue-9'] = theme.palette.info.dark;
|
|
122
|
+
}
|
|
123
|
+
const rgb = hexToRgb(theme.palette.info.main);
|
|
124
|
+
if (rgb) {
|
|
125
|
+
tokens['info-rgb'] = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Background colors
|
|
130
|
+
if (theme.palette.background) {
|
|
131
|
+
tokens['body-bg'] = theme.palette.background.default;
|
|
132
|
+
tokens['primary-bg-subtle'] = theme.palette.background.default;
|
|
133
|
+
tokens['secondary-bg-subtle'] = theme.palette.background.paper;
|
|
134
|
+
tokens['tertiary-bg-subtle'] = theme.palette.background.subtle;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Text colors
|
|
138
|
+
if (theme.palette.text) {
|
|
139
|
+
tokens['body-color'] = theme.palette.text.primary;
|
|
140
|
+
tokens['heading-color'] = theme.palette.text.primary;
|
|
141
|
+
tokens['primary-text-emphasis'] = theme.palette.text.primary;
|
|
142
|
+
tokens['secondary-text-emphasis'] = theme.palette.text.secondary;
|
|
143
|
+
tokens['disabled-text-emphasis'] = theme.palette.text.disabled;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Convert typography
|
|
148
|
+
if (theme.typography) {
|
|
149
|
+
tokens['body-font-family'] = theme.typography.fontFamily;
|
|
150
|
+
tokens['font-sans-serif'] = theme.typography.fontFamily;
|
|
151
|
+
tokens['body-font-size'] = `${theme.typography.fontSize}px`;
|
|
152
|
+
tokens['body-font-weight'] = String(theme.typography.fontWeightRegular);
|
|
153
|
+
|
|
154
|
+
// Font weights
|
|
155
|
+
tokens['font-weight-light'] = String(theme.typography.fontWeightLight);
|
|
156
|
+
tokens['font-weight-normal'] = String(theme.typography.fontWeightRegular);
|
|
157
|
+
tokens['font-weight-medium'] = String(theme.typography.fontWeightMedium);
|
|
158
|
+
tokens['font-weight-semibold'] = String(theme.typography.fontWeightSemiBold);
|
|
159
|
+
tokens['font-weight-bold'] = String(theme.typography.fontWeightBold);
|
|
160
|
+
|
|
161
|
+
// Line heights
|
|
162
|
+
if (theme.typography.h1?.lineHeight) {
|
|
163
|
+
tokens['line-height-base'] = String(theme.typography.h1.lineHeight);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Convert spacing (if available as object)
|
|
168
|
+
if (theme.spacing && typeof theme.spacing === 'object' && !('__isSpacingFunction' in theme.spacing)) {
|
|
169
|
+
const spacing = theme.spacing as Record<string, string | number>;
|
|
170
|
+
Object.entries(spacing).forEach(([key, value]) => {
|
|
171
|
+
tokens[`spacing-${key}` as keyof DesignTokens] = String(value);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Convert border radius
|
|
176
|
+
if (theme.borderRadius) {
|
|
177
|
+
Object.entries(theme.borderRadius).forEach(([key, value]) => {
|
|
178
|
+
const tokenKey = key === 'sm' ? 'border-radius-sm' :
|
|
179
|
+
key === 'md' ? 'border-radius' :
|
|
180
|
+
key === 'lg' ? 'border-radius-lg' :
|
|
181
|
+
key === 'xl' ? 'border-radius-xl' :
|
|
182
|
+
key === 'xxl' ? 'border-radius-xxl' :
|
|
183
|
+
`border-radius-${key}`;
|
|
184
|
+
tokens[tokenKey as keyof DesignTokens] = String(value);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Convert shadows
|
|
189
|
+
if (theme.shadows) {
|
|
190
|
+
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
191
|
+
const tokenKey = key === 'xs' ? 'box-shadow-xs' :
|
|
192
|
+
key === 'sm' ? 'box-shadow-sm' :
|
|
193
|
+
key === 'md' ? 'box-shadow' :
|
|
194
|
+
key === 'lg' ? 'box-shadow-lg' :
|
|
195
|
+
key === 'xl' ? 'box-shadow-xl' :
|
|
196
|
+
`box-shadow-${key}`;
|
|
197
|
+
tokens[tokenKey as keyof DesignTokens] = String(value);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Convert z-index
|
|
202
|
+
if (theme.zIndex) {
|
|
203
|
+
Object.entries(theme.zIndex).forEach(([key, value]) => {
|
|
204
|
+
tokens[`z-${key}` as keyof DesignTokens] = String(value);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Convert transitions
|
|
209
|
+
if (theme.transitions) {
|
|
210
|
+
if (theme.transitions.duration) {
|
|
211
|
+
Object.entries(theme.transitions.duration).forEach(([key, value]) => {
|
|
212
|
+
tokens[`transition-duration-${key}` as keyof DesignTokens] = String(value);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (theme.transitions.easing) {
|
|
216
|
+
Object.entries(theme.transitions.easing).forEach(([key, value]) => {
|
|
217
|
+
tokens[`easing-${key}` as keyof DesignTokens] = String(value);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Convert breakpoints
|
|
223
|
+
if (theme.breakpoints?.values) {
|
|
224
|
+
Object.entries(theme.breakpoints.values).forEach(([key, value]) => {
|
|
225
|
+
tokens[`breakpoint-${key}` as keyof DesignTokens] = String(value);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Merge any existing cssVars from theme
|
|
230
|
+
if (theme.cssVars) {
|
|
231
|
+
Object.entries(theme.cssVars).forEach(([key, value]) => {
|
|
232
|
+
// Remove --atomix- prefix if present
|
|
233
|
+
const cleanKey = key.replace(/^--atomix-/, '').replace(/^--/, '');
|
|
234
|
+
tokens[cleanKey as keyof DesignTokens] = String(value);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return tokens;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Convert DesignTokens to Theme-compatible CSS variables
|
|
243
|
+
*
|
|
244
|
+
* @param tokens - DesignTokens object
|
|
245
|
+
* @returns CSS variables object compatible with Theme.cssVars
|
|
246
|
+
*/
|
|
247
|
+
export function designTokensToCSSVars(tokens: Partial<DesignTokens>): Record<string, string> {
|
|
248
|
+
const cssVars: Record<string, string> = {};
|
|
249
|
+
|
|
250
|
+
Object.entries(tokens).forEach(([key, value]) => {
|
|
251
|
+
if (value !== undefined) {
|
|
252
|
+
cssVars[`--atomix-${key}`] = String(value);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return cssVars;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Create DesignTokens from Theme with defaults
|
|
261
|
+
*
|
|
262
|
+
* Converts a Theme to DesignTokens and merges with default tokens.
|
|
263
|
+
*
|
|
264
|
+
* @param theme - Theme object to convert
|
|
265
|
+
* @returns Complete DesignTokens object
|
|
266
|
+
*/
|
|
267
|
+
export function createDesignTokensFromTheme(theme: Theme): DesignTokens {
|
|
268
|
+
const partialTokens = themeToDesignTokens(theme);
|
|
269
|
+
return createTokens(partialTokens);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Create a minimal Theme object from DesignTokens
|
|
274
|
+
*
|
|
275
|
+
* @param tokens - DesignTokens to convert
|
|
276
|
+
* @returns Minimal Theme object with cssVars populated
|
|
277
|
+
*/
|
|
278
|
+
export function designTokensToTheme(tokens: Partial<DesignTokens>): Partial<Theme> {
|
|
279
|
+
const cssVars = designTokensToCSSVars(tokens);
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
name: 'Design Tokens Theme',
|
|
283
|
+
cssVars,
|
|
284
|
+
__isJSTheme: true,
|
|
285
|
+
} as Partial<Theme>;
|
|
286
|
+
}
|
|
287
|
+
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for automatic config loading from atomix.config.ts
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
8
|
+
import { loadThemeFromConfigSync, loadThemeFromConfig } from '../configLoader';
|
|
9
|
+
import { createTheme } from '../../core/createTheme';
|
|
10
|
+
import type { DesignTokens } from '../../tokens/tokens';
|
|
11
|
+
|
|
12
|
+
describe('Config Loader', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
// Clear any cached configs
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('loadThemeFromConfigSync', () => {
|
|
23
|
+
it('should return empty object in browser environment', () => {
|
|
24
|
+
// Mock window object
|
|
25
|
+
const originalWindow = global.window;
|
|
26
|
+
// @ts-expect-error - intentionally setting window for test
|
|
27
|
+
global.window = {};
|
|
28
|
+
|
|
29
|
+
const result = loadThemeFromConfigSync();
|
|
30
|
+
expect(result).toEqual({});
|
|
31
|
+
|
|
32
|
+
// Restore
|
|
33
|
+
global.window = originalWindow;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should handle missing config file gracefully', () => {
|
|
37
|
+
// In Node.js environment, if config doesn't exist, should return empty object
|
|
38
|
+
const result = loadThemeFromConfigSync('non-existent-config.ts');
|
|
39
|
+
expect(result).toEqual({});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('loadThemeFromConfig', () => {
|
|
44
|
+
it('should return empty object in browser environment', async () => {
|
|
45
|
+
// Mock window object
|
|
46
|
+
const originalWindow = global.window;
|
|
47
|
+
// @ts-expect-error - intentionally setting window for test
|
|
48
|
+
global.window = {};
|
|
49
|
+
|
|
50
|
+
const result = await loadThemeFromConfig();
|
|
51
|
+
expect(result).toEqual({});
|
|
52
|
+
|
|
53
|
+
// Restore
|
|
54
|
+
global.window = originalWindow;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should handle missing config file gracefully', async () => {
|
|
58
|
+
const result = await loadThemeFromConfig('non-existent-config.ts');
|
|
59
|
+
expect(result).toEqual({});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('Token Flattening', () => {
|
|
64
|
+
it('should correctly map simple color strings', () => {
|
|
65
|
+
// This tests the internal flattenConfigTokens function indirectly
|
|
66
|
+
// by checking that createTheme can handle config structure
|
|
67
|
+
const mockConfig = {
|
|
68
|
+
theme: {
|
|
69
|
+
extend: {
|
|
70
|
+
colors: {
|
|
71
|
+
primary: '#7AFFD7',
|
|
72
|
+
secondary: '#FF5733',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Since we can't directly test the private function,
|
|
79
|
+
// we test through createTheme which uses it
|
|
80
|
+
// This is an integration test
|
|
81
|
+
expect(typeof createTheme).toBe('function');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should correctly map palette color objects', () => {
|
|
85
|
+
const mockConfig = {
|
|
86
|
+
theme: {
|
|
87
|
+
extend: {
|
|
88
|
+
colors: {
|
|
89
|
+
primary: {
|
|
90
|
+
main: '#7AFFD7',
|
|
91
|
+
light: '#B3FFE9',
|
|
92
|
+
dark: '#00E6C3',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Integration test through createTheme
|
|
100
|
+
expect(typeof createTheme).toBe('function');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should correctly map color scales', () => {
|
|
104
|
+
const mockConfig = {
|
|
105
|
+
theme: {
|
|
106
|
+
extend: {
|
|
107
|
+
colors: {
|
|
108
|
+
primary: {
|
|
109
|
+
1: '#f0f9ff',
|
|
110
|
+
6: '#3b82f6',
|
|
111
|
+
10: '#1e3a8a',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Integration test
|
|
119
|
+
expect(typeof createTheme).toBe('function');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should correctly map spacing tokens', () => {
|
|
123
|
+
const mockConfig = {
|
|
124
|
+
theme: {
|
|
125
|
+
extend: {
|
|
126
|
+
spacing: {
|
|
127
|
+
'4': '1rem',
|
|
128
|
+
'8': '2rem',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Integration test
|
|
135
|
+
expect(typeof createTheme).toBe('function');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should correctly map typography tokens', () => {
|
|
139
|
+
const mockConfig = {
|
|
140
|
+
theme: {
|
|
141
|
+
extend: {
|
|
142
|
+
typography: {
|
|
143
|
+
fontFamilies: {
|
|
144
|
+
sans: ['Inter', 'sans-serif'],
|
|
145
|
+
},
|
|
146
|
+
fontSizes: {
|
|
147
|
+
'2xl': '1.5rem',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Integration test
|
|
155
|
+
expect(typeof createTheme).toBe('function');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('createTheme with Config Loading', () => {
|
|
161
|
+
it('should work without input (will use defaults if config not available)', () => {
|
|
162
|
+
// createTheme() should work even if config is not available
|
|
163
|
+
// It will fall back to default tokens
|
|
164
|
+
const css = createTheme();
|
|
165
|
+
|
|
166
|
+
expect(typeof css).toBe('string');
|
|
167
|
+
expect(css).toContain(':root');
|
|
168
|
+
expect(css).toContain('--atomix');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should accept DesignTokens input', () => {
|
|
172
|
+
const tokens: Partial<DesignTokens> = {
|
|
173
|
+
'primary': '#7AFFD7',
|
|
174
|
+
'spacing-4': '1rem',
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const css = createTheme(tokens);
|
|
178
|
+
|
|
179
|
+
expect(typeof css).toBe('string');
|
|
180
|
+
expect(css).toContain('--atomix-primary');
|
|
181
|
+
expect(css).toContain('#7AFFD7');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should respect prefix option', () => {
|
|
185
|
+
const tokens: Partial<DesignTokens> = {
|
|
186
|
+
'primary': '#7AFFD7',
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const css = createTheme(tokens, { prefix: 'myapp' });
|
|
190
|
+
|
|
191
|
+
expect(css).toContain('--myapp-primary');
|
|
192
|
+
expect(css).not.toContain('--atomix-primary');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should respect selector option', () => {
|
|
196
|
+
const tokens: Partial<DesignTokens> = {
|
|
197
|
+
'primary': '#7AFFD7',
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const css = createTheme(tokens, { selector: '[data-theme="dark"]' });
|
|
201
|
+
|
|
202
|
+
expect(css).toContain('[data-theme="dark"]');
|
|
203
|
+
expect(css).not.toContain(':root');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
|