@shohojdhara/atomix 0.5.2 → 0.5.4
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/atomix.config.ts +33 -33
- package/dist/config.d.ts +187 -112
- package/dist/config.js +7 -49
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1958 -900
- package/dist/index.esm.js +2275 -383
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2327 -417
- 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 +1390 -276
- package/dist/theme.js +2129 -621
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cli/internal/config-loader.js +30 -20
- package/src/lib/config/index.ts +38 -362
- package/src/lib/config/loader.ts +419 -0
- package/src/lib/config/public-api.ts +43 -0
- package/src/lib/config/types.ts +389 -0
- package/src/lib/config/validator.ts +305 -0
- package/src/lib/theme/adapters/index.ts +1 -1
- package/src/lib/theme/adapters/themeAdapter.ts +358 -229
- package/src/lib/theme/components/ThemeToggle.tsx +276 -0
- package/src/lib/theme/config/configLoader.ts +351 -0
- package/src/lib/theme/config/loader.ts +221 -0
- package/src/lib/theme/core/createTheme.ts +126 -50
- package/src/lib/theme/core/createThemeObject.ts +7 -4
- package/src/lib/theme/hooks/useThemeSwitcher.ts +164 -0
- package/src/lib/theme/index.ts +322 -38
- package/src/lib/theme/runtime/ThemeProvider.tsx +44 -10
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +44 -393
- package/src/lib/theme/runtime/useTheme.ts +1 -0
- package/src/lib/theme/tokens/tokens.ts +101 -1
- package/src/lib/theme/types.ts +91 -0
- package/src/lib/theme/utils/performanceMonitor.ts +315 -0
- package/src/lib/theme/utils/responsive.ts +280 -0
- package/src/lib/theme/utils/themeUtils.ts +531 -117
- package/src/styles/05-objects/_objects.masonry-grid.scss +3 -3
|
@@ -1,264 +1,422 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme Adapter
|
|
3
|
-
*
|
|
4
|
-
* Converts between Theme objects and DesignTokens
|
|
3
|
+
*
|
|
4
|
+
* Converts between Theme objects and DesignTokens
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Theme } from '../types';
|
|
8
|
-
import type {
|
|
9
|
-
import { createTokens } from '../tokens/tokens';
|
|
10
|
-
import { hexToRgb } from '../utils/themeUtils';
|
|
8
|
+
import type { AtomixConfig } from '../../config';
|
|
9
|
+
import { type DesignTokens, defaultTokens, createTokens } from '../tokens/tokens';
|
|
11
10
|
|
|
12
11
|
/**
|
|
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
|
-
* ```
|
|
12
|
+
* Convert a Theme object to DesignTokens
|
|
26
13
|
*/
|
|
27
|
-
export function themeToDesignTokens(theme: Theme):
|
|
14
|
+
export function themeToDesignTokens(theme: Theme): DesignTokens {
|
|
28
15
|
const tokens: Partial<DesignTokens> = {};
|
|
29
16
|
|
|
30
|
-
// Convert
|
|
17
|
+
// Convert colors
|
|
31
18
|
if (theme.palette) {
|
|
32
|
-
// Primary
|
|
19
|
+
// Primary color
|
|
33
20
|
if (theme.palette.primary) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
}
|
|
21
|
+
const primaryMain = theme.palette.primary.main;
|
|
22
|
+
tokens.primary = primaryMain;
|
|
23
|
+
const rgb = hexToRgb(primaryMain);
|
|
24
|
+
if (rgb) tokens['primary-rgb'] = rgb;
|
|
48
25
|
}
|
|
49
26
|
|
|
50
|
-
// Secondary
|
|
27
|
+
// Secondary color
|
|
51
28
|
if (theme.palette.secondary) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
}
|
|
29
|
+
const secondaryMain = theme.palette.secondary.main;
|
|
30
|
+
tokens.secondary = secondaryMain;
|
|
31
|
+
const rgb = hexToRgb(secondaryMain);
|
|
32
|
+
if (rgb) tokens['secondary-rgb'] = rgb;
|
|
79
33
|
}
|
|
80
34
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
tokens[
|
|
87
|
-
|
|
88
|
-
|
|
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}`;
|
|
35
|
+
// Other colors
|
|
36
|
+
const colorKeys = ['error', 'warning', 'info', 'success'] as const;
|
|
37
|
+
for (const key of colorKeys) {
|
|
38
|
+
if (theme.palette[key]) {
|
|
39
|
+
const colorMain = theme.palette[key]!.main;
|
|
40
|
+
tokens[key] = colorMain;
|
|
41
|
+
const rgb = hexToRgb(colorMain);
|
|
42
|
+
if (rgb) tokens[`${key}-rgb` as keyof DesignTokens] = rgb as any;
|
|
126
43
|
}
|
|
127
44
|
}
|
|
128
45
|
|
|
129
46
|
// Background colors
|
|
130
47
|
if (theme.palette.background) {
|
|
131
48
|
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
49
|
}
|
|
136
50
|
|
|
137
51
|
// Text colors
|
|
138
52
|
if (theme.palette.text) {
|
|
139
53
|
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
54
|
}
|
|
145
55
|
}
|
|
146
56
|
|
|
147
57
|
// Convert typography
|
|
148
58
|
if (theme.typography) {
|
|
149
59
|
tokens['body-font-family'] = theme.typography.fontFamily;
|
|
150
|
-
tokens['font-sans-serif'] = theme.typography.fontFamily;
|
|
151
60
|
tokens['body-font-size'] = `${theme.typography.fontSize}px`;
|
|
152
|
-
tokens['
|
|
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
|
-
}
|
|
61
|
+
tokens['font-weight-normal'] = `${theme.typography.fontWeightRegular}`;
|
|
62
|
+
tokens['font-weight-bold'] = `${theme.typography.fontWeightBold}`;
|
|
165
63
|
}
|
|
166
64
|
|
|
167
|
-
// Convert spacing
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const spacing = theme.spacing as Record<string, string | number>;
|
|
174
|
-
Object.entries(spacing).forEach(([key, value]) => {
|
|
175
|
-
tokens[`spacing-${key}` as keyof DesignTokens] = String(value);
|
|
176
|
-
});
|
|
65
|
+
// Convert spacing
|
|
66
|
+
if (typeof theme.spacing === 'function') {
|
|
67
|
+
// If spacing is a function, call it with some values to get results
|
|
68
|
+
tokens['spacing-1'] = theme.spacing(1);
|
|
69
|
+
tokens['spacing-2'] = theme.spacing(2);
|
|
70
|
+
tokens['spacing-4'] = theme.spacing(4);
|
|
177
71
|
}
|
|
178
72
|
|
|
179
|
-
// Convert
|
|
180
|
-
if (theme.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
? 'border-radius'
|
|
187
|
-
: key === 'lg'
|
|
188
|
-
? 'border-radius-lg'
|
|
189
|
-
: key === 'xl'
|
|
190
|
-
? 'border-radius-xl'
|
|
191
|
-
: key === 'xxl'
|
|
192
|
-
? 'border-radius-xxl'
|
|
193
|
-
: `border-radius-${key}`;
|
|
194
|
-
tokens[tokenKey as keyof DesignTokens] = String(value);
|
|
195
|
-
});
|
|
73
|
+
// Convert breakpoints
|
|
74
|
+
if (theme.breakpoints?.values) {
|
|
75
|
+
tokens['breakpoint-xs'] = `${theme.breakpoints.values.xs}px`;
|
|
76
|
+
tokens['breakpoint-sm'] = `${theme.breakpoints.values.sm}px`;
|
|
77
|
+
tokens['breakpoint-md'] = `${theme.breakpoints.values.md}px`;
|
|
78
|
+
tokens['breakpoint-lg'] = `${theme.breakpoints.values.lg}px`;
|
|
79
|
+
tokens['breakpoint-xl'] = `${theme.breakpoints.values.xl}px`;
|
|
196
80
|
}
|
|
197
81
|
|
|
198
82
|
// Convert shadows
|
|
199
83
|
if (theme.shadows) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
: key === 'lg'
|
|
209
|
-
? 'box-shadow-lg'
|
|
210
|
-
: key === 'xl'
|
|
211
|
-
? 'box-shadow-xl'
|
|
212
|
-
: `box-shadow-${key}`;
|
|
213
|
-
tokens[tokenKey as keyof DesignTokens] = String(value);
|
|
214
|
-
});
|
|
84
|
+
tokens['box-shadow'] = theme.shadows[2]; // Use a moderate shadow
|
|
85
|
+
tokens['box-shadow-sm'] = theme.shadows[1];
|
|
86
|
+
tokens['box-shadow-lg'] = theme.shadows[3];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Convert transitions
|
|
90
|
+
if (theme.transitions) {
|
|
91
|
+
tokens['transition-duration-base'] = `${theme.transitions.duration.standard}ms`;
|
|
215
92
|
}
|
|
216
93
|
|
|
217
94
|
// Convert z-index
|
|
218
95
|
if (theme.zIndex) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
96
|
+
tokens['z-modal'] = `${theme.zIndex.modal}`;
|
|
97
|
+
tokens['z-popover'] = `${theme.zIndex.popover}`;
|
|
98
|
+
tokens['z-tooltip'] = `${theme.zIndex.tooltip}`;
|
|
222
99
|
}
|
|
223
100
|
|
|
224
|
-
// Convert
|
|
225
|
-
if (theme.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
101
|
+
// Convert border radius
|
|
102
|
+
if (theme.borderRadius) {
|
|
103
|
+
const baseRadius = theme.borderRadius.base;
|
|
104
|
+
tokens['border-radius'] = typeof baseRadius === 'number'
|
|
105
|
+
? `${baseRadius}px`
|
|
106
|
+
: baseRadius;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add advanced feature tokens if available in theme
|
|
110
|
+
if (theme.custom) {
|
|
111
|
+
// Interactive Effects (Phase 2)
|
|
112
|
+
if (theme.custom.interactiveEffects) {
|
|
113
|
+
const ie = theme.custom.interactiveEffects;
|
|
114
|
+
|
|
115
|
+
// Vortex effects
|
|
116
|
+
if (ie.vortex) {
|
|
117
|
+
tokens['interactive-vortex-enabled'] = String(ie.vortex.enabled ?? false);
|
|
118
|
+
tokens['interactive-vortex-strength'] = String(ie.vortex.strength ?? 0.5);
|
|
119
|
+
tokens['interactive-vortex-radius'] = String(ie.vortex.radius ?? 100);
|
|
120
|
+
tokens['interactive-vortex-decay'] = String(ie.vortex.decay ?? 0.8);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Chromatic aberration
|
|
124
|
+
if (ie.chromaticAberration) {
|
|
125
|
+
tokens['interactive-chromatic-enabled'] = String(ie.chromaticAberration.enabled ?? false);
|
|
126
|
+
tokens['interactive-chromatic-mode'] = ie.chromaticAberration.mode ?? 'lateral';
|
|
127
|
+
tokens['interactive-chromatic-red-shift'] = String(ie.chromaticAberration.redShift ?? 0.02);
|
|
128
|
+
tokens['interactive-chromatic-green-shift'] = String(ie.chromaticAberration.greenShift ?? 0);
|
|
129
|
+
tokens['interactive-chromatic-blue-shift'] = String(ie.chromaticAberration.blueShift ?? -0.02);
|
|
130
|
+
tokens['interactive-chromatic-edge-only'] = String(ie.chromaticAberration.edgeOnly ?? false);
|
|
131
|
+
tokens['interactive-chromatic-edge-threshold'] = String(ie.chromaticAberration.edgeThreshold ?? 0.5);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Mouse interaction
|
|
135
|
+
if (ie.mouseInteraction) {
|
|
136
|
+
tokens['interactive-mouse-sensitivity'] = String(ie.mouseInteraction.sensitivity ?? 1.0);
|
|
137
|
+
tokens['interactive-mouse-trail-effect'] = String(ie.mouseInteraction.trailEffect ?? false);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Animation speed
|
|
141
|
+
if (ie.animationSpeed) {
|
|
142
|
+
tokens['interactive-animation-speed-base'] = String(ie.animationSpeed.base ?? 1.0);
|
|
143
|
+
tokens['interactive-animation-speed-multiplier'] = String(ie.animationSpeed.timeMultiplier ?? 1.0);
|
|
144
|
+
}
|
|
230
145
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
146
|
+
|
|
147
|
+
// Optimization (Phase 3)
|
|
148
|
+
if (theme.custom.optimization) {
|
|
149
|
+
const opt = theme.custom.optimization;
|
|
150
|
+
|
|
151
|
+
// Responsive breakpoints
|
|
152
|
+
if (opt.responsive) {
|
|
153
|
+
if (opt.responsive.breakpoints) {
|
|
154
|
+
tokens['optimization-breakpoint-mobile'] = opt.responsive.breakpoints.mobile ?? '0px';
|
|
155
|
+
tokens['optimization-breakpoint-tablet'] = opt.responsive.breakpoints.tablet ?? '768px';
|
|
156
|
+
tokens['optimization-breakpoint-desktop'] = opt.responsive.breakpoints.desktop ?? '1024px';
|
|
157
|
+
tokens['optimization-breakpoint-wide'] = opt.responsive.breakpoints.wide ?? '1440px';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (opt.responsive.deviceScaling) {
|
|
161
|
+
tokens['optimization-device-scaling-mobile'] = String(opt.responsive.deviceScaling.mobile ?? 0.5);
|
|
162
|
+
tokens['optimization-device-scaling-tablet'] = String(opt.responsive.deviceScaling.tablet ?? 0.75);
|
|
163
|
+
tokens['optimization-device-scaling-desktop'] = String(opt.responsive.deviceScaling.desktop ?? 1.0);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Performance settings
|
|
168
|
+
if (opt.performance) {
|
|
169
|
+
tokens['optimization-performance-fps-target'] = String(opt.performance.fpsTarget ?? 60);
|
|
170
|
+
tokens['optimization-auto-scaling-enabled'] = String(opt.performance.autoScaling ?? false);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Auto-scaling settings
|
|
174
|
+
if (opt.autoScaling) {
|
|
175
|
+
tokens['optimization-auto-scaling-enabled'] = String(opt.autoScaling.enabled ?? false);
|
|
176
|
+
tokens['optimization-auto-scaling-low-end'] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? 0.5);
|
|
177
|
+
tokens['optimization-auto-scaling-mid-range'] = String(opt.autoScaling.qualityThresholds?.midRange ?? 0.75);
|
|
178
|
+
tokens['optimization-auto-scaling-high-end'] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1.0);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Visual Polish (Phase 4)
|
|
183
|
+
if (theme.custom.visualPolish) {
|
|
184
|
+
const vp = theme.custom.visualPolish;
|
|
185
|
+
|
|
186
|
+
if (vp.borders) {
|
|
187
|
+
tokens['visual-polish-border-iridescent-glow'] = String(vp.borders.iridescentGlow ?? false);
|
|
188
|
+
tokens['visual-polish-border-shimmer-effect'] = String(vp.borders.shimmerEffect ?? false);
|
|
189
|
+
tokens['visual-polish-border-beveled-edges'] = String(vp.borders.beveledEdges ?? false);
|
|
190
|
+
tokens['visual-polish-border-pulsing-glow'] = String(vp.borders.pulsingGlow ?? false);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (vp.contentAwareBlur) {
|
|
194
|
+
tokens['visual-polish-content-aware-blur-enabled'] = String(vp.contentAwareBlur.enabled ?? false);
|
|
195
|
+
tokens['visual-polish-content-aware-depth-detection'] = String(vp.contentAwareBlur.depthDetection ?? false);
|
|
196
|
+
tokens['visual-polish-content-aware-edge-preservation'] = String(vp.contentAwareBlur.edgePreservation ?? false);
|
|
197
|
+
tokens['visual-polish-content-aware-variable-radius'] = String(vp.contentAwareBlur.variableRadius ?? false);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (vp.holographicEffects) {
|
|
201
|
+
tokens['visual-polish-holographic-enabled'] = String(vp.holographicEffects.enabled ?? false);
|
|
202
|
+
tokens['visual-polish-holographic-rainbow-diffraction'] = String(vp.holographicEffects.rainbowDiffraction ?? false);
|
|
203
|
+
tokens['visual-polish-holographic-scanline-animation'] = String(vp.holographicEffects.scanlineAnimation ?? false);
|
|
204
|
+
tokens['visual-polish-holographic-grid-overlay'] = String(vp.holographicEffects.gridOverlay ?? false);
|
|
205
|
+
tokens['visual-polish-holographic-data-stream'] = String(vp.holographicEffects.dataStream ?? false);
|
|
206
|
+
tokens['visual-polish-holographic-pulse-rings'] = String(vp.holographicEffects.pulseRings ?? false);
|
|
207
|
+
}
|
|
235
208
|
}
|
|
236
209
|
}
|
|
237
210
|
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
211
|
+
// Create full tokens object with defaults
|
|
212
|
+
return createTokens(tokens);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Convert DesignTokens to a Theme object
|
|
217
|
+
*/
|
|
218
|
+
export function designTokensToTheme(tokens: DesignTokens): Theme {
|
|
219
|
+
// Implementation would go here if needed
|
|
220
|
+
// For now, we're primarily concerned with the direction from theme to tokens
|
|
221
|
+
throw new Error('designTokensToTheme not yet implemented');
|
|
222
|
+
}
|
|
244
223
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Converts an AtomixConfig to DesignTokens
|
|
226
|
+
*
|
|
227
|
+
* This function maps the configuration from the user-facing format
|
|
228
|
+
* to the internal DesignTokens format used by the theme system.
|
|
229
|
+
*
|
|
230
|
+
* @param config - The configuration object to convert
|
|
231
|
+
* @returns DesignTokens object ready for theme generation
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* import { configToTokens } from '@shohojdhara/atomix/theme';
|
|
236
|
+
*
|
|
237
|
+
* const config = {
|
|
238
|
+
* prefix: 'myapp',
|
|
239
|
+
* theme: { extend: { colors: { primary: { main: '#7AFFD7' } } } }
|
|
240
|
+
* };
|
|
241
|
+
* const tokens = configToTokens(config);
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
export function configToTokens(config: AtomixConfig): DesignTokens {
|
|
245
|
+
const prefix = config.prefix || 'atomix';
|
|
246
|
+
const theme = config.theme || {};
|
|
247
|
+
|
|
248
|
+
// Start with default tokens
|
|
249
|
+
let tokens: DesignTokens = { ...defaultTokens };
|
|
250
|
+
|
|
251
|
+
// Apply theme extensions
|
|
252
|
+
if (theme.extend) {
|
|
253
|
+
// Apply extensions to tokens
|
|
254
|
+
Object.entries(theme.extend).forEach(([category, values]) => {
|
|
255
|
+
if (typeof values === 'object' && values !== null) {
|
|
256
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
257
|
+
// Map theme categories to token names
|
|
258
|
+
const tokenName = `${category}-${key}`;
|
|
259
|
+
|
|
260
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
261
|
+
tokens[tokenName as keyof DesignTokens] = String(value);
|
|
262
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
263
|
+
// Handle nested objects like color scales
|
|
264
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
|
265
|
+
if (typeof nestedValue === 'string' || typeof nestedValue === 'number') {
|
|
266
|
+
tokens[`${tokenName}-${nestedKey}` as keyof DesignTokens] = String(nestedValue);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
251
272
|
});
|
|
252
273
|
}
|
|
274
|
+
|
|
275
|
+
// Apply theme tokens if provided (completely replacing defaults)
|
|
276
|
+
if (theme.tokens) {
|
|
277
|
+
tokens = { ...tokens, ...theme.tokens } as DesignTokens;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Apply advanced features if available in config
|
|
281
|
+
if (config) {
|
|
282
|
+
// Interactive Effects (Phase 2)
|
|
283
|
+
if (config.interactiveEffects) {
|
|
284
|
+
const ie = config.interactiveEffects;
|
|
285
|
+
|
|
286
|
+
// Vortex effects
|
|
287
|
+
if (ie.vortex) {
|
|
288
|
+
tokens['interactive-vortex-enabled'] = String(ie.vortex.enabled ?? false);
|
|
289
|
+
tokens['interactive-vortex-strength'] = String(ie.vortex.strength ?? 0.5);
|
|
290
|
+
tokens['interactive-vortex-radius'] = String(ie.vortex.radius ?? 100);
|
|
291
|
+
tokens['interactive-vortex-decay'] = String(ie.vortex.decay ?? 0.8);
|
|
292
|
+
tokens['interactive-vortex-curl-noise'] = String(ie.vortex.curlNoise ?? false);
|
|
293
|
+
tokens['interactive-vortex-velocity-tracking'] = String(ie.vortex.velocityTracking ?? false);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Chromatic aberration
|
|
297
|
+
if (ie.chromaticAberration) {
|
|
298
|
+
tokens['interactive-chromatic-enabled'] = String(ie.chromaticAberration.enabled ?? false);
|
|
299
|
+
tokens['interactive-chromatic-mode'] = ie.chromaticAberration.mode ?? 'lateral';
|
|
300
|
+
tokens['interactive-chromatic-red-shift'] = String(ie.chromaticAberration.redShift ?? 0.02);
|
|
301
|
+
tokens['interactive-chromatic-green-shift'] = String(ie.chromaticAberration.greenShift ?? 0);
|
|
302
|
+
tokens['interactive-chromatic-blue-shift'] = String(ie.chromaticAberration.blueShift ?? -0.02);
|
|
303
|
+
tokens['interactive-chromatic-edge-only'] = String(ie.chromaticAberration.edgeOnly ?? false);
|
|
304
|
+
tokens['interactive-chromatic-edge-threshold'] = String(ie.chromaticAberration.edgeThreshold ?? 0.5);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Mouse interaction
|
|
308
|
+
if (ie.mouseInteraction) {
|
|
309
|
+
tokens['interactive-mouse-sensitivity'] = String(ie.mouseInteraction.sensitivity ?? 1.0);
|
|
310
|
+
tokens['interactive-mouse-trail-effect'] = String(ie.mouseInteraction.trailEffect ?? false);
|
|
311
|
+
tokens['interactive-mouse-pressure-sensitivity'] = String(ie.mouseInteraction.pressureSensitivity ?? false);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Animation speed
|
|
315
|
+
if (ie.animationSpeed) {
|
|
316
|
+
tokens['interactive-animation-speed-base'] = String(ie.animationSpeed.base ?? 1.0);
|
|
317
|
+
tokens['interactive-animation-speed-multiplier'] = String(ie.animationSpeed.timeMultiplier ?? 1.0);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Optimization (Phase 3)
|
|
322
|
+
if (config.optimization) {
|
|
323
|
+
const opt = config.optimization;
|
|
324
|
+
|
|
325
|
+
// Responsive breakpoints
|
|
326
|
+
if (opt.responsive) {
|
|
327
|
+
if (opt.responsive.breakpoints) {
|
|
328
|
+
tokens['optimization-breakpoint-mobile'] = opt.responsive.breakpoints.mobile ?? '0px';
|
|
329
|
+
tokens['optimization-breakpoint-tablet'] = opt.responsive.breakpoints.tablet ?? '768px';
|
|
330
|
+
tokens['optimization-breakpoint-desktop'] = opt.responsive.breakpoints.desktop ?? '1024px';
|
|
331
|
+
tokens['optimization-breakpoint-wide'] = opt.responsive.breakpoints.wide ?? '1440px';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (opt.responsive.deviceScaling) {
|
|
335
|
+
tokens['optimization-device-scaling-mobile'] = String(opt.responsive.deviceScaling.mobile ?? 0.5);
|
|
336
|
+
tokens['optimization-device-scaling-tablet'] = String(opt.responsive.deviceScaling.tablet ?? 0.75);
|
|
337
|
+
tokens['optimization-device-scaling-desktop'] = String(opt.responsive.deviceScaling.desktop ?? 1.0);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Performance settings
|
|
342
|
+
if (opt.performance) {
|
|
343
|
+
tokens['optimization-performance-fps-target'] = String(opt.performance.fpsTarget ?? 60);
|
|
344
|
+
tokens['optimization-auto-scaling-enabled'] = String(opt.performance.autoScaling ?? false);
|
|
345
|
+
tokens['optimization-monitor-dashboard-enabled'] = String(opt.performance.monitorDashboard ?? false);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Auto-scaling settings
|
|
349
|
+
if (opt.autoScaling) {
|
|
350
|
+
tokens['optimization-auto-scaling-enabled'] = String(opt.autoScaling.enabled ?? false);
|
|
351
|
+
tokens['optimization-auto-scaling-low-end'] = String(opt.autoScaling.qualityThresholds?.lowEnd ?? 0.5);
|
|
352
|
+
tokens['optimization-auto-scaling-mid-range'] = String(opt.autoScaling.qualityThresholds?.midRange ?? 0.75);
|
|
353
|
+
tokens['optimization-auto-scaling-high-end'] = String(opt.autoScaling.qualityThresholds?.highEnd ?? 1.0);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Visual Polish (Phase 4)
|
|
358
|
+
if (config.visualPolish) {
|
|
359
|
+
const vp = config.visualPolish;
|
|
360
|
+
|
|
361
|
+
if (vp.borders) {
|
|
362
|
+
tokens['visual-polish-border-iridescent-glow'] = String(vp.borders.iridescentGlow ?? false);
|
|
363
|
+
tokens['visual-polish-border-shimmer-effect'] = String(vp.borders.shimmerEffect ?? false);
|
|
364
|
+
tokens['visual-polish-border-beveled-edges'] = String(vp.borders.beveledEdges ?? false);
|
|
365
|
+
tokens['visual-polish-border-pulsing-glow'] = String(vp.borders.pulsingGlow ?? false);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (vp.contentAwareBlur) {
|
|
369
|
+
tokens['visual-polish-content-aware-blur-enabled'] = String(vp.contentAwareBlur.enabled ?? false);
|
|
370
|
+
tokens['visual-polish-content-aware-depth-detection'] = String(vp.contentAwareBlur.depthDetection ?? false);
|
|
371
|
+
tokens['visual-polish-content-aware-edge-preservation'] = String(vp.contentAwareBlur.edgePreservation ?? false);
|
|
372
|
+
tokens['visual-polish-content-aware-variable-radius'] = String(vp.contentAwareBlur.variableRadius ?? false);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (vp.holographicEffects) {
|
|
376
|
+
tokens['visual-polish-holographic-enabled'] = String(vp.holographicEffects.enabled ?? false);
|
|
377
|
+
tokens['visual-polish-holographic-rainbow-diffraction'] = String(vp.holographicEffects.rainbowDiffraction ?? false);
|
|
378
|
+
tokens['visual-polish-holographic-scanline-animation'] = String(vp.holographicEffects.scanlineAnimation ?? false);
|
|
379
|
+
tokens['visual-polish-holographic-grid-overlay'] = String(vp.holographicEffects.gridOverlay ?? false);
|
|
380
|
+
tokens['visual-polish-holographic-data-stream'] = String(vp.holographicEffects.dataStream ?? false);
|
|
381
|
+
tokens['visual-polish-holographic-pulse-rings'] = String(vp.holographicEffects.pulseRings ?? false);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Apply prefix to all tokens
|
|
387
|
+
const prefixedTokens: DesignTokens = {} as DesignTokens;
|
|
388
|
+
Object.entries(tokens).forEach(([key, value]) => {
|
|
389
|
+
// If the token key already starts with the prefix, use as-is
|
|
390
|
+
// Otherwise, add the prefix
|
|
391
|
+
const prefixedKey = key.startsWith(prefix) ? key : `${prefix}-${key}`;
|
|
392
|
+
prefixedTokens[prefixedKey as keyof DesignTokens] = value;
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return prefixedTokens;
|
|
396
|
+
}
|
|
253
397
|
|
|
254
|
-
|
|
398
|
+
/**
|
|
399
|
+
* Convert hex color to RGB
|
|
400
|
+
*/
|
|
401
|
+
function hexToRgb(hex: string): string {
|
|
402
|
+
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
|
403
|
+
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
404
|
+
hex = hex.replace(shorthandRegex, (m, r, g, b) => {
|
|
405
|
+
return r + r + g + g + b + b;
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
409
|
+
if (!result || !result[1] || !result[2] || !result[3]) {
|
|
410
|
+
return '0, 0, 0';
|
|
411
|
+
}
|
|
412
|
+
return `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`;
|
|
255
413
|
}
|
|
256
414
|
|
|
257
415
|
/**
|
|
258
|
-
*
|
|
416
|
+
* Converts DesignTokens to CSS variables
|
|
259
417
|
*
|
|
260
|
-
* @param tokens -
|
|
261
|
-
* @returns CSS
|
|
418
|
+
* @param tokens - The tokens to convert
|
|
419
|
+
* @returns A record of CSS variable names and values
|
|
262
420
|
*/
|
|
263
421
|
export function designTokensToCSSVars(tokens: Partial<DesignTokens>): Record<string, string> {
|
|
264
422
|
const cssVars: Record<string, string> = {};
|
|
@@ -271,32 +429,3 @@ export function designTokensToCSSVars(tokens: Partial<DesignTokens>): Record<str
|
|
|
271
429
|
|
|
272
430
|
return cssVars;
|
|
273
431
|
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Create DesignTokens from Theme with defaults
|
|
277
|
-
*
|
|
278
|
-
* Converts a Theme to DesignTokens and merges with default tokens.
|
|
279
|
-
*
|
|
280
|
-
* @param theme - Theme object to convert
|
|
281
|
-
* @returns Complete DesignTokens object
|
|
282
|
-
*/
|
|
283
|
-
export function createDesignTokensFromTheme(theme: Theme): DesignTokens {
|
|
284
|
-
const partialTokens = themeToDesignTokens(theme);
|
|
285
|
-
return createTokens(partialTokens);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Create a minimal Theme object from DesignTokens
|
|
290
|
-
*
|
|
291
|
-
* @param tokens - DesignTokens to convert
|
|
292
|
-
* @returns Minimal Theme object with cssVars populated
|
|
293
|
-
*/
|
|
294
|
-
export function designTokensToTheme(tokens: Partial<DesignTokens>): Partial<Theme> {
|
|
295
|
-
const cssVars = designTokensToCSSVars(tokens);
|
|
296
|
-
|
|
297
|
-
return {
|
|
298
|
-
name: 'Design Tokens Theme',
|
|
299
|
-
cssVars,
|
|
300
|
-
__isJSTheme: true,
|
|
301
|
-
} as Partial<Theme>;
|
|
302
|
-
}
|