@idealyst/theme 1.1.6 → 1.1.8
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/package.json +29 -1
- package/src/babel/index.ts +9 -0
- package/src/babel/plugin.js +871 -0
- package/src/babel/plugin.ts +187 -0
- package/src/babel/runtime.ts +94 -0
- package/src/babel/theme-analyzer.js +357 -0
- package/src/builder.ts +317 -0
- package/src/componentStyles.ts +93 -0
- package/src/config/cli.ts +95 -0
- package/src/config/generator.ts +817 -0
- package/src/config/index.ts +10 -0
- package/src/config/types.ts +112 -0
- package/src/darkTheme.ts +186 -943
- package/src/extensions.ts +110 -0
- package/src/helpers.ts +206 -0
- package/src/index.ts +18 -4
- package/src/lightTheme.ts +286 -859
- package/src/styleBuilder.ts +108 -0
- package/src/theme/color.ts +36 -15
- package/src/theme/extensions.ts +99 -0
- package/src/theme/index.ts +41 -27
- package/src/theme/intent.ts +12 -7
- package/src/theme/shadow.ts +12 -16
- package/src/theme/size.ts +6 -202
- package/src/theme/structures.ts +237 -0
- package/src/unistyles.ts +8 -24
- package/src/variants/color.ts +3 -5
package/src/builder.ts
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IntentValue,
|
|
3
|
+
ShadowValue,
|
|
4
|
+
InteractionConfig,
|
|
5
|
+
ColorValue,
|
|
6
|
+
Shade,
|
|
7
|
+
Typography,
|
|
8
|
+
TypographyValue,
|
|
9
|
+
ButtonSizeValue,
|
|
10
|
+
ChipSizeValue,
|
|
11
|
+
BadgeSizeValue,
|
|
12
|
+
IconSizeValue,
|
|
13
|
+
InputSizeValue,
|
|
14
|
+
RadioButtonSizeValue,
|
|
15
|
+
SelectSizeValue,
|
|
16
|
+
SliderSizeValue,
|
|
17
|
+
SwitchSizeValue,
|
|
18
|
+
TextAreaSizeValue,
|
|
19
|
+
AvatarSizeValue,
|
|
20
|
+
ProgressSizeValue,
|
|
21
|
+
AccordionSizeValue,
|
|
22
|
+
ActivityIndicatorSizeValue,
|
|
23
|
+
BreadcrumbSizeValue,
|
|
24
|
+
ListSizeValue,
|
|
25
|
+
MenuSizeValue,
|
|
26
|
+
TextSizeValue,
|
|
27
|
+
TabBarSizeValue,
|
|
28
|
+
TableSizeValue,
|
|
29
|
+
TooltipSizeValue,
|
|
30
|
+
ViewSizeValue,
|
|
31
|
+
} from './theme/structures';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Built theme structure - self-contained, no external type dependencies.
|
|
35
|
+
*/
|
|
36
|
+
export type BuiltTheme<
|
|
37
|
+
TIntents extends string,
|
|
38
|
+
TRadii extends string,
|
|
39
|
+
TShadows extends string,
|
|
40
|
+
TPallet extends string,
|
|
41
|
+
TSurface extends string,
|
|
42
|
+
TText extends string,
|
|
43
|
+
TBorder extends string,
|
|
44
|
+
TSize extends string,
|
|
45
|
+
> = {
|
|
46
|
+
intents: Record<TIntents, IntentValue>;
|
|
47
|
+
radii: Record<TRadii, number>;
|
|
48
|
+
shadows: Record<TShadows, ShadowValue>;
|
|
49
|
+
colors: {
|
|
50
|
+
pallet: Record<TPallet, Record<Shade, ColorValue>>;
|
|
51
|
+
surface: Record<TSurface, ColorValue>;
|
|
52
|
+
text: Record<TText, ColorValue>;
|
|
53
|
+
border: Record<TBorder, ColorValue>;
|
|
54
|
+
};
|
|
55
|
+
sizes: {
|
|
56
|
+
button: Record<TSize, ButtonSizeValue>;
|
|
57
|
+
chip: Record<TSize, ChipSizeValue>;
|
|
58
|
+
badge: Record<TSize, BadgeSizeValue>;
|
|
59
|
+
icon: Record<TSize, IconSizeValue>;
|
|
60
|
+
input: Record<TSize, InputSizeValue>;
|
|
61
|
+
radioButton: Record<TSize, RadioButtonSizeValue>;
|
|
62
|
+
select: Record<TSize, SelectSizeValue>;
|
|
63
|
+
slider: Record<TSize, SliderSizeValue>;
|
|
64
|
+
switch: Record<TSize, SwitchSizeValue>;
|
|
65
|
+
textarea: Record<TSize, TextAreaSizeValue>;
|
|
66
|
+
avatar: Record<TSize, AvatarSizeValue>;
|
|
67
|
+
progress: Record<TSize, ProgressSizeValue>;
|
|
68
|
+
accordion: Record<TSize, AccordionSizeValue>;
|
|
69
|
+
activityIndicator: Record<TSize, ActivityIndicatorSizeValue>;
|
|
70
|
+
breadcrumb: Record<TSize, BreadcrumbSizeValue>;
|
|
71
|
+
list: Record<TSize, ListSizeValue>;
|
|
72
|
+
menu: Record<TSize, MenuSizeValue>;
|
|
73
|
+
text: Record<TSize, TextSizeValue>;
|
|
74
|
+
tabBar: Record<TSize, TabBarSizeValue>;
|
|
75
|
+
table: Record<TSize, TableSizeValue>;
|
|
76
|
+
tooltip: Record<TSize, TooltipSizeValue>;
|
|
77
|
+
view: Record<TSize, ViewSizeValue>;
|
|
78
|
+
typography: Record<Typography, TypographyValue>;
|
|
79
|
+
};
|
|
80
|
+
interaction: InteractionConfig;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Internal config type for building.
|
|
85
|
+
*/
|
|
86
|
+
type ThemeConfig<
|
|
87
|
+
TIntents extends string,
|
|
88
|
+
TRadii extends string,
|
|
89
|
+
TShadows extends string,
|
|
90
|
+
TPallet extends string,
|
|
91
|
+
TSurface extends string,
|
|
92
|
+
TText extends string,
|
|
93
|
+
TBorder extends string,
|
|
94
|
+
TSize extends string,
|
|
95
|
+
> = BuiltTheme<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Fluent builder for creating themes with full TypeScript inference.
|
|
99
|
+
*
|
|
100
|
+
* Build a theme, then register it to get automatic type inference for all components:
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const myTheme = createTheme()
|
|
105
|
+
* .addIntent('primary', { primary: '#3b82f6', contrast: '#fff', light: '#bfdbfe', dark: '#1e40af' })
|
|
106
|
+
* .addIntent('brand', { primary: '#6366f1', contrast: '#fff', light: '#818cf8', dark: '#4f46e5' })
|
|
107
|
+
* .addRadius('sm', 4)
|
|
108
|
+
* .addRadius('full', 9999)
|
|
109
|
+
* .build();
|
|
110
|
+
*
|
|
111
|
+
* // Register the theme type
|
|
112
|
+
* declare module '@idealyst/theme' {
|
|
113
|
+
* interface RegisteredTheme {
|
|
114
|
+
* theme: typeof myTheme;
|
|
115
|
+
* }
|
|
116
|
+
* }
|
|
117
|
+
*
|
|
118
|
+
* // Now Intent = 'primary' | 'brand', Radius = 'sm' | 'full', etc.
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export class ThemeBuilder<
|
|
122
|
+
TIntents extends string = never,
|
|
123
|
+
TRadii extends string = never,
|
|
124
|
+
TShadows extends string = never,
|
|
125
|
+
TPallet extends string = never,
|
|
126
|
+
TSurface extends string = never,
|
|
127
|
+
TText extends string = never,
|
|
128
|
+
TBorder extends string = never,
|
|
129
|
+
TSize extends string = never,
|
|
130
|
+
> {
|
|
131
|
+
private config: ThemeConfig<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize>;
|
|
132
|
+
|
|
133
|
+
constructor() {
|
|
134
|
+
this.config = {
|
|
135
|
+
intents: {} as any,
|
|
136
|
+
radii: {} as any,
|
|
137
|
+
shadows: {} as any,
|
|
138
|
+
colors: {
|
|
139
|
+
pallet: {} as any,
|
|
140
|
+
surface: {} as any,
|
|
141
|
+
text: {} as any,
|
|
142
|
+
border: {} as any,
|
|
143
|
+
},
|
|
144
|
+
sizes: {} as any,
|
|
145
|
+
interaction: {} as any,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Add a custom intent to the theme.
|
|
151
|
+
*/
|
|
152
|
+
addIntent<K extends string>(
|
|
153
|
+
name: K,
|
|
154
|
+
value: IntentValue
|
|
155
|
+
): ThemeBuilder<TIntents | K, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize> {
|
|
156
|
+
const newBuilder = new ThemeBuilder<TIntents | K, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize>();
|
|
157
|
+
newBuilder.config = {
|
|
158
|
+
...this.config,
|
|
159
|
+
intents: {
|
|
160
|
+
...this.config.intents,
|
|
161
|
+
[name]: value,
|
|
162
|
+
} as any,
|
|
163
|
+
};
|
|
164
|
+
return newBuilder;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Add a custom border radius value.
|
|
169
|
+
*/
|
|
170
|
+
addRadius<K extends string>(
|
|
171
|
+
name: K,
|
|
172
|
+
value: number
|
|
173
|
+
): ThemeBuilder<TIntents, TRadii | K, TShadows, TPallet, TSurface, TText, TBorder, TSize> {
|
|
174
|
+
const newBuilder = new ThemeBuilder<TIntents, TRadii | K, TShadows, TPallet, TSurface, TText, TBorder, TSize>();
|
|
175
|
+
newBuilder.config = {
|
|
176
|
+
...this.config,
|
|
177
|
+
radii: {
|
|
178
|
+
...this.config.radii,
|
|
179
|
+
[name]: value,
|
|
180
|
+
} as any,
|
|
181
|
+
};
|
|
182
|
+
return newBuilder;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Add a custom shadow value.
|
|
187
|
+
*/
|
|
188
|
+
addShadow<K extends string>(
|
|
189
|
+
name: K,
|
|
190
|
+
value: ShadowValue
|
|
191
|
+
): ThemeBuilder<TIntents, TRadii, TShadows | K, TPallet, TSurface, TText, TBorder, TSize> {
|
|
192
|
+
const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows | K, TPallet, TSurface, TText, TBorder, TSize>();
|
|
193
|
+
newBuilder.config = {
|
|
194
|
+
...this.config,
|
|
195
|
+
shadows: {
|
|
196
|
+
...this.config.shadows,
|
|
197
|
+
[name]: value,
|
|
198
|
+
} as any,
|
|
199
|
+
};
|
|
200
|
+
return newBuilder;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Set the interaction configuration.
|
|
205
|
+
*/
|
|
206
|
+
setInteraction(
|
|
207
|
+
interaction: InteractionConfig
|
|
208
|
+
): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize> {
|
|
209
|
+
const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize>();
|
|
210
|
+
newBuilder.config = {
|
|
211
|
+
...this.config,
|
|
212
|
+
interaction,
|
|
213
|
+
};
|
|
214
|
+
return newBuilder;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Set the colors configuration.
|
|
219
|
+
*/
|
|
220
|
+
setColors<
|
|
221
|
+
P extends string,
|
|
222
|
+
S extends string,
|
|
223
|
+
T extends string,
|
|
224
|
+
B extends string,
|
|
225
|
+
>(colors: {
|
|
226
|
+
pallet: Record<P, Record<Shade, ColorValue>>;
|
|
227
|
+
surface: Record<S, ColorValue>;
|
|
228
|
+
text: Record<T, ColorValue>;
|
|
229
|
+
border: Record<B, ColorValue>;
|
|
230
|
+
}): ThemeBuilder<TIntents, TRadii, TShadows, P, S, T, B, TSize> {
|
|
231
|
+
const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, P, S, T, B, TSize>();
|
|
232
|
+
newBuilder.config = {
|
|
233
|
+
...this.config,
|
|
234
|
+
colors,
|
|
235
|
+
} as any;
|
|
236
|
+
return newBuilder;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Set the sizes configuration.
|
|
241
|
+
*/
|
|
242
|
+
setSizes<S extends string>(sizes: {
|
|
243
|
+
button: Record<S, ButtonSizeValue>;
|
|
244
|
+
chip: Record<S, ChipSizeValue>;
|
|
245
|
+
badge: Record<S, BadgeSizeValue>;
|
|
246
|
+
icon: Record<S, IconSizeValue>;
|
|
247
|
+
input: Record<S, InputSizeValue>;
|
|
248
|
+
radioButton: Record<S, RadioButtonSizeValue>;
|
|
249
|
+
select: Record<S, SelectSizeValue>;
|
|
250
|
+
slider: Record<S, SliderSizeValue>;
|
|
251
|
+
switch: Record<S, SwitchSizeValue>;
|
|
252
|
+
textarea: Record<S, TextAreaSizeValue>;
|
|
253
|
+
avatar: Record<S, AvatarSizeValue>;
|
|
254
|
+
progress: Record<S, ProgressSizeValue>;
|
|
255
|
+
accordion: Record<S, AccordionSizeValue>;
|
|
256
|
+
activityIndicator: Record<S, ActivityIndicatorSizeValue>;
|
|
257
|
+
breadcrumb: Record<S, BreadcrumbSizeValue>;
|
|
258
|
+
list: Record<S, ListSizeValue>;
|
|
259
|
+
menu: Record<S, MenuSizeValue>;
|
|
260
|
+
text: Record<S, TextSizeValue>;
|
|
261
|
+
tabBar: Record<S, TabBarSizeValue>;
|
|
262
|
+
table: Record<S, TableSizeValue>;
|
|
263
|
+
tooltip: Record<S, TooltipSizeValue>;
|
|
264
|
+
view: Record<S, ViewSizeValue>;
|
|
265
|
+
typography: Record<Typography, TypographyValue>;
|
|
266
|
+
}): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, S> {
|
|
267
|
+
const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, S>();
|
|
268
|
+
newBuilder.config = {
|
|
269
|
+
...this.config,
|
|
270
|
+
sizes,
|
|
271
|
+
} as any;
|
|
272
|
+
return newBuilder;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Build the final theme object.
|
|
277
|
+
*/
|
|
278
|
+
build(): BuiltTheme<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize> {
|
|
279
|
+
return this.config;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Create a new theme builder.
|
|
285
|
+
*/
|
|
286
|
+
export function createTheme(): ThemeBuilder {
|
|
287
|
+
return new ThemeBuilder();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Create a builder from an existing theme to add more values.
|
|
292
|
+
*/
|
|
293
|
+
export function fromTheme<T extends BuiltTheme<any, any, any, any, any, any, any, any>>(
|
|
294
|
+
base: T
|
|
295
|
+
): ThemeBuilder<
|
|
296
|
+
keyof T['intents'] & string,
|
|
297
|
+
keyof T['radii'] & string,
|
|
298
|
+
keyof T['shadows'] & string,
|
|
299
|
+
keyof T['colors']['pallet'] & string,
|
|
300
|
+
keyof T['colors']['surface'] & string,
|
|
301
|
+
keyof T['colors']['text'] & string,
|
|
302
|
+
keyof T['colors']['border'] & string,
|
|
303
|
+
keyof T['sizes']['button'] & string
|
|
304
|
+
> {
|
|
305
|
+
const builder = new ThemeBuilder<
|
|
306
|
+
keyof T['intents'] & string,
|
|
307
|
+
keyof T['radii'] & string,
|
|
308
|
+
keyof T['shadows'] & string,
|
|
309
|
+
keyof T['colors']['pallet'] & string,
|
|
310
|
+
keyof T['colors']['surface'] & string,
|
|
311
|
+
keyof T['colors']['text'] & string,
|
|
312
|
+
keyof T['colors']['border'] & string,
|
|
313
|
+
keyof T['sizes']['button'] & string
|
|
314
|
+
>();
|
|
315
|
+
(builder as any).config = { ...base };
|
|
316
|
+
return builder;
|
|
317
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Style Types Registry
|
|
3
|
+
*
|
|
4
|
+
* This module provides type definitions for component styles used with
|
|
5
|
+
* defineStyle, extendStyle, and overrideStyle.
|
|
6
|
+
*
|
|
7
|
+
* Components register their style types via module augmentation:
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // In Text.styles.tsx
|
|
12
|
+
* declare module '@idealyst/theme' {
|
|
13
|
+
* interface ComponentStyleRegistry {
|
|
14
|
+
* Text: TextStyleDef;
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { TextStyle, ViewStyle } from 'react-native';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Registry interface that components augment to register their style types.
|
|
24
|
+
* This enables type-safe extendStyle and overrideStyle calls.
|
|
25
|
+
*/
|
|
26
|
+
export interface ComponentStyleRegistry {
|
|
27
|
+
// Components augment this interface to add their style types
|
|
28
|
+
// Example: Text: { text: (params: TextStyleParams) => TextStyleObject }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get the style definition type for a component.
|
|
33
|
+
* Returns the registered type or a loose Record type for unregistered components.
|
|
34
|
+
*/
|
|
35
|
+
export type ComponentStyleDef<K extends string> = K extends keyof ComponentStyleRegistry
|
|
36
|
+
? ComponentStyleRegistry[K]
|
|
37
|
+
: Record<string, any>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Deep partial type that works with functions.
|
|
41
|
+
* For style functions, preserves the function signature but makes the return type partial.
|
|
42
|
+
*/
|
|
43
|
+
export type DeepPartialStyle<T> = T extends (...args: infer A) => infer R
|
|
44
|
+
? (...args: A) => DeepPartialStyle<R>
|
|
45
|
+
: T extends object
|
|
46
|
+
? { [K in keyof T]?: DeepPartialStyle<T[K]> }
|
|
47
|
+
: T;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Style definition for extendStyle - requires functions with same params as base.
|
|
51
|
+
* All style properties must be functions to access dynamic params.
|
|
52
|
+
*/
|
|
53
|
+
export type ExtendStyleDef<K extends string> = DeepPartialStyle<ComponentStyleDef<K>>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Style definition for overrideStyle - requires full implementation with functions.
|
|
57
|
+
*/
|
|
58
|
+
export type OverrideStyleDef<K extends string> = ComponentStyleDef<K>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Helper to extract the params type from a dynamic style function.
|
|
62
|
+
* Use this to type your extension functions.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* type TextParams = StyleParams<TextStyleDef['text']>;
|
|
67
|
+
* // TextParams = { color?: TextColorVariant }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export type StyleParams<T> = T extends (params: infer P) => any ? P : never;
|
|
71
|
+
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// Common Style Types
|
|
74
|
+
// =============================================================================
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Base style object with optional variants and compound variants.
|
|
78
|
+
*/
|
|
79
|
+
export interface StyleWithVariants<TVariants extends Record<string, any> = Record<string, any>> {
|
|
80
|
+
variants?: {
|
|
81
|
+
[K in keyof TVariants]?: {
|
|
82
|
+
[V in TVariants[K] extends string | boolean ? TVariants[K] : string]?: ViewStyle | TextStyle;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
compoundVariants?: Array<{
|
|
86
|
+
[K in keyof TVariants]?: TVariants[K];
|
|
87
|
+
} & { styles: ViewStyle | TextStyle }>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Dynamic style function type.
|
|
92
|
+
*/
|
|
93
|
+
export type DynamicStyleFn<TParams, TStyle> = (params: TParams) => TStyle;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Idealyst Style Generator CLI
|
|
4
|
+
*
|
|
5
|
+
* Reads idealyst.config.ts and generates flat Unistyles-compatible style files.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx ts-node packages/theme/src/config/cli.ts [config-path] [output-dir]
|
|
9
|
+
*
|
|
10
|
+
* Defaults:
|
|
11
|
+
* config-path: ./idealyst.config.ts
|
|
12
|
+
* output-dir: ./generated
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
|
|
18
|
+
// Dynamic import for ESM compatibility
|
|
19
|
+
async function main() {
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const configPath = args[0] || './idealyst.config.ts';
|
|
22
|
+
const outputDir = args[1] || './generated';
|
|
23
|
+
|
|
24
|
+
console.log('🎨 Idealyst Style Generator');
|
|
25
|
+
console.log(` Config: ${configPath}`);
|
|
26
|
+
console.log(` Output: ${outputDir}`);
|
|
27
|
+
console.log('');
|
|
28
|
+
|
|
29
|
+
// Resolve paths
|
|
30
|
+
const resolvedConfigPath = path.resolve(process.cwd(), configPath);
|
|
31
|
+
const resolvedOutputDir = path.resolve(process.cwd(), outputDir);
|
|
32
|
+
|
|
33
|
+
// Check config exists
|
|
34
|
+
if (!fs.existsSync(resolvedConfigPath)) {
|
|
35
|
+
console.error(`❌ Config file not found: ${resolvedConfigPath}`);
|
|
36
|
+
console.error('');
|
|
37
|
+
console.error('Create an idealyst.config.ts file with your theme configuration.');
|
|
38
|
+
console.error('See the documentation for examples.');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Import config dynamically
|
|
43
|
+
// Note: This requires ts-node or a pre-compiled config
|
|
44
|
+
let config;
|
|
45
|
+
try {
|
|
46
|
+
// Try to import the config
|
|
47
|
+
const configModule = await import(resolvedConfigPath);
|
|
48
|
+
config = configModule.default || configModule;
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error(`❌ Failed to load config: ${err}`);
|
|
51
|
+
console.error('');
|
|
52
|
+
console.error('Make sure your config file:');
|
|
53
|
+
console.error(' 1. Is a valid TypeScript/JavaScript file');
|
|
54
|
+
console.error(' 2. Uses export default or named exports');
|
|
55
|
+
console.error(' 3. Has all required theme properties');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Validate config
|
|
60
|
+
if (!config.themes || !config.themes.light || !config.themes.dark) {
|
|
61
|
+
console.error('❌ Invalid config: themes.light and themes.dark are required');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Import generator
|
|
66
|
+
const { generateStyles } = await import('./generator');
|
|
67
|
+
|
|
68
|
+
// Generate styles
|
|
69
|
+
console.log('⚙️ Generating styles...');
|
|
70
|
+
const files = generateStyles(config);
|
|
71
|
+
|
|
72
|
+
// Ensure output directory exists
|
|
73
|
+
if (!fs.existsSync(resolvedOutputDir)) {
|
|
74
|
+
fs.mkdirSync(resolvedOutputDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Write files
|
|
78
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
79
|
+
const filePath = path.join(resolvedOutputDir, filename);
|
|
80
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
81
|
+
console.log(` ✓ ${filename}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(`✅ Generated ${Object.keys(files).length} files in ${outputDir}`);
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log('Next steps:');
|
|
88
|
+
console.log(' 1. Import the generated unistyles.generated.ts in your app entry');
|
|
89
|
+
console.log(' 2. Update components to import from generated style files');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
main().catch((err) => {
|
|
93
|
+
console.error('Fatal error:', err);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|