@shohojdhara/atomix 0.3.2 → 0.3.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.
Files changed (84) hide show
  1. package/README.md +58 -21
  2. package/dist/atomix.css +96 -121
  3. package/dist/atomix.min.css +3 -3
  4. package/dist/index.d.ts +7937 -7765
  5. package/dist/index.esm.js +3677 -4031
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/index.js +3648 -3952
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.min.js +1 -1
  10. package/dist/index.min.js.map +1 -1
  11. package/package.json +44 -16
  12. package/scripts/atomix-cli.js +1764 -0
  13. package/scripts/build-themes.js +208 -0
  14. package/scripts/cli/interactive-init.js +520 -0
  15. package/scripts/cli/migration-tools.js +603 -0
  16. package/scripts/cli/theme-bridge.js +129 -0
  17. package/scripts/cli/token-manager.js +519 -0
  18. package/scripts/sync-theme-config.js +309 -0
  19. package/src/components/Button/Button.tsx +36 -1
  20. package/src/components/List/ListGroup.tsx +1 -2
  21. package/src/components/Popover/Popover.tsx +2 -2
  22. package/src/components/Tooltip/Tooltip.stories.tsx +49 -12
  23. package/src/components/Tooltip/Tooltip.tsx +32 -58
  24. package/src/lib/composables/useTooltip.ts +285 -0
  25. package/src/lib/config/index.ts +275 -0
  26. package/src/lib/config/loader.ts +105 -0
  27. package/src/lib/constants/cssVariables.ts +390 -0
  28. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +151 -0
  29. package/src/lib/hooks/index.ts +19 -0
  30. package/src/lib/hooks/useComponentCustomization.ts +175 -0
  31. package/src/lib/index.ts +14 -1
  32. package/src/lib/patterns/__tests__/slots.test.ts +108 -0
  33. package/src/lib/patterns/index.ts +35 -0
  34. package/src/lib/patterns/slots.tsx +421 -0
  35. package/src/lib/theme/composeTheme.ts +0 -5
  36. package/src/lib/theme/config/index.ts +1 -1
  37. package/src/lib/theme/config/loader.ts +75 -41
  38. package/src/lib/theme/config/types.ts +21 -7
  39. package/src/lib/theme/config/validator.ts +1 -1
  40. package/src/lib/theme/constants.ts +12 -2
  41. package/src/lib/theme/createTheme.ts +2 -135
  42. package/src/lib/theme/createThemeFromConfig.ts +132 -0
  43. package/src/lib/theme/cssVariableMapper.ts +261 -0
  44. package/src/lib/theme/devtools/CLI.ts +161 -76
  45. package/src/lib/theme/devtools/Comparator.tsx +343 -0
  46. package/src/lib/theme/devtools/IMPROVEMENTS.md +429 -0
  47. package/src/lib/theme/devtools/Inspector.tsx +21 -6
  48. package/src/lib/theme/devtools/LiveEditor.tsx +393 -0
  49. package/src/lib/theme/devtools/README.md +433 -0
  50. package/src/lib/theme/devtools/index.ts +12 -11
  51. package/src/lib/theme/generateCSSVariables.ts +79 -38
  52. package/src/lib/theme/index.ts +45 -246
  53. package/src/lib/theme/runtime/ThemeApplicator.ts +252 -0
  54. package/src/lib/theme/runtime/ThemeManager.test.ts +17 -1
  55. package/src/lib/theme/runtime/ThemeManager.ts +7 -7
  56. package/src/lib/theme/themeUtils.ts +27 -5
  57. package/src/lib/theme/types.ts +59 -1
  58. package/src/lib/theme-tools.ts +125 -0
  59. package/src/lib/types/components.ts +260 -72
  60. package/src/lib/types/partProps.ts +426 -0
  61. package/src/lib/utils/__tests__/componentUtils.test.ts +144 -0
  62. package/src/lib/utils/componentUtils.ts +163 -0
  63. package/src/lib/utils/index.ts +17 -57
  64. package/src/styles/01-settings/_settings.colors.scss +10 -10
  65. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  66. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  67. package/src/styles/03-generic/_generated-root.css +5 -0
  68. package/src/styles/06-components/_components.navbar.scss +12 -5
  69. package/src/styles/06-components/_components.tooltip.scss +31 -81
  70. package/src/themes/README.md +442 -0
  71. package/src/themes/themes.config.js +35 -0
  72. package/src/lib/theme/errors.test.ts +0 -207
  73. package/src/lib/theme/generators/CSSGenerator.ts +0 -311
  74. package/src/lib/theme/generators/ConfigGenerator.ts +0 -287
  75. package/src/lib/theme/generators/TypeGenerator.ts +0 -228
  76. package/src/lib/theme/generators/index.ts +0 -21
  77. package/src/lib/theme/monitoring/ThemeAnalytics.ts +0 -409
  78. package/src/lib/theme/monitoring/index.ts +0 -17
  79. package/src/lib/theme/overrides/ComponentOverrides.ts +0 -243
  80. package/src/lib/theme/overrides/index.ts +0 -15
  81. package/src/lib/theme/studio/ThemeStudio.tsx +0 -312
  82. package/src/lib/theme/studio/index.ts +0 -8
  83. package/src/lib/theme/whitelabel/WhiteLabelManager.ts +0 -364
  84. package/src/lib/theme/whitelabel/index.ts +0 -13
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Slot Pattern System
3
+ *
4
+ * Provides render props and slot-based customization for components.
5
+ * Allows complete control over component rendering and structure.
6
+ */
7
+
8
+ import React from 'react';
9
+
10
+ /**
11
+ * Slot configuration with multiple rendering options
12
+ */
13
+ export interface SlotProps<T = any> {
14
+ /** Static children to render */
15
+ children?: React.ReactNode;
16
+ /** Render function with access to slot props */
17
+ render?: (props: T) => React.ReactNode;
18
+ /** Custom component to render */
19
+ component?: React.ComponentType<T>;
20
+ }
21
+
22
+ /**
23
+ * Render a slot with the given props
24
+ *
25
+ * Priority order:
26
+ * 1. render function
27
+ * 2. component
28
+ * 3. children
29
+ * 4. fallback
30
+ *
31
+ * @example
32
+ * renderSlot(
33
+ * { render: (props) => <CustomButton {...props} /> },
34
+ * { onClick: handleClick, children: 'Click me' }
35
+ * )
36
+ */
37
+ export function renderSlot<T>(
38
+ slot: SlotProps<T> | React.ReactNode | undefined,
39
+ props: T,
40
+ fallback?: React.ReactNode
41
+ ): React.ReactNode {
42
+ // No slot provided, use fallback
43
+ if (!slot) return fallback;
44
+
45
+ // Slot is a plain React node
46
+ if (React.isValidElement(slot) || typeof slot === 'string' || typeof slot === 'number') {
47
+ return slot;
48
+ }
49
+
50
+ // Slot is an object with rendering options
51
+ if (typeof slot === 'object' && slot !== null) {
52
+ const slotObj = slot as SlotProps<T>;
53
+
54
+ // Priority 1: render function
55
+ if (slotObj.render && typeof slotObj.render === 'function') {
56
+ return slotObj.render(props);
57
+ }
58
+
59
+ // Priority 2: component
60
+ if (slotObj.component) {
61
+ const Component = slotObj.component;
62
+ return <Component {...props} />;
63
+ }
64
+
65
+ // Priority 3: children
66
+ if (slotObj.children !== undefined) {
67
+ return slotObj.children;
68
+ }
69
+ }
70
+
71
+ // Fallback
72
+ return fallback;
73
+ }
74
+
75
+ /**
76
+ * Check if a value is a slot configuration
77
+ */
78
+ export function isSlot<T>(value: any): value is SlotProps<T> {
79
+ return (
80
+ typeof value === 'object' &&
81
+ value !== null &&
82
+ ('render' in value || 'component' in value || 'children' in value)
83
+ );
84
+ }
85
+
86
+ /**
87
+ * Merge multiple slot configurations
88
+ * Later slots override earlier ones
89
+ */
90
+ export function mergeSlots<T>(
91
+ ...slots: Array<SlotProps<T> | undefined>
92
+ ): SlotProps<T> | undefined {
93
+ const filtered = slots.filter((s): s is SlotProps<T> => s !== undefined);
94
+
95
+ if (filtered.length === 0) return undefined;
96
+ if (filtered.length === 1) return filtered[0];
97
+
98
+ return filtered.reduce((acc, slot) => ({
99
+ ...acc,
100
+ ...slot,
101
+ }));
102
+ }
103
+
104
+ /**
105
+ * Create a slot wrapper component
106
+ *
107
+ * @example
108
+ * const ButtonSlot = createSlotComponent<ButtonSlotProps>('button')
109
+ *
110
+ * <ButtonSlot slot={customSlot} {...props}>
111
+ * Default content
112
+ * </ButtonSlot>
113
+ */
114
+ export function createSlotComponent<T>(
115
+ defaultElement: keyof JSX.IntrinsicElements | React.ComponentType<T> = 'div'
116
+ ) {
117
+ return function SlotComponent({
118
+ slot,
119
+ children,
120
+ ...props
121
+ }: T & {
122
+ slot?: SlotProps<T>;
123
+ children?: React.ReactNode;
124
+ }) {
125
+ const slotProps = props as T;
126
+
127
+ if (slot) {
128
+ return <>{renderSlot(slot, slotProps, children)}</>;
129
+ }
130
+
131
+ if (typeof defaultElement === 'string') {
132
+ const Element = defaultElement;
133
+ return <Element {...(props as any)}>{children}</Element>;
134
+ }
135
+
136
+ const Component = defaultElement;
137
+ return <Component {...slotProps}>{children}</Component>;
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Slot props for Button component
143
+ */
144
+ export interface ButtonRootSlotProps {
145
+ className: string;
146
+ style?: React.CSSProperties;
147
+ children: React.ReactNode;
148
+ disabled?: boolean;
149
+ loading?: boolean;
150
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
151
+ type?: 'button' | 'submit' | 'reset';
152
+ 'aria-label'?: string;
153
+ 'aria-disabled'?: boolean;
154
+ 'aria-busy'?: boolean;
155
+ }
156
+
157
+ export interface ButtonIconSlotProps {
158
+ className: string;
159
+ style?: React.CSSProperties;
160
+ children: React.ReactNode;
161
+ size?: 'sm' | 'md' | 'lg';
162
+ }
163
+
164
+ export interface ButtonLabelSlotProps {
165
+ className: string;
166
+ style?: React.CSSProperties;
167
+ children: React.ReactNode;
168
+ }
169
+
170
+ export interface ButtonSpinnerSlotProps {
171
+ className: string;
172
+ style?: React.CSSProperties;
173
+ size?: 'sm' | 'md' | 'lg';
174
+ variant?: string;
175
+ }
176
+
177
+ /**
178
+ * Slot props for Card component
179
+ */
180
+ export interface CardRootSlotProps {
181
+ className: string;
182
+ style?: React.CSSProperties;
183
+ children: React.ReactNode;
184
+ onClick?: React.MouseEventHandler<HTMLDivElement>;
185
+ role?: string;
186
+ 'aria-label'?: string;
187
+ }
188
+
189
+ export interface CardHeaderSlotProps {
190
+ className: string;
191
+ style?: React.CSSProperties;
192
+ children: React.ReactNode;
193
+ }
194
+
195
+ export interface CardBodySlotProps {
196
+ className: string;
197
+ style?: React.CSSProperties;
198
+ children: React.ReactNode;
199
+ scrollable?: boolean;
200
+ maxHeight?: string | number;
201
+ }
202
+
203
+ export interface CardFooterSlotProps {
204
+ className: string;
205
+ style?: React.CSSProperties;
206
+ children: React.ReactNode;
207
+ align?: 'start' | 'center' | 'end' | 'between';
208
+ }
209
+
210
+ /**
211
+ * Slot props for Modal component
212
+ */
213
+ export interface ModalRootSlotProps {
214
+ className: string;
215
+ style?: React.CSSProperties;
216
+ children: React.ReactNode;
217
+ role: string;
218
+ 'aria-modal': boolean;
219
+ 'aria-hidden': boolean;
220
+ }
221
+
222
+ export interface ModalBackdropSlotProps {
223
+ className: string;
224
+ style?: React.CSSProperties;
225
+ onClick?: React.MouseEventHandler<HTMLDivElement>;
226
+ }
227
+
228
+ export interface ModalDialogSlotProps {
229
+ className: string;
230
+ style?: React.CSSProperties;
231
+ children: React.ReactNode;
232
+ }
233
+
234
+ export interface ModalContentSlotProps {
235
+ className: string;
236
+ style?: React.CSSProperties;
237
+ children: React.ReactNode;
238
+ }
239
+
240
+ /**
241
+ * Slot props for Input component
242
+ */
243
+ export interface InputRootSlotProps {
244
+ className: string;
245
+ style?: React.CSSProperties;
246
+ children: React.ReactNode;
247
+ }
248
+
249
+ export interface InputElementSlotProps {
250
+ className: string;
251
+ style?: React.CSSProperties;
252
+ type?: string;
253
+ value?: string | number;
254
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
255
+ onFocus?: React.FocusEventHandler<HTMLInputElement>;
256
+ onBlur?: React.FocusEventHandler<HTMLInputElement>;
257
+ placeholder?: string;
258
+ disabled?: boolean;
259
+ required?: boolean;
260
+ readOnly?: boolean;
261
+ 'aria-label'?: string;
262
+ 'aria-invalid'?: boolean;
263
+ }
264
+
265
+ /**
266
+ * Slot props for Dropdown component
267
+ */
268
+ export interface DropdownRootSlotProps {
269
+ className: string;
270
+ style?: React.CSSProperties;
271
+ children: React.ReactNode;
272
+ }
273
+
274
+ export interface DropdownToggleSlotProps {
275
+ className: string;
276
+ style?: React.CSSProperties;
277
+ children: React.ReactNode;
278
+ onClick?: React.MouseEventHandler<HTMLDivElement>;
279
+ onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
280
+ 'aria-haspopup': string;
281
+ 'aria-expanded': boolean;
282
+ 'aria-controls': string;
283
+ tabIndex: number;
284
+ }
285
+
286
+ export interface DropdownMenuSlotProps {
287
+ className: string;
288
+ style?: React.CSSProperties;
289
+ children: React.ReactNode;
290
+ role: string;
291
+ 'aria-orientation': string;
292
+ 'aria-hidden': boolean;
293
+ }
294
+
295
+ /**
296
+ * Slot props for Badge component
297
+ */
298
+ export interface BadgeRootSlotProps {
299
+ className: string;
300
+ style?: React.CSSProperties;
301
+ children: React.ReactNode;
302
+ onClick?: React.MouseEventHandler<HTMLSpanElement>;
303
+ role?: string;
304
+ 'aria-label'?: string;
305
+ }
306
+
307
+ export interface BadgeIconSlotProps {
308
+ className: string;
309
+ style?: React.CSSProperties;
310
+ children: React.ReactNode;
311
+ }
312
+
313
+ export interface BadgeLabelSlotProps {
314
+ className: string;
315
+ style?: React.CSSProperties;
316
+ children: React.ReactNode;
317
+ }
318
+
319
+ /**
320
+ * Slot props for Progress component
321
+ */
322
+ export interface ProgressRootSlotProps {
323
+ className: string;
324
+ style?: React.CSSProperties;
325
+ children: React.ReactNode;
326
+ role: string;
327
+ 'aria-valuenow': number;
328
+ 'aria-valuemin': number;
329
+ 'aria-valuemax': number;
330
+ 'aria-label'?: string;
331
+ }
332
+
333
+ export interface ProgressBarSlotProps {
334
+ className: string;
335
+ style?: React.CSSProperties;
336
+ }
337
+
338
+ /**
339
+ * Slot props for Checkbox component
340
+ */
341
+ export interface CheckboxRootSlotProps {
342
+ className: string;
343
+ style?: React.CSSProperties;
344
+ children: React.ReactNode;
345
+ }
346
+
347
+ export interface CheckboxInputSlotProps {
348
+ className: string;
349
+ style?: React.CSSProperties;
350
+ type: 'checkbox';
351
+ checked?: boolean;
352
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
353
+ disabled?: boolean;
354
+ required?: boolean;
355
+ id?: string;
356
+ name?: string;
357
+ value?: string;
358
+ 'aria-label'?: string;
359
+ 'aria-describedby'?: string;
360
+ 'aria-invalid'?: boolean;
361
+ }
362
+
363
+ export interface CheckboxLabelSlotProps {
364
+ className: string;
365
+ style?: React.CSSProperties;
366
+ children: React.ReactNode;
367
+ htmlFor?: string;
368
+ }
369
+
370
+ /**
371
+ * Slot props for Radio component
372
+ */
373
+ export interface RadioRootSlotProps {
374
+ className: string;
375
+ style?: React.CSSProperties;
376
+ children: React.ReactNode;
377
+ }
378
+
379
+ export interface RadioInputSlotProps {
380
+ className: string;
381
+ style?: React.CSSProperties;
382
+ type: 'radio';
383
+ checked?: boolean;
384
+ onChange?: React.ChangeEventHandler<HTMLInputElement>;
385
+ disabled?: boolean;
386
+ required?: boolean;
387
+ id?: string;
388
+ name?: string;
389
+ value?: string;
390
+ 'aria-label'?: string;
391
+ 'aria-describedby'?: string;
392
+ 'aria-invalid'?: boolean;
393
+ }
394
+
395
+ export interface RadioLabelSlotProps {
396
+ className: string;
397
+ style?: React.CSSProperties;
398
+ children: React.ReactNode;
399
+ htmlFor?: string;
400
+ }
401
+
402
+ /**
403
+ * Utility to create typed slot props
404
+ */
405
+ export function createSlotProps<T>(props: T): T {
406
+ return props;
407
+ }
408
+
409
+ /**
410
+ * Hook to manage slot rendering
411
+ */
412
+ export function useSlot<T>(
413
+ slot: SlotProps<T> | React.ReactNode | undefined,
414
+ props: T,
415
+ fallback?: React.ReactNode
416
+ ): React.ReactNode {
417
+ return React.useMemo(
418
+ () => renderSlot(slot, props, fallback),
419
+ [slot, props, fallback]
420
+ );
421
+ }
@@ -185,7 +185,6 @@ export function createThemeVariants(baseTheme: ThemeOptions): {
185
185
  ...baseTheme.palette,
186
186
  background: {
187
187
  default: '#121212',
188
- paper: '#1E1E1E',
189
188
  subtle: '#2A2A2A',
190
189
  ...baseTheme.palette?.background,
191
190
  },
@@ -304,7 +303,6 @@ export function createThemePreset(
304
303
  secondary: { main: '#FFFFFF' },
305
304
  background: {
306
305
  default: '#FFFFFF',
307
- paper: '#F5F5F5',
308
306
  subtle: '#FAFAFA',
309
307
  },
310
308
  },
@@ -319,7 +317,6 @@ export function createThemePreset(
319
317
  secondary: { main: '#FF5733' },
320
318
  background: {
321
319
  default: '#FAFAFA',
322
- paper: '#FFFFFF',
323
320
  subtle: '#F5F5F5',
324
321
  },
325
322
  },
@@ -334,7 +331,6 @@ export function createThemePreset(
334
331
  secondary: { main: '#DC004E' },
335
332
  background: {
336
333
  default: '#FFFFFF',
337
- paper: '#F5F5F5',
338
334
  subtle: '#EEEEEE',
339
335
  },
340
336
  },
@@ -349,7 +345,6 @@ export function createThemePreset(
349
345
  secondary: { main: '#4ECDC4' },
350
346
  background: {
351
347
  default: '#FFF8F0',
352
- paper: '#FFFFFF',
353
348
  subtle: '#FFF0E0',
354
349
  },
355
350
  },
@@ -11,7 +11,7 @@ export type {
11
11
  LoadedThemeConfig,
12
12
  ConfigValidationResult,
13
13
  ThemeMetadata,
14
- ThemeConfig,
14
+ AtomixConfig,
15
15
  ThemeDefinition,
16
16
  CSSThemeDefinition,
17
17
  JSThemeDefinition,
@@ -13,7 +13,9 @@ import { validateConfig } from './validator';
13
13
  import { ThemeError, ThemeErrorCode, getLogger } from '../errors';
14
14
  import {
15
15
  DEFAULT_CONFIG_PATH,
16
+ DEFAULT_ATOMIX_CONFIG_PATH,
16
17
  DEFAULT_CONFIG_RELATIVE_PATH,
18
+ DEFAULT_LEGACY_CONFIG_RELATIVE_PATH,
17
19
  DEFAULT_BASE_PATH,
18
20
  DEFAULT_STORAGE_KEY,
19
21
  DEFAULT_DATA_ATTRIBUTE,
@@ -50,7 +52,7 @@ export function loadThemeConfig(
50
52
  options: ConfigLoaderOptions = {}
51
53
  ): LoadedThemeConfig {
52
54
  const {
53
- configPath = DEFAULT_CONFIG_PATH,
55
+ configPath = DEFAULT_ATOMIX_CONFIG_PATH,
54
56
  validate = true,
55
57
  env = typeof process !== 'undefined' && process.env ? (process.env.NODE_ENV === 'production' ? 'production' : 'development') : 'development',
56
58
  } = options;
@@ -62,67 +64,99 @@ export function loadThemeConfig(
62
64
 
63
65
  // Try to load config dynamically
64
66
  let config: LoadedThemeConfig;
65
-
67
+
66
68
  try {
67
- // In browser/Vite environment, we can't load theme.config.ts dynamically
68
- // This is expected and we'll use the fallback config
69
+ // In browser/Vite environment, we can't load config dynamically
69
70
  if (typeof window !== 'undefined') {
70
71
  throw new Error('Theme config loading not supported in browser environment');
71
72
  }
72
-
73
- // In Node.js/bundler environment, try require (CommonJS) first
74
- // Check if we're in a browser environment first
75
- if (typeof window !== 'undefined' || typeof require === 'undefined') {
76
- throw new Error('Theme config loading not supported in browser environment');
73
+
74
+ // In ESM environments, require might be undefined.
75
+ let nodeRequire: any;
76
+ try {
77
+ nodeRequire = require;
78
+ } catch {
79
+ // require is not defined
77
80
  }
78
-
79
- // Type for theme config module
80
- interface ThemeConfigModule {
81
- default?: LoadedThemeConfig;
81
+
82
+ if (!nodeRequire) {
83
+ throw new Error('Theme config loading not supported in this environment (require is undefined)');
84
+ }
85
+
86
+ // Type for config module
87
+ interface ConfigModule {
88
+ default?: any;
82
89
  [key: string]: unknown;
83
90
  }
84
-
85
- let themeConfigModule: ThemeConfigModule;
86
-
87
- // Try require (Node.js/CommonJS) - works in Node.js environments
91
+
92
+ let configModule: ConfigModule;
93
+
94
+ // Try require (Node.js/CommonJS)
88
95
  try {
89
- // Try relative path first (for build tools)
96
+ // Try relative path first
90
97
  try {
91
- themeConfigModule = require(DEFAULT_CONFIG_RELATIVE_PATH) as ThemeConfigModule;
98
+ configModule = nodeRequire(DEFAULT_CONFIG_RELATIVE_PATH) as ConfigModule;
92
99
  } catch {
93
- // If relative path fails, try to resolve from process.cwd()
94
- const path = require('path') as typeof import('path');
95
- const fs = require('fs') as typeof import('fs');
96
- const configFilePath = path.resolve(process.cwd(), configPath);
97
-
98
- // Check if file exists
99
- if (fs.existsSync(configFilePath)) {
100
- // Delete from cache to force reload
101
- const resolvedPath = require.resolve(configFilePath);
102
- if (require.cache && require.cache[resolvedPath]) {
103
- delete require.cache[resolvedPath];
100
+ // Try fallback to legacy relative path
101
+ try {
102
+ configModule = nodeRequire(DEFAULT_LEGACY_CONFIG_RELATIVE_PATH) as ConfigModule;
103
+ } catch {
104
+ // If relative paths fail, try to resolve from process.cwd()
105
+ const path = nodeRequire('path') as typeof import('path');
106
+ const fs = nodeRequire('fs') as typeof import('fs');
107
+
108
+ let configFilePath = path.resolve(process.cwd(), configPath);
109
+
110
+ // Fallback if atomix.config.ts not found
111
+ if (!fs.existsSync(configFilePath) && configPath === DEFAULT_ATOMIX_CONFIG_PATH) {
112
+ configFilePath = path.resolve(process.cwd(), DEFAULT_CONFIG_PATH);
113
+ }
114
+
115
+ if (fs.existsSync(configFilePath)) {
116
+ const resolvedPath = nodeRequire.resolve(configFilePath);
117
+ if (nodeRequire.cache && nodeRequire.cache[resolvedPath]) {
118
+ delete nodeRequire.cache[resolvedPath];
119
+ }
120
+ configModule = nodeRequire(configFilePath) as ConfigModule;
121
+ } else {
122
+ throw new Error(`Config file not found: ${configFilePath}`);
104
123
  }
105
- themeConfigModule = require(configFilePath) as ThemeConfigModule;
106
- } else {
107
- throw new Error(`Config file not found: ${configFilePath}`);
108
124
  }
109
125
  }
110
126
  } catch (requireError) {
111
- // If require fails, throw to fall through to error handling
112
- const errorMessage = requireError instanceof Error
113
- ? requireError.message
127
+ const errorMessage = requireError instanceof Error
128
+ ? requireError.message
114
129
  : String(requireError);
115
130
  throw new ThemeError(
116
- `Cannot load theme config: ${errorMessage}`,
131
+ `Cannot load config: ${errorMessage}`,
117
132
  ThemeErrorCode.CONFIG_LOAD_FAILED,
118
133
  { configPath, error: errorMessage }
119
134
  );
120
135
  }
121
-
122
- const rawConfig = (themeConfigModule.default || themeConfigModule) as LoadedThemeConfig;
136
+
137
+ const rawConfig = configModule.default || configModule;
138
+
139
+ // Handle new AtomixConfig structure vs legacy ThemeConfig
140
+ let processedConfig: any;
141
+ if (rawConfig.theme && (rawConfig.theme.themes || rawConfig.theme.tokens || rawConfig.theme.extend)) {
142
+ // New AtomixConfig structure
143
+ processedConfig = {
144
+ themes: rawConfig.theme.themes || {},
145
+ build: rawConfig.build || {},
146
+ runtime: rawConfig.runtime || {},
147
+ integration: rawConfig.integration || {},
148
+ dependencies: rawConfig.dependencies || {},
149
+ // Store tokens for generator
150
+ __tokens: rawConfig.theme.tokens,
151
+ __extend: rawConfig.theme.extend,
152
+ };
153
+ } else {
154
+ // Legacy ThemeConfig structure
155
+ processedConfig = { ...rawConfig };
156
+ }
123
157
 
124
158
  // Apply environment-specific overrides
125
- const processedConfig = applyEnvOverrides(rawConfig, env);
159
+ processedConfig = applyEnvOverrides(processedConfig, env);
126
160
 
127
161
  // Validate if requested
128
162
  let validationResult: ConfigValidationResult | null = null;
@@ -143,7 +177,7 @@ export function loadThemeConfig(
143
177
  configPath,
144
178
  error: errorMessage,
145
179
  });
146
-
180
+
147
181
  config = {
148
182
  themes: {},
149
183
  build: {
@@ -5,14 +5,14 @@
5
5
  */
6
6
 
7
7
  import type {
8
- ThemeConfig,
9
- ThemeDefinition,
10
- CSSThemeDefinition,
11
- JSThemeDefinition,
8
+ AtomixConfig,
12
9
  BuildConfig,
13
10
  RuntimeConfig,
14
11
  IntegrationConfig,
15
- } from '../../../../theme.config';
12
+ ThemeDefinition,
13
+ CSSThemeDefinition,
14
+ JSThemeDefinition,
15
+ } from '../../config';
16
16
 
17
17
  /**
18
18
  * Configuration loader options
@@ -29,13 +29,27 @@ export interface ConfigLoaderOptions {
29
29
  /**
30
30
  * Loaded and validated theme configuration
31
31
  */
32
- export interface LoadedThemeConfig extends ThemeConfig {
32
+ export interface LoadedThemeConfig {
33
+ /** Registered themes */
34
+ themes: Record<string, ThemeDefinition>;
35
+ /** Build configuration */
36
+ build: BuildConfig;
37
+ /** Runtime configuration */
38
+ runtime: RuntimeConfig;
39
+ /** Integration settings */
40
+ integration: IntegrationConfig;
41
+ /** Theme dependencies mapping */
42
+ dependencies: Record<string, string[]>;
33
43
  /** Whether config was validated */
34
44
  validated: boolean;
35
45
  /** Validation errors (if any) */
36
46
  errors?: string[];
37
47
  /** Validation warnings (if any) */
38
48
  warnings?: string[];
49
+ /** Internal tokens (for generator) */
50
+ __tokens?: any;
51
+ /** Internal extensions (for generator) */
52
+ __extend?: any;
39
53
  }
40
54
 
41
55
  /**
@@ -88,7 +102,7 @@ export interface ConfigValidationResult {
88
102
  }
89
103
 
90
104
  export type {
91
- ThemeConfig,
105
+ AtomixConfig,
92
106
  ThemeDefinition,
93
107
  CSSThemeDefinition,
94
108
  JSThemeDefinition,
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import type {
8
- ThemeConfig,
8
+ AtomixConfig,
9
9
  ThemeDefinition,
10
10
  CSSThemeDefinition,
11
11
  JSThemeDefinition,