@shohojdhara/atomix 0.3.5 → 0.3.7
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 +260 -179
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +250 -179
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +69 -166
- package/dist/charts.js.map +1 -1
- package/dist/core.js +184 -263
- package/dist/core.js.map +1 -1
- package/dist/forms.js +55 -131
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +184 -263
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +1831 -1657
- package/dist/index.esm.js +4497 -4318
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +4510 -4328
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +1431 -1472
- package/dist/theme.js +4175 -4138
- package/dist/theme.js.map +1 -1
- package/package.json +6 -20
- package/src/components/Accordion/Accordion.stories.tsx +50 -17
- package/src/components/AtomixGlass/AtomixGlass.tsx +128 -322
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +12 -5
- 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/Badge/Badge.stories.tsx +91 -13
- package/src/components/Block/Block.stories.tsx +7 -23
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +7 -0
- package/src/components/Button/Button.stories.tsx +141 -22
- package/src/components/Button/Button.tsx +85 -167
- 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/Chart/AnimatedChart.tsx +0 -1
- package/src/components/Chart/AreaChart.tsx +0 -1
- package/src/components/Chart/BarChart.tsx +0 -1
- package/src/components/Chart/BubbleChart.tsx +0 -1
- 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/DonutChart.tsx +0 -1
- package/src/components/Chart/FunnelChart.tsx +0 -1
- 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 +0 -1
- package/src/components/Chart/ScatterChart.tsx +0 -1
- package/src/components/Chart/WaterfallChart.tsx +0 -1
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +7 -0
- package/src/components/DataTable/DataTable.stories.tsx +23 -16
- package/src/components/DatePicker/DatePicker.stories.tsx +27 -19
- package/src/components/Dropdown/Dropdown.stories.tsx +11 -19
- 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/Form/Checkbox.stories.tsx +7 -0
- 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/Radio.stories.tsx +9 -1
- package/src/components/Form/Select.stories.tsx +9 -1
- package/src/components/Form/Textarea.stories.tsx +10 -2
- package/src/components/Hero/Hero.stories.tsx +7 -0
- package/src/components/List/List.stories.tsx +7 -0
- package/src/components/Messages/Messages.stories.tsx +8 -7
- package/src/components/Modal/Modal.stories.tsx +17 -6
- package/src/components/Navigation/Menu/Menu.stories.tsx +7 -0
- 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 +83 -3
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -5
- package/src/components/Popover/Popover.stories.tsx +191 -115
- package/src/components/ProductReview/ProductReview.stories.tsx +80 -58
- package/src/components/Progress/Progress.stories.tsx +79 -49
- package/src/components/Rating/Rating.stories.tsx +109 -84
- 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/Spinner/Spinner.stories.tsx +15 -11
- package/src/components/Steps/Steps.stories.tsx +132 -98
- package/src/components/Tabs/Tabs.stories.tsx +163 -112
- 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/Upload/Upload.stories.tsx +122 -84
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +7 -24
- package/src/components/index.ts +1 -0
- package/src/lib/composables/useAtomixGlass.ts +9 -10
- package/src/lib/composables/useNavbar.ts +0 -10
- package/src/lib/config/loader.ts +4 -4
- package/src/lib/constants/components.ts +17 -0
- package/src/lib/hooks/useComponentCustomization.ts +1 -1
- package/src/lib/hooks/usePerformanceMonitor.ts +1 -1
- package/src/lib/hooks/useThemeTokens.ts +105 -0
- 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 +95 -0
- package/src/lib/theme/config/loader.ts +37 -54
- 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} +1 -19
- package/src/lib/theme/constants/index.ts +8 -0
- package/src/lib/theme/core/ThemeRegistry.ts +75 -266
- package/src/lib/theme/core/__tests__/createTheme.test.ts +132 -0
- package/src/lib/theme/core/composeTheme.ts +105 -0
- package/src/lib/theme/core/createTheme.ts +108 -0
- package/src/lib/theme/{createTheme.ts → core/createThemeObject.ts} +12 -8
- package/src/lib/theme/core/index.ts +19 -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 +478 -107
- package/src/lib/theme/devtools/Preview.tsx +471 -221
- package/src/lib/theme/{core → devtools}/ThemeValidator.ts +1 -1
- package/src/lib/theme/devtools/index.ts +14 -4
- package/src/lib/theme/devtools/useHistory.ts +130 -0
- package/src/lib/theme/{errors.ts → errors/errors.ts} +1 -1
- 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/generators/generateCSSNested.ts +130 -0
- package/src/lib/theme/{generateCSSVariables.ts → generators/generateCSSVariables.ts} +3 -13
- package/src/lib/theme/generators/index.ts +25 -0
- package/src/lib/theme/i18n/rtl.ts +5 -6
- package/src/lib/theme/index.ts +149 -19
- package/src/lib/theme/runtime/ThemeApplicator.ts +53 -112
- package/src/lib/theme/{ThemeContext.tsx → runtime/ThemeContext.tsx} +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +5 -5
- package/src/lib/theme/runtime/ThemeProvider.tsx +266 -282
- package/src/lib/theme/runtime/index.ts +2 -2
- package/src/lib/theme/runtime/useTheme.ts +1 -2
- package/src/lib/theme/runtime/useThemeTokens.ts +131 -0
- 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/componentTheming.ts +132 -0
- 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/naming.ts +100 -0
- package/src/lib/theme/utils/themeHelpers.ts +78 -0
- package/src/lib/theme/{themeUtils.ts → utils/themeUtils.ts} +7 -7
- package/src/lib/theme-tools.ts +7 -8
- package/src/lib/types/components.ts +40 -130
- package/src/lib/utils/componentUtils.ts +2 -2
- package/src/lib/utils/memoryMonitor.ts +3 -3
- package/src/lib/utils/themeNaming.ts +135 -0
- package/src/styles/01-settings/_settings.design-tokens.scss +4 -1
- 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.pagination.scss +88 -0
- package/scripts/sync-theme-config.js +0 -309
- 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 -665
- 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 -446
- package/src/styles/03-generic/_generated-root.css +0 -26
- package/src/themes/README.md +0 -442
- package/src/themes/themes.config.js +0 -68
- /package/src/lib/theme/{cssVariableMapper.ts → adapters/cssVariableMapper.ts} +0 -0
package/src/lib/theme/types.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* TypeScript types and interfaces for the Atomix Design System theme management system.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ThemeManager as ThemeManagerType } from './runtime/ThemeManager';
|
|
8
7
|
import type { PartStyleProps } from '../types/partProps';
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -42,39 +41,6 @@ export interface ThemeMetadata {
|
|
|
42
41
|
dependencies?: string[];
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
/**
|
|
46
|
-
* Theme manager configuration options
|
|
47
|
-
*/
|
|
48
|
-
export interface ThemeManagerConfig {
|
|
49
|
-
/** Available themes metadata */
|
|
50
|
-
themes: Record<string, ThemeMetadata>;
|
|
51
|
-
/** Default theme to use */
|
|
52
|
-
defaultTheme?: string | Theme;
|
|
53
|
-
/** Base path for theme CSS files */
|
|
54
|
-
basePath?: string;
|
|
55
|
-
/** CDN path for theme CSS files (optional) */
|
|
56
|
-
cdnPath?: string | null;
|
|
57
|
-
/** Themes to preload on initialization */
|
|
58
|
-
preload?: string[];
|
|
59
|
-
/** Enable lazy loading of themes */
|
|
60
|
-
lazy?: boolean;
|
|
61
|
-
/** localStorage key for persistence */
|
|
62
|
-
storageKey?: string;
|
|
63
|
-
/** Data attribute name for theme */
|
|
64
|
-
dataAttribute?: string;
|
|
65
|
-
/** Enable persistence */
|
|
66
|
-
enablePersistence?: boolean;
|
|
67
|
-
/** Custom CSS file extension */
|
|
68
|
-
cssExtension?: string;
|
|
69
|
-
/** Use minified CSS files */
|
|
70
|
-
useMinified?: boolean;
|
|
71
|
-
/** Callback when theme changes */
|
|
72
|
-
onThemeChange?: (theme: string | Theme) => void;
|
|
73
|
-
/** Callback when theme load fails */
|
|
74
|
-
onError?: (error: Error, themeName: string) => void;
|
|
75
|
-
/** RTL configuration */
|
|
76
|
-
rtl?: import('./i18n/rtl').RTLConfig;
|
|
77
|
-
}
|
|
78
44
|
|
|
79
45
|
/**
|
|
80
46
|
* Theme change event payload
|
|
@@ -160,7 +126,7 @@ export interface UseThemeOptions {
|
|
|
160
126
|
/** Custom storage key */
|
|
161
127
|
storageKey?: string;
|
|
162
128
|
/** Callback when theme changes */
|
|
163
|
-
onChange?: (theme: string | Theme) => void;
|
|
129
|
+
onChange?: (theme: string | Theme | import('./tokens').DesignTokens) => void;
|
|
164
130
|
}
|
|
165
131
|
|
|
166
132
|
/**
|
|
@@ -171,8 +137,8 @@ export interface UseThemeReturn {
|
|
|
171
137
|
theme: string;
|
|
172
138
|
/** Current active theme object (for JS themes) */
|
|
173
139
|
activeTheme: Theme | null;
|
|
174
|
-
/** Function to change theme */
|
|
175
|
-
setTheme: (theme: string | Theme
|
|
140
|
+
/** Function to change theme (supports string, Theme, or DesignTokens) */
|
|
141
|
+
setTheme: (theme: string | Theme | import('./tokens').DesignTokens | Partial<import('./tokens').DesignTokens>, options?: ThemeLoadOptions) => Promise<void>;
|
|
176
142
|
/** Available themes */
|
|
177
143
|
availableThemes: ThemeMetadata[];
|
|
178
144
|
/** Whether a theme is currently loading */
|
|
@@ -268,7 +234,7 @@ export interface ThemeProviderProps {
|
|
|
268
234
|
/** Use minified CSS */
|
|
269
235
|
useMinified?: boolean;
|
|
270
236
|
/** Callback when theme changes */
|
|
271
|
-
onThemeChange?: (theme: string | Theme) => void;
|
|
237
|
+
onThemeChange?: (theme: string | Theme | import('./tokens').DesignTokens) => void;
|
|
272
238
|
/** Callback on error */
|
|
273
239
|
onError?: (error: Error, themeName: string) => void;
|
|
274
240
|
}
|
|
@@ -281,8 +247,8 @@ export interface ThemeContextValue {
|
|
|
281
247
|
theme: string;
|
|
282
248
|
/** Current active theme object (for JS themes) */
|
|
283
249
|
activeTheme: Theme | null;
|
|
284
|
-
/** Set theme function */
|
|
285
|
-
setTheme: (theme: string | Theme
|
|
250
|
+
/** Set theme function (supports string, Theme, or DesignTokens) */
|
|
251
|
+
setTheme: (theme: string | Theme | import('./tokens').DesignTokens | Partial<import('./tokens').DesignTokens>, options?: ThemeLoadOptions) => Promise<void>;
|
|
286
252
|
/** Available themes */
|
|
287
253
|
availableThemes: ThemeMetadata[];
|
|
288
254
|
/** Loading state */
|
|
@@ -293,8 +259,6 @@ export interface ThemeContextValue {
|
|
|
293
259
|
isThemeLoaded: (themeName: string) => boolean;
|
|
294
260
|
/** Preload theme */
|
|
295
261
|
preloadTheme: (themeName: string) => Promise<void>;
|
|
296
|
-
/** Theme manager instance */
|
|
297
|
-
themeManager: ThemeManagerType;
|
|
298
262
|
}
|
|
299
263
|
|
|
300
264
|
// ============================================================================
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Theming Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent patterns for applying theme values to components
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Theme } from '../types';
|
|
8
|
+
|
|
9
|
+
export interface ComponentThemeOptions {
|
|
10
|
+
component: string;
|
|
11
|
+
variant?: string;
|
|
12
|
+
size?: string;
|
|
13
|
+
theme: Theme;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get a theme value for a specific component using CSS variables
|
|
18
|
+
* This ensures all components access theme values consistently
|
|
19
|
+
*/
|
|
20
|
+
export function getComponentThemeValue(
|
|
21
|
+
component: string,
|
|
22
|
+
property: string,
|
|
23
|
+
variant?: string,
|
|
24
|
+
size?: string
|
|
25
|
+
): string {
|
|
26
|
+
// Build CSS variable name following consistent pattern
|
|
27
|
+
const parts = ['atomix', component];
|
|
28
|
+
|
|
29
|
+
if (variant) {
|
|
30
|
+
parts.push(variant);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (size) {
|
|
34
|
+
parts.push(size);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
parts.push(property);
|
|
38
|
+
|
|
39
|
+
const cssVarName = `--${parts.join('-')}`;
|
|
40
|
+
const fallbackVarName = `--atomix-${property}`;
|
|
41
|
+
|
|
42
|
+
// Return CSS variable reference with fallback
|
|
43
|
+
return `var(${cssVarName}, var(${fallbackVarName}, initial))`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate component-specific CSS variables from theme
|
|
48
|
+
*/
|
|
49
|
+
export function generateComponentCSSVars(
|
|
50
|
+
component: string,
|
|
51
|
+
theme: Theme,
|
|
52
|
+
variant?: string,
|
|
53
|
+
size?: string
|
|
54
|
+
): Record<string, string> {
|
|
55
|
+
const vars: Record<string, string> = {};
|
|
56
|
+
|
|
57
|
+
// This is a simplified implementation - in a real system you'd have more
|
|
58
|
+
// sophisticated logic to extract component-specific values from the theme
|
|
59
|
+
const prefixParts = ['atomix', component];
|
|
60
|
+
|
|
61
|
+
if (variant) {
|
|
62
|
+
prefixParts.push(variant);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (size) {
|
|
66
|
+
prefixParts.push(size);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const prefix = prefixParts.join('-');
|
|
70
|
+
|
|
71
|
+
// Add common component properties
|
|
72
|
+
if (theme.palette) {
|
|
73
|
+
vars[`--${prefix}-color`] = theme.palette.primary?.main || '#7c3aed';
|
|
74
|
+
vars[`--${prefix}-color-hover`] = theme.palette.primary?.dark || '#5b21b6';
|
|
75
|
+
vars[`--${prefix}-color-active`] = theme.palette.primary?.main || '#7c3aed';
|
|
76
|
+
vars[`--${prefix}-color-disabled`] = theme.palette.text?.disabled || '#9ca3af';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (theme.typography) {
|
|
80
|
+
vars[`--${prefix}-font-family`] = theme.typography.fontFamily || 'Inter, sans-serif';
|
|
81
|
+
vars[`--${prefix}-font-size`] = theme.typography.fontSize ? `${theme.typography.fontSize}px` : '16px';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (theme.spacing) {
|
|
85
|
+
const spacing = typeof theme.spacing === 'function' ? theme.spacing : (val: number) => val * 8;
|
|
86
|
+
vars[`--${prefix}-spacing-unit`] = `${spacing(1)}px`;
|
|
87
|
+
vars[`--${prefix}-spacing-sm`] = `${spacing(0.5)}px`;
|
|
88
|
+
vars[`--${prefix}-spacing-md`] = `${spacing(1)}px`;
|
|
89
|
+
vars[`--${prefix}-spacing-lg`] = `${spacing(2)}px`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return vars;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Apply consistent theme to component style object
|
|
97
|
+
*/
|
|
98
|
+
export function applyComponentTheme(
|
|
99
|
+
component: string,
|
|
100
|
+
style: React.CSSProperties = {},
|
|
101
|
+
variant?: string,
|
|
102
|
+
size?: string,
|
|
103
|
+
theme?: Theme
|
|
104
|
+
): React.CSSProperties {
|
|
105
|
+
// If no theme provided, return original style
|
|
106
|
+
if (!theme) {
|
|
107
|
+
return style;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Generate component-specific CSS variables
|
|
111
|
+
const componentVars = generateComponentCSSVars(component, theme, variant, size);
|
|
112
|
+
|
|
113
|
+
// Merge with existing style
|
|
114
|
+
return {
|
|
115
|
+
...componentVars,
|
|
116
|
+
...style,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a hook for consistent component theming
|
|
122
|
+
*/
|
|
123
|
+
export function useComponentTheme(
|
|
124
|
+
component: string,
|
|
125
|
+
variant?: string,
|
|
126
|
+
size?: string,
|
|
127
|
+
theme?: Theme
|
|
128
|
+
): (property: string) => string {
|
|
129
|
+
return (property: string) => {
|
|
130
|
+
return getComponentThemeValue(component, property, variant, size);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* and theme validation.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ThemeMetadata, ThemeValidationResult } from '
|
|
9
|
-
import { THEME_LINK_ID_PREFIX } from '
|
|
8
|
+
import type { ThemeMetadata, ThemeValidationResult } from '../types';
|
|
9
|
+
import { THEME_LINK_ID_PREFIX } from '../constants/constants';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Check if code is running in a browser environment
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS Injection Utilities
|
|
3
|
+
*
|
|
4
|
+
* Inject CSS into HTML head via <style> element.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Check if running in browser environment
|
|
9
|
+
*/
|
|
10
|
+
function isBrowser(): boolean {
|
|
11
|
+
return typeof document !== 'undefined';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Inject CSS into HTML head via <style> element
|
|
16
|
+
*
|
|
17
|
+
* Creates or updates a style element in the document head.
|
|
18
|
+
* If an element with the same ID exists, it will be updated.
|
|
19
|
+
*
|
|
20
|
+
* @param css - CSS string to inject
|
|
21
|
+
* @param id - Style element ID (default: 'atomix-theme')
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const css = ':root { --atomix-color-primary: #7AFFD7; }';
|
|
26
|
+
* injectCSS(css);
|
|
27
|
+
*
|
|
28
|
+
* // With custom ID
|
|
29
|
+
* injectCSS(css, 'my-custom-theme');
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function injectCSS(
|
|
33
|
+
css: string,
|
|
34
|
+
id: string = 'atomix-theme'
|
|
35
|
+
): void {
|
|
36
|
+
if (!isBrowser()) {
|
|
37
|
+
console.warn('injectCSS: Not in browser environment, CSS not injected');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let styleElement = document.getElementById(id) as HTMLStyleElement | null;
|
|
42
|
+
|
|
43
|
+
if (!styleElement) {
|
|
44
|
+
styleElement = document.createElement('style');
|
|
45
|
+
styleElement.id = id;
|
|
46
|
+
styleElement.setAttribute('data-atomix-theme', 'true');
|
|
47
|
+
document.head.appendChild(styleElement);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
styleElement.textContent = css;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Remove injected CSS from DOM
|
|
55
|
+
*
|
|
56
|
+
* Removes the style element with the given ID from the document head.
|
|
57
|
+
*
|
|
58
|
+
* @param id - Style element ID to remove (default: 'atomix-theme')
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* removeCSS(); // Removes default 'atomix-theme'
|
|
63
|
+
* removeCSS('my-custom-theme'); // Removes custom ID
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function removeCSS(id: string = 'atomix-theme'): void {
|
|
67
|
+
if (!isBrowser()) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const styleElement = document.getElementById(id);
|
|
72
|
+
if (styleElement) {
|
|
73
|
+
styleElement.remove();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if CSS is already injected
|
|
79
|
+
*
|
|
80
|
+
* @param id - Style element ID to check (default: 'atomix-theme')
|
|
81
|
+
* @returns True if style element exists
|
|
82
|
+
*/
|
|
83
|
+
export function isCSSInjected(id: string = 'atomix-theme'): boolean {
|
|
84
|
+
if (!isBrowser()) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return document.getElementById(id) !== null;
|
|
89
|
+
}
|
|
90
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Naming Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent naming conventions across the theme system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface NamingOptions {
|
|
8
|
+
prefix?: string;
|
|
9
|
+
component?: string;
|
|
10
|
+
variant?: string;
|
|
11
|
+
state?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Generate consistent CSS class names following BEM methodology
|
|
16
|
+
*/
|
|
17
|
+
export function generateClassName(block: string, element?: string, modifiers?: Record<string, boolean | string>): string {
|
|
18
|
+
let className = block;
|
|
19
|
+
|
|
20
|
+
if (element) {
|
|
21
|
+
className += `__${element}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (modifiers) {
|
|
25
|
+
Object.entries(modifiers).forEach(([key, value]) => {
|
|
26
|
+
if (value) {
|
|
27
|
+
className += `--${key}`;
|
|
28
|
+
if (typeof value === 'string' && value !== key) {
|
|
29
|
+
className += `-${value}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return className;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generate consistent CSS variable names
|
|
40
|
+
*/
|
|
41
|
+
export function generateCSSVariableName(property: string, options: NamingOptions = {}): string {
|
|
42
|
+
const { prefix = 'atomix', component, variant, state } = options;
|
|
43
|
+
|
|
44
|
+
const parts = [prefix];
|
|
45
|
+
|
|
46
|
+
if (component) {
|
|
47
|
+
parts.push(component);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (variant) {
|
|
51
|
+
parts.push(variant);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (state) {
|
|
55
|
+
parts.push(state);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
parts.push(property);
|
|
59
|
+
|
|
60
|
+
return `--${parts.join('-')}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Normalize theme tokens to consistent naming convention
|
|
65
|
+
*/
|
|
66
|
+
export function normalizeThemeTokens(tokens: Record<string, any>): Record<string, any> {
|
|
67
|
+
const normalized: Record<string, any> = {};
|
|
68
|
+
|
|
69
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
70
|
+
if (typeof value === 'object' && value !== null) {
|
|
71
|
+
// Recursively normalize nested objects
|
|
72
|
+
normalized[key] = normalizeThemeTokens(value);
|
|
73
|
+
} else {
|
|
74
|
+
// Apply consistent naming transformation
|
|
75
|
+
normalized[key] = value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return normalized;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Convert camelCase to kebab-case for CSS custom properties
|
|
84
|
+
*/
|
|
85
|
+
export function camelToKebab(str: string): string {
|
|
86
|
+
return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Convert theme property to CSS variable name
|
|
91
|
+
*/
|
|
92
|
+
export function themePropertyToCSSVar(propertyPath: string, prefix: string = 'atomix'): string {
|
|
93
|
+
// Convert nested property paths to kebab-case
|
|
94
|
+
const path = propertyPath
|
|
95
|
+
.split('.')
|
|
96
|
+
.map(part => camelToKebab(part))
|
|
97
|
+
.join('-');
|
|
98
|
+
|
|
99
|
+
return `--${prefix}-${path}`;
|
|
100
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for working with themes and DesignTokens
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Theme } from '../types';
|
|
8
|
+
import type { DesignTokens } from '../tokens/tokens';
|
|
9
|
+
import { createDesignTokensFromTheme } from '../adapters/themeAdapter';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get DesignTokens from current theme
|
|
13
|
+
*
|
|
14
|
+
* Converts a Theme object to DesignTokens. Useful when you need to
|
|
15
|
+
* work with DesignTokens but have a Theme object.
|
|
16
|
+
*
|
|
17
|
+
* @param theme - Theme object to convert
|
|
18
|
+
* @returns DesignTokens object
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // If you have a Theme object, convert it to DesignTokens
|
|
23
|
+
* const tokens = getDesignTokensFromTheme(theme);
|
|
24
|
+
* // Now you can use tokens with unified theme system
|
|
25
|
+
* const css = createTheme(tokens);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function getDesignTokensFromTheme(theme: Theme | null): DesignTokens | null {
|
|
29
|
+
if (!theme) return null;
|
|
30
|
+
return createDesignTokensFromTheme(theme);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if a value is DesignTokens
|
|
35
|
+
*
|
|
36
|
+
* Type guard to check if an object is DesignTokens format.
|
|
37
|
+
*
|
|
38
|
+
* @param value - Value to check
|
|
39
|
+
* @returns True if value is DesignTokens
|
|
40
|
+
*/
|
|
41
|
+
export function isDesignTokens(value: unknown): value is DesignTokens {
|
|
42
|
+
if (!value || typeof value !== 'object') return false;
|
|
43
|
+
|
|
44
|
+
// DesignTokens is a flat object with string keys, no nested structures
|
|
45
|
+
const obj = value as Record<string, unknown>;
|
|
46
|
+
|
|
47
|
+
// Check for absence of Theme-specific properties
|
|
48
|
+
if ('palette' in obj || 'typography' in obj || '__isJSTheme' in obj) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check if it has DesignTokens-like structure (flat string keys)
|
|
53
|
+
const keys = Object.keys(obj);
|
|
54
|
+
if (keys.length === 0) return false;
|
|
55
|
+
|
|
56
|
+
// Check if keys look like DesignTokens (kebab-case, no nesting)
|
|
57
|
+
const hasDesignTokenKeys = keys.some(key =>
|
|
58
|
+
/^[a-z]+(-[a-z0-9]+)*$/.test(key) &&
|
|
59
|
+
typeof obj[key] === 'string'
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return hasDesignTokenKeys;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check if a value is a Theme object
|
|
67
|
+
*
|
|
68
|
+
* Type guard to check if an object is a Theme.
|
|
69
|
+
*
|
|
70
|
+
* @param value - Value to check
|
|
71
|
+
* @returns True if value is Theme
|
|
72
|
+
*/
|
|
73
|
+
export function isThemeObject(value: unknown): value is Theme {
|
|
74
|
+
if (!value || typeof value !== 'object') return false;
|
|
75
|
+
const obj = value as Record<string, unknown>;
|
|
76
|
+
return '__isJSTheme' in obj || ('palette' in obj && 'typography' in obj);
|
|
77
|
+
}
|
|
78
|
+
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* spacing helpers, and theme value accessors.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { Theme, SpacingFunction, SpacingOptions } from '
|
|
8
|
+
import type { Theme, SpacingFunction, SpacingOptions } from '../types';
|
|
9
9
|
|
|
10
10
|
// ============================================================================
|
|
11
11
|
// Color Manipulation Utilities
|
|
@@ -207,13 +207,13 @@ export function spacing(theme: Theme, ...values: number[]): string {
|
|
|
207
207
|
* @param fallback - Fallback value if path not found
|
|
208
208
|
* @returns Theme value or fallback
|
|
209
209
|
*/
|
|
210
|
-
export function getThemeValue<T =
|
|
210
|
+
export function getThemeValue<T = unknown>(theme: Theme, path: string, fallback?: T): T {
|
|
211
211
|
const keys = path.split('.');
|
|
212
|
-
let value:
|
|
212
|
+
let value: unknown = theme;
|
|
213
213
|
|
|
214
214
|
for (const key of keys) {
|
|
215
215
|
if (value && typeof value === 'object' && key in value) {
|
|
216
|
-
value = value[key];
|
|
216
|
+
value = (value as Record<string, unknown>)[key];
|
|
217
217
|
} else {
|
|
218
218
|
return fallback as T;
|
|
219
219
|
}
|
|
@@ -225,8 +225,8 @@ export function getThemeValue<T = any>(theme: Theme, path: string, fallback?: T)
|
|
|
225
225
|
/**
|
|
226
226
|
* Check if a theme is a JS theme (created with createTheme)
|
|
227
227
|
*/
|
|
228
|
-
export function isJSTheme(theme:
|
|
229
|
-
return
|
|
228
|
+
export function isJSTheme(theme: unknown): theme is Theme {
|
|
229
|
+
return typeof theme === 'object' && theme !== null && '__isJSTheme' in theme && theme.__isJSTheme === true;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
// ============================================================================
|
|
@@ -265,7 +265,7 @@ export function breakpointBetween(
|
|
|
265
265
|
/**
|
|
266
266
|
* Get typography variant styles
|
|
267
267
|
*/
|
|
268
|
-
export function getTypography(theme: Theme, variant: keyof Theme['typography']):
|
|
268
|
+
export function getTypography(theme: Theme, variant: keyof Theme['typography']): Theme['typography'][keyof Theme['typography']] {
|
|
269
269
|
return theme.typography[variant] ?? {};
|
|
270
270
|
}
|
|
271
271
|
|
package/src/lib/theme-tools.ts
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Theme, ThemeMetadata } from './theme/types';
|
|
8
|
-
import {
|
|
9
|
-
import { extendTheme, mergeTheme } from './theme/composeTheme';
|
|
10
|
-
import { generateCSSVariables } from './theme/generateCSSVariables';
|
|
8
|
+
import { createThemeObject } from './theme/core/createThemeObject';
|
|
9
|
+
import { extendTheme, mergeTheme } from './theme/core/composeTheme';
|
|
10
|
+
import { generateCSSVariables } from './theme/generators/generateCSSVariables';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Quick theme creator with sensible defaults
|
|
14
14
|
*/
|
|
15
15
|
export function quickTheme(name: string, primaryColor: string, secondaryColor?: string): Theme {
|
|
16
|
-
return
|
|
16
|
+
return createThemeObject({
|
|
17
17
|
name,
|
|
18
18
|
palette: {
|
|
19
19
|
primary: { main: primaryColor },
|
|
@@ -119,7 +119,6 @@ export function importTheme(json: string): Theme {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
export { RTLManager } from './theme/i18n/rtl';
|
|
122
|
+
// Note: createTheme, extendTheme, mergeTheme, and generateCSSVariables
|
|
123
|
+
// are already exported from './theme' module. Import them directly from there.
|
|
124
|
+
// This file only exports theme-tools specific utilities.
|