@webmate-studio/builder 0.2.63 → 0.2.64
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 +1 -1
- package/src/design-tokens.js +1164 -0
- package/src/index.js +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,1164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Design Tokens für Website-Design
|
|
3
|
+
* Tailwind v4 kompatibel - verwendet Base-Values wo möglich
|
|
4
|
+
* Diese Tokens werden verwendet wenn keine custom Tokens in der DB existieren
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const defaultDesignTokens = {
|
|
8
|
+
colors: {
|
|
9
|
+
// Primary Colors
|
|
10
|
+
primary: '#0f172a',
|
|
11
|
+
primaryDark: '#020617',
|
|
12
|
+
primaryLight: '#334155',
|
|
13
|
+
|
|
14
|
+
// Secondary Colors
|
|
15
|
+
secondary: '#6366f1',
|
|
16
|
+
secondaryDark: '#4f46e5',
|
|
17
|
+
secondaryLight: '#818cf8',
|
|
18
|
+
|
|
19
|
+
// Neutral Colors
|
|
20
|
+
white: '#ffffff',
|
|
21
|
+
black: '#000000',
|
|
22
|
+
|
|
23
|
+
// Semantic Colors
|
|
24
|
+
success: '#10b981',
|
|
25
|
+
successDark: '#059669',
|
|
26
|
+
warning: '#f59e0b',
|
|
27
|
+
warningDark: '#d97706',
|
|
28
|
+
error: '#ef4444',
|
|
29
|
+
errorDark: '#dc2626',
|
|
30
|
+
info: '#3b82f6',
|
|
31
|
+
infoDark: '#2563eb',
|
|
32
|
+
|
|
33
|
+
// Background Colors (Semantic)
|
|
34
|
+
bgBase: '#ffffff',
|
|
35
|
+
bgElevated: '#f9fafb',
|
|
36
|
+
bgLifted: '#ffffff',
|
|
37
|
+
bgAccentBase: '#8b5cf6',
|
|
38
|
+
bgAccentElevated: '#a78bfa',
|
|
39
|
+
bgAccentLifted: '#ddd6fe',
|
|
40
|
+
|
|
41
|
+
// Text Colors (Semantic)
|
|
42
|
+
textBase: '#111827',
|
|
43
|
+
textSubtle: '#374151',
|
|
44
|
+
textMuted: '#6b7280',
|
|
45
|
+
textAccentBase: '#7c3aed',
|
|
46
|
+
textAccentSubtle: '#8b5cf6',
|
|
47
|
+
textAccentMuted: '#a78bfa',
|
|
48
|
+
|
|
49
|
+
// Border Colors (Semantic)
|
|
50
|
+
borderBase: '#d1d5db', // slate-300 - Standard Border
|
|
51
|
+
borderSubtle: '#e5e7eb', // slate-200 - Dezenter Border
|
|
52
|
+
borderMuted: '#f3f4f6' // slate-100 - Sehr dezenter Border
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
typography: {
|
|
56
|
+
fontFamily: {
|
|
57
|
+
heading: 'Inter, system-ui, -apple-system, sans-serif',
|
|
58
|
+
body: 'Inter, system-ui, -apple-system, sans-serif',
|
|
59
|
+
mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
60
|
+
accent: 'Inter, system-ui, -apple-system, sans-serif'
|
|
61
|
+
},
|
|
62
|
+
// Font References (IDs from Font table, null = use fontFamily string)
|
|
63
|
+
fontHeadingId: null,
|
|
64
|
+
fontBodyId: null,
|
|
65
|
+
fontMonoId: null,
|
|
66
|
+
fontAccentId: null,
|
|
67
|
+
// Base font size - Tailwind berechnet Skala automatisch
|
|
68
|
+
fontSizeBase: '1rem', // 16px base
|
|
69
|
+
// Base line height
|
|
70
|
+
lineHeightBase: '1.5',
|
|
71
|
+
// Base letter spacing
|
|
72
|
+
letterSpacingBase: '0em'
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Text Styles - Predefined typography combinations
|
|
76
|
+
textStyles: {
|
|
77
|
+
display: {
|
|
78
|
+
fontFamily: 'heading',
|
|
79
|
+
fontSize: {
|
|
80
|
+
base: '2.5rem', // 40px - Mobile
|
|
81
|
+
md: '3.5rem', // 56px - Tablet
|
|
82
|
+
lg: '4.5rem' // 72px - Desktop
|
|
83
|
+
},
|
|
84
|
+
fontWeight: 800,
|
|
85
|
+
lineHeight: '1.1',
|
|
86
|
+
letterSpacing: '-0.02em',
|
|
87
|
+
textTransform: 'none',
|
|
88
|
+
textColor: 'textBase'
|
|
89
|
+
},
|
|
90
|
+
heading1: {
|
|
91
|
+
fontFamily: 'heading',
|
|
92
|
+
fontSize: {
|
|
93
|
+
base: '2rem', // 32px - Mobile
|
|
94
|
+
md: '2.5rem', // 40px - Tablet
|
|
95
|
+
lg: '3rem' // 48px - Desktop
|
|
96
|
+
},
|
|
97
|
+
fontWeight: 700,
|
|
98
|
+
lineHeight: '1.2',
|
|
99
|
+
letterSpacing: '-0.015em',
|
|
100
|
+
textTransform: 'none',
|
|
101
|
+
textColor: 'textBase'
|
|
102
|
+
},
|
|
103
|
+
heading2: {
|
|
104
|
+
fontFamily: 'heading',
|
|
105
|
+
fontSize: {
|
|
106
|
+
base: '1.5rem', // 24px - Mobile
|
|
107
|
+
md: '1.875rem', // 30px - Tablet
|
|
108
|
+
lg: '2.25rem' // 36px - Desktop
|
|
109
|
+
},
|
|
110
|
+
fontWeight: 600,
|
|
111
|
+
lineHeight: '1.3',
|
|
112
|
+
letterSpacing: '-0.01em',
|
|
113
|
+
textTransform: 'none',
|
|
114
|
+
textColor: 'textBase'
|
|
115
|
+
},
|
|
116
|
+
heading3: {
|
|
117
|
+
fontFamily: 'heading',
|
|
118
|
+
fontSize: {
|
|
119
|
+
base: '1.25rem', // 20px - Mobile
|
|
120
|
+
lg: '1.5rem' // 24px - Desktop
|
|
121
|
+
},
|
|
122
|
+
fontWeight: 600,
|
|
123
|
+
lineHeight: '1.4',
|
|
124
|
+
letterSpacing: '0em',
|
|
125
|
+
textTransform: 'none',
|
|
126
|
+
textColor: 'textBase'
|
|
127
|
+
},
|
|
128
|
+
overlineDisplay: {
|
|
129
|
+
fontFamily: 'body',
|
|
130
|
+
fontSize: '1rem', // 16px
|
|
131
|
+
fontWeight: 600,
|
|
132
|
+
lineHeight: '1.5',
|
|
133
|
+
letterSpacing: '0.1em',
|
|
134
|
+
textTransform: 'uppercase',
|
|
135
|
+
textColor: 'textAccentBase'
|
|
136
|
+
},
|
|
137
|
+
overlineHeading1: {
|
|
138
|
+
fontFamily: 'body',
|
|
139
|
+
fontSize: '0.875rem', // 14px
|
|
140
|
+
fontWeight: 600,
|
|
141
|
+
lineHeight: '1.5',
|
|
142
|
+
letterSpacing: '0.1em',
|
|
143
|
+
textTransform: 'uppercase',
|
|
144
|
+
textColor: 'textAccentBase'
|
|
145
|
+
},
|
|
146
|
+
overlineHeading2: {
|
|
147
|
+
fontFamily: 'body',
|
|
148
|
+
fontSize: '0.75rem', // 12px
|
|
149
|
+
fontWeight: 600,
|
|
150
|
+
lineHeight: '1.5',
|
|
151
|
+
letterSpacing: '0.1em',
|
|
152
|
+
textTransform: 'uppercase',
|
|
153
|
+
textColor: 'textAccentSubtle'
|
|
154
|
+
},
|
|
155
|
+
overlineHeading3: {
|
|
156
|
+
fontFamily: 'body',
|
|
157
|
+
fontSize: '0.75rem', // 12px
|
|
158
|
+
fontWeight: 500,
|
|
159
|
+
lineHeight: '1.5',
|
|
160
|
+
letterSpacing: '0.08em',
|
|
161
|
+
textTransform: 'uppercase',
|
|
162
|
+
textColor: 'textAccentSubtle'
|
|
163
|
+
},
|
|
164
|
+
lead: {
|
|
165
|
+
fontFamily: 'body',
|
|
166
|
+
fontSize: '1.25rem', // 20px
|
|
167
|
+
fontWeight: 400,
|
|
168
|
+
lineHeight: '1.6',
|
|
169
|
+
letterSpacing: '0em',
|
|
170
|
+
textTransform: 'none',
|
|
171
|
+
textColor: 'textSubtle'
|
|
172
|
+
},
|
|
173
|
+
body: {
|
|
174
|
+
fontFamily: 'body',
|
|
175
|
+
fontSize: '1rem', // 16px
|
|
176
|
+
fontWeight: 400,
|
|
177
|
+
lineHeight: '1.6',
|
|
178
|
+
letterSpacing: '0em',
|
|
179
|
+
textTransform: 'none',
|
|
180
|
+
textColor: 'textSubtle'
|
|
181
|
+
},
|
|
182
|
+
bodySmall: {
|
|
183
|
+
fontFamily: 'body',
|
|
184
|
+
fontSize: '0.875rem', // 14px
|
|
185
|
+
fontWeight: 400,
|
|
186
|
+
lineHeight: '1.5',
|
|
187
|
+
letterSpacing: '0em',
|
|
188
|
+
textTransform: 'none',
|
|
189
|
+
textColor: 'textSubtle'
|
|
190
|
+
},
|
|
191
|
+
caption: {
|
|
192
|
+
fontFamily: 'body',
|
|
193
|
+
fontSize: '0.75rem', // 12px
|
|
194
|
+
fontWeight: 400,
|
|
195
|
+
lineHeight: '1.4',
|
|
196
|
+
letterSpacing: '0em',
|
|
197
|
+
textTransform: 'none',
|
|
198
|
+
textColor: 'textMuted'
|
|
199
|
+
},
|
|
200
|
+
label: {
|
|
201
|
+
fontFamily: 'body',
|
|
202
|
+
fontSize: '0.875rem', // 14px
|
|
203
|
+
fontWeight: 500,
|
|
204
|
+
lineHeight: '1.4',
|
|
205
|
+
letterSpacing: '0.01em',
|
|
206
|
+
textTransform: 'none',
|
|
207
|
+
textColor: 'textBase'
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
// Base spacing unit - Tailwind berechnet p-1, p-2, p-4 etc. automatisch
|
|
212
|
+
spacing: '0.25rem', // 4px base unit (Tailwind default)
|
|
213
|
+
|
|
214
|
+
// Base border width
|
|
215
|
+
borderWidth: '1px',
|
|
216
|
+
|
|
217
|
+
// Base border radius
|
|
218
|
+
borderRadius: '0.25rem', // 4px
|
|
219
|
+
|
|
220
|
+
// Container max widths (bleiben als Objekt, da spezifische Breakpoints)
|
|
221
|
+
container: {
|
|
222
|
+
sm: '640px',
|
|
223
|
+
md: '768px',
|
|
224
|
+
lg: '1024px',
|
|
225
|
+
xl: '1280px',
|
|
226
|
+
'2xl': '1536px'
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
// Breakpoints (bleiben als Objekt, da spezifische Werte)
|
|
230
|
+
breakpoints: {
|
|
231
|
+
sm: '640px',
|
|
232
|
+
md: '768px',
|
|
233
|
+
lg: '1024px',
|
|
234
|
+
xl: '1280px',
|
|
235
|
+
'2xl': '1536px'
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
// Buttons - Shared sizes and individual variants
|
|
239
|
+
buttons: {
|
|
240
|
+
sizes: {
|
|
241
|
+
small: {
|
|
242
|
+
paddingX: 12, // px
|
|
243
|
+
paddingY: 8, // px
|
|
244
|
+
fontSize: 14, // px
|
|
245
|
+
lineHeight: 20, // px
|
|
246
|
+
minHeight: 36, // px
|
|
247
|
+
borderRadius: 6, // px
|
|
248
|
+
borderWidth: 1, // px
|
|
249
|
+
gap: 8, // px (icon spacing)
|
|
250
|
+
iconSize: 16 // px (icon size)
|
|
251
|
+
},
|
|
252
|
+
medium: {
|
|
253
|
+
paddingX: 16, // px
|
|
254
|
+
paddingY: 10, // px
|
|
255
|
+
fontSize: 16, // px
|
|
256
|
+
lineHeight: 24, // px
|
|
257
|
+
minHeight: 44, // px
|
|
258
|
+
borderRadius: 8, // px
|
|
259
|
+
borderWidth: 1, // px
|
|
260
|
+
gap: 8, // px (icon spacing)
|
|
261
|
+
iconSize: 20 // px (icon size)
|
|
262
|
+
},
|
|
263
|
+
large: {
|
|
264
|
+
paddingX: 24, // px
|
|
265
|
+
paddingY: 12, // px
|
|
266
|
+
fontSize: 18, // px
|
|
267
|
+
lineHeight: 28, // px
|
|
268
|
+
minHeight: 52, // px
|
|
269
|
+
borderRadius: 8, // px
|
|
270
|
+
borderWidth: 2, // px
|
|
271
|
+
gap: 10, // px (icon spacing)
|
|
272
|
+
iconSize: 24 // px (icon size)
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
primary: {
|
|
276
|
+
bgColor: 'primary',
|
|
277
|
+
bgColorHover: 'primaryDark',
|
|
278
|
+
bgGradient: null, // null or { from: 'primary', to: 'primaryDark', direction: 'to-br' }
|
|
279
|
+
bgGradientHover: null,
|
|
280
|
+
textColor: 'white',
|
|
281
|
+
textColorHover: null, // null = same as textColor
|
|
282
|
+
borderColor: 'primary',
|
|
283
|
+
borderColorHover: 'primaryDark',
|
|
284
|
+
shadow: 'sm', // none, sm, md, lg, xl, 2xl
|
|
285
|
+
shadowHover: 'md',
|
|
286
|
+
shadowColor: null, // null = default shadow, or color token
|
|
287
|
+
backdropBlur: null, // null or px value (4, 8, 12, 16, 24)
|
|
288
|
+
backdropBlurHover: null,
|
|
289
|
+
opacity: 100, // 0-100
|
|
290
|
+
opacityHover: 100 // 0-100
|
|
291
|
+
},
|
|
292
|
+
secondary: {
|
|
293
|
+
bgColor: 'secondary',
|
|
294
|
+
bgColorHover: 'secondaryDark',
|
|
295
|
+
bgGradient: null,
|
|
296
|
+
bgGradientHover: null,
|
|
297
|
+
textColor: 'white',
|
|
298
|
+
textColorHover: null,
|
|
299
|
+
borderColor: 'secondary',
|
|
300
|
+
borderColorHover: 'secondaryDark',
|
|
301
|
+
shadow: 'sm',
|
|
302
|
+
shadowHover: 'md',
|
|
303
|
+
shadowColor: null,
|
|
304
|
+
backdropBlur: null,
|
|
305
|
+
backdropBlurHover: null,
|
|
306
|
+
opacity: 100,
|
|
307
|
+
opacityHover: 100
|
|
308
|
+
},
|
|
309
|
+
ghost: {
|
|
310
|
+
bgColor: 'transparent',
|
|
311
|
+
bgColorHover: 'bgElevated',
|
|
312
|
+
bgGradient: null,
|
|
313
|
+
bgGradientHover: null,
|
|
314
|
+
textColor: 'textBase',
|
|
315
|
+
textColorHover: null,
|
|
316
|
+
borderColor: 'transparent',
|
|
317
|
+
borderColorHover: 'transparent',
|
|
318
|
+
shadow: 'none',
|
|
319
|
+
shadowHover: 'none',
|
|
320
|
+
shadowColor: null,
|
|
321
|
+
backdropBlur: null,
|
|
322
|
+
backdropBlurHover: null,
|
|
323
|
+
opacity: 100,
|
|
324
|
+
opacityHover: 100
|
|
325
|
+
},
|
|
326
|
+
accent: {
|
|
327
|
+
bgColor: 'bgAccentBase',
|
|
328
|
+
bgColorHover: 'bgAccentElevated',
|
|
329
|
+
bgGradient: null,
|
|
330
|
+
bgGradientHover: null,
|
|
331
|
+
textColor: 'white',
|
|
332
|
+
textColorHover: null,
|
|
333
|
+
borderColor: 'bgAccentBase',
|
|
334
|
+
borderColorHover: 'bgAccentElevated',
|
|
335
|
+
shadow: 'md',
|
|
336
|
+
shadowHover: 'lg',
|
|
337
|
+
shadowColor: null,
|
|
338
|
+
backdropBlur: null,
|
|
339
|
+
backdropBlurHover: null,
|
|
340
|
+
opacity: 100,
|
|
341
|
+
opacityHover: 100
|
|
342
|
+
},
|
|
343
|
+
inverted: {
|
|
344
|
+
bgColor: 'white',
|
|
345
|
+
bgColorHover: 'bgElevated',
|
|
346
|
+
bgGradient: null,
|
|
347
|
+
bgGradientHover: null,
|
|
348
|
+
textColor: 'textBase',
|
|
349
|
+
textColorHover: null,
|
|
350
|
+
borderColor: 'white',
|
|
351
|
+
borderColorHover: 'bgElevated',
|
|
352
|
+
shadow: 'sm',
|
|
353
|
+
shadowHover: 'md',
|
|
354
|
+
shadowColor: null,
|
|
355
|
+
backdropBlur: null,
|
|
356
|
+
backdropBlurHover: null,
|
|
357
|
+
opacity: 100,
|
|
358
|
+
opacityHover: 100
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Generate Tailwind v4 @theme CSS from Design Tokens
|
|
365
|
+
*/
|
|
366
|
+
export function generateTailwindV4Theme(tokens) {
|
|
367
|
+
const lines = [];
|
|
368
|
+
|
|
369
|
+
// Colors - Map to Tailwind v4 CSS variables
|
|
370
|
+
if (tokens.colors) {
|
|
371
|
+
// Primary colors
|
|
372
|
+
if (tokens.colors.primary) lines.push(` --color-primary: ${tokens.colors.primary};`);
|
|
373
|
+
if (tokens.colors.primaryDark) lines.push(` --color-primary-dark: ${tokens.colors.primaryDark};`);
|
|
374
|
+
if (tokens.colors.primaryLight) lines.push(` --color-primary-light: ${tokens.colors.primaryLight};`);
|
|
375
|
+
|
|
376
|
+
// Secondary colors
|
|
377
|
+
if (tokens.colors.secondary) lines.push(` --color-secondary: ${tokens.colors.secondary};`);
|
|
378
|
+
if (tokens.colors.secondaryDark) lines.push(` --color-secondary-dark: ${tokens.colors.secondaryDark};`);
|
|
379
|
+
if (tokens.colors.secondaryLight) lines.push(` --color-secondary-light: ${tokens.colors.secondaryLight};`);
|
|
380
|
+
|
|
381
|
+
// Semantic colors
|
|
382
|
+
if (tokens.colors.success) lines.push(` --color-success: ${tokens.colors.success};`);
|
|
383
|
+
if (tokens.colors.successDark) lines.push(` --color-success-dark: ${tokens.colors.successDark};`);
|
|
384
|
+
if (tokens.colors.warning) lines.push(` --color-warning: ${tokens.colors.warning};`);
|
|
385
|
+
if (tokens.colors.warningDark) lines.push(` --color-warning-dark: ${tokens.colors.warningDark};`);
|
|
386
|
+
if (tokens.colors.error) lines.push(` --color-error: ${tokens.colors.error};`);
|
|
387
|
+
if (tokens.colors.errorDark) lines.push(` --color-error-dark: ${tokens.colors.errorDark};`);
|
|
388
|
+
if (tokens.colors.info) lines.push(` --color-info: ${tokens.colors.info};`);
|
|
389
|
+
if (tokens.colors.infoDark) lines.push(` --color-info-dark: ${tokens.colors.infoDark};`);
|
|
390
|
+
|
|
391
|
+
// Background colors (Semantic)
|
|
392
|
+
if (tokens.colors.bgBase) lines.push(` --color-bg-base: ${tokens.colors.bgBase};`);
|
|
393
|
+
if (tokens.colors.bgElevated) lines.push(` --color-bg-elevated: ${tokens.colors.bgElevated};`);
|
|
394
|
+
if (tokens.colors.bgLifted) lines.push(` --color-bg-lifted: ${tokens.colors.bgLifted};`);
|
|
395
|
+
if (tokens.colors.bgAccentBase) lines.push(` --color-bg-accent-base: ${tokens.colors.bgAccentBase};`);
|
|
396
|
+
if (tokens.colors.bgAccentElevated) lines.push(` --color-bg-accent-elevated: ${tokens.colors.bgAccentElevated};`);
|
|
397
|
+
if (tokens.colors.bgAccentLifted) lines.push(` --color-bg-accent-lifted: ${tokens.colors.bgAccentLifted};`);
|
|
398
|
+
|
|
399
|
+
// Text colors (Semantic)
|
|
400
|
+
if (tokens.colors.textBase) lines.push(` --color-text-base: ${tokens.colors.textBase};`);
|
|
401
|
+
if (tokens.colors.textSubtle) lines.push(` --color-text-subtle: ${tokens.colors.textSubtle};`);
|
|
402
|
+
if (tokens.colors.textMuted) lines.push(` --color-text-muted: ${tokens.colors.textMuted};`);
|
|
403
|
+
if (tokens.colors.textAccentBase) lines.push(` --color-text-accent-base: ${tokens.colors.textAccentBase};`);
|
|
404
|
+
if (tokens.colors.textAccentSubtle) lines.push(` --color-text-accent-subtle: ${tokens.colors.textAccentSubtle};`);
|
|
405
|
+
if (tokens.colors.textAccentMuted) lines.push(` --color-text-accent-muted: ${tokens.colors.textAccentMuted};`);
|
|
406
|
+
|
|
407
|
+
// Border colors (Semantic)
|
|
408
|
+
if (tokens.colors.borderBase) lines.push(` --color-border-base: ${tokens.colors.borderBase};`);
|
|
409
|
+
if (tokens.colors.borderSubtle) lines.push(` --color-border-subtle: ${tokens.colors.borderSubtle};`);
|
|
410
|
+
if (tokens.colors.borderMuted) lines.push(` --color-border-muted: ${tokens.colors.borderMuted};`);
|
|
411
|
+
|
|
412
|
+
// Basic colors
|
|
413
|
+
if (tokens.colors.white) lines.push(` --color-white: ${tokens.colors.white};`);
|
|
414
|
+
if (tokens.colors.black) lines.push(` --color-black: ${tokens.colors.black};`);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Typography - Font families
|
|
418
|
+
if (tokens.typography?.fontFamily) {
|
|
419
|
+
if (tokens.typography.fontFamily.heading) {
|
|
420
|
+
lines.push(` --font-heading: ${tokens.typography.fontFamily.heading};`);
|
|
421
|
+
}
|
|
422
|
+
if (tokens.typography.fontFamily.body) {
|
|
423
|
+
lines.push(` --font-body: ${tokens.typography.fontFamily.body};`);
|
|
424
|
+
}
|
|
425
|
+
if (tokens.typography.fontFamily.mono) {
|
|
426
|
+
lines.push(` --font-mono: ${tokens.typography.fontFamily.mono};`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Typography - Base values
|
|
431
|
+
if (tokens.typography?.fontSizeBase) {
|
|
432
|
+
lines.push(` --font-size: ${tokens.typography.fontSizeBase};`);
|
|
433
|
+
}
|
|
434
|
+
if (tokens.typography?.lineHeightBase) {
|
|
435
|
+
lines.push(` --line-height: ${tokens.typography.lineHeightBase};`);
|
|
436
|
+
}
|
|
437
|
+
if (tokens.typography?.letterSpacingBase) {
|
|
438
|
+
lines.push(` --letter-spacing: ${tokens.typography.letterSpacingBase};`);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Text Styles - Generate CSS variables for each style (with responsive support)
|
|
442
|
+
if (tokens.textStyles) {
|
|
443
|
+
for (const [styleName, style] of Object.entries(tokens.textStyles)) {
|
|
444
|
+
const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
445
|
+
|
|
446
|
+
// Font family (not responsive)
|
|
447
|
+
if (style.fontFamily) {
|
|
448
|
+
lines.push(` --text-${kebabName}-font-family: var(--font-${style.fontFamily});`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Font weight (not responsive)
|
|
452
|
+
if (style.fontWeight) {
|
|
453
|
+
lines.push(` --text-${kebabName}-font-weight: ${style.fontWeight};`);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Text transform (not responsive)
|
|
457
|
+
if (style.textTransform) {
|
|
458
|
+
lines.push(` --text-${kebabName}-text-transform: ${style.textTransform};`);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Font size (can be responsive)
|
|
462
|
+
if (style.fontSize) {
|
|
463
|
+
if (typeof style.fontSize === 'object') {
|
|
464
|
+
// Responsive: base value
|
|
465
|
+
if (style.fontSize.base) {
|
|
466
|
+
lines.push(` --text-${kebabName}-font-size: ${style.fontSize.base};`);
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
// Simple value
|
|
470
|
+
lines.push(` --text-${kebabName}-font-size: ${style.fontSize};`);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Line height (can be responsive)
|
|
475
|
+
if (style.lineHeight) {
|
|
476
|
+
if (typeof style.lineHeight === 'object') {
|
|
477
|
+
if (style.lineHeight.base) {
|
|
478
|
+
lines.push(` --text-${kebabName}-line-height: ${style.lineHeight.base};`);
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
lines.push(` --text-${kebabName}-line-height: ${style.lineHeight};`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Letter spacing (can be responsive)
|
|
486
|
+
if (style.letterSpacing) {
|
|
487
|
+
if (typeof style.letterSpacing === 'object') {
|
|
488
|
+
if (style.letterSpacing.base) {
|
|
489
|
+
lines.push(` --text-${kebabName}-letter-spacing: ${style.letterSpacing.base};`);
|
|
490
|
+
}
|
|
491
|
+
} else {
|
|
492
|
+
lines.push(` --text-${kebabName}-letter-spacing: ${style.letterSpacing};`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Spacing base
|
|
499
|
+
if (tokens.spacing) {
|
|
500
|
+
lines.push(` --spacing: ${tokens.spacing};`);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Border width base
|
|
504
|
+
if (tokens.borderWidth) {
|
|
505
|
+
lines.push(` --border-width: ${tokens.borderWidth};`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Border radius base
|
|
509
|
+
if (tokens.borderRadius) {
|
|
510
|
+
lines.push(` --radius: ${tokens.borderRadius};`);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Container widths (specific breakpoints)
|
|
514
|
+
if (tokens.container) {
|
|
515
|
+
for (const [key, value] of Object.entries(tokens.container)) {
|
|
516
|
+
lines.push(` --container-${key}: ${value};`);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Breakpoints
|
|
521
|
+
if (tokens.breakpoints) {
|
|
522
|
+
for (const [key, value] of Object.entries(tokens.breakpoints)) {
|
|
523
|
+
lines.push(` --breakpoint-${key}: ${value};`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Buttons - Sizes
|
|
528
|
+
if (tokens.buttons?.sizes) {
|
|
529
|
+
for (const [sizeName, sizeProps] of Object.entries(tokens.buttons.sizes)) {
|
|
530
|
+
const prefix = `button-${sizeName}`;
|
|
531
|
+
if (sizeProps.paddingX) lines.push(` --${prefix}-padding-x: ${sizeProps.paddingX};`);
|
|
532
|
+
if (sizeProps.paddingY) lines.push(` --${prefix}-padding-y: ${sizeProps.paddingY};`);
|
|
533
|
+
if (sizeProps.fontSize) lines.push(` --${prefix}-font-size: ${sizeProps.fontSize};`);
|
|
534
|
+
if (sizeProps.lineHeight) lines.push(` --${prefix}-line-height: ${sizeProps.lineHeight};`);
|
|
535
|
+
if (sizeProps.borderRadius) lines.push(` --${prefix}-border-radius: ${sizeProps.borderRadius};`);
|
|
536
|
+
if (sizeProps.gap) lines.push(` --${prefix}-gap: ${sizeProps.gap};`);
|
|
537
|
+
if (sizeProps.iconSize) lines.push(` --${prefix}-icon-size: ${sizeProps.iconSize};`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Buttons - Variants
|
|
542
|
+
if (tokens.buttons) {
|
|
543
|
+
const variants = Object.keys(tokens.buttons).filter(key => key !== 'sizes');
|
|
544
|
+
for (const variantName of variants) {
|
|
545
|
+
const variant = tokens.buttons[variantName];
|
|
546
|
+
const prefix = `button-${variantName}`;
|
|
547
|
+
|
|
548
|
+
if (variant.bgColor) {
|
|
549
|
+
const colorVar = tokens.colors[variant.bgColor] || variant.bgColor;
|
|
550
|
+
lines.push(` --${prefix}-bg: ${colorVar};`);
|
|
551
|
+
}
|
|
552
|
+
if (variant.bgColorHover) {
|
|
553
|
+
const colorVar = tokens.colors[variant.bgColorHover] || variant.bgColorHover;
|
|
554
|
+
lines.push(` --${prefix}-bg-hover: ${colorVar};`);
|
|
555
|
+
}
|
|
556
|
+
if (variant.textColor) {
|
|
557
|
+
const colorVar = tokens.colors[variant.textColor] || variant.textColor;
|
|
558
|
+
lines.push(` --${prefix}-text: ${colorVar};`);
|
|
559
|
+
}
|
|
560
|
+
if (variant.borderColor) {
|
|
561
|
+
const colorVar = tokens.colors[variant.borderColor] || variant.borderColor;
|
|
562
|
+
lines.push(` --${prefix}-border: ${colorVar};`);
|
|
563
|
+
}
|
|
564
|
+
if (variant.borderColorHover) {
|
|
565
|
+
const colorVar = tokens.colors[variant.borderColorHover] || variant.borderColorHover;
|
|
566
|
+
lines.push(` --${prefix}-border-hover: ${colorVar};`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const themeVars = lines.join('\n');
|
|
572
|
+
|
|
573
|
+
// Global styles (MUST be outside @theme block)
|
|
574
|
+
let globalStyles = `
|
|
575
|
+
/* Global baseline font */
|
|
576
|
+
body {
|
|
577
|
+
font-family: var(--font-body);
|
|
578
|
+
}`;
|
|
579
|
+
|
|
580
|
+
// Generate utility classes for text styles
|
|
581
|
+
if (tokens.textStyles) {
|
|
582
|
+
globalStyles += '\n\n/* Text Style Utilities */';
|
|
583
|
+
for (const [styleName, style] of Object.entries(tokens.textStyles)) {
|
|
584
|
+
const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
585
|
+
const className = `text-${kebabName}`;
|
|
586
|
+
|
|
587
|
+
globalStyles += `\n.${className} {`;
|
|
588
|
+
if (style.fontFamily) {
|
|
589
|
+
globalStyles += `\n font-family: var(--text-${kebabName}-font-family);`;
|
|
590
|
+
}
|
|
591
|
+
if (style.fontWeight) {
|
|
592
|
+
globalStyles += `\n font-weight: var(--text-${kebabName}-font-weight);`;
|
|
593
|
+
}
|
|
594
|
+
if (style.fontSize) {
|
|
595
|
+
globalStyles += `\n font-size: var(--text-${kebabName}-font-size);`;
|
|
596
|
+
}
|
|
597
|
+
if (style.lineHeight) {
|
|
598
|
+
globalStyles += `\n line-height: var(--text-${kebabName}-line-height);`;
|
|
599
|
+
}
|
|
600
|
+
if (style.letterSpacing) {
|
|
601
|
+
globalStyles += `\n letter-spacing: var(--text-${kebabName}-letter-spacing);`;
|
|
602
|
+
}
|
|
603
|
+
if (style.textTransform) {
|
|
604
|
+
globalStyles += `\n text-transform: var(--text-${kebabName}-text-transform);`;
|
|
605
|
+
}
|
|
606
|
+
globalStyles += `\n}`;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Generate utility classes for buttons
|
|
611
|
+
if (tokens.buttons) {
|
|
612
|
+
globalStyles += '\n\n/* Button Utilities */';
|
|
613
|
+
|
|
614
|
+
// Base button class
|
|
615
|
+
globalStyles += `\n.btn {
|
|
616
|
+
display: inline-flex;
|
|
617
|
+
align-items: center;
|
|
618
|
+
justify-content: center;
|
|
619
|
+
font-weight: 500;
|
|
620
|
+
border-width: 1px;
|
|
621
|
+
border-style: solid;
|
|
622
|
+
transition: all 0.15s ease-in-out;
|
|
623
|
+
cursor: pointer;
|
|
624
|
+
text-decoration: none;
|
|
625
|
+
}`;
|
|
626
|
+
|
|
627
|
+
// Size classes
|
|
628
|
+
if (tokens.buttons.sizes) {
|
|
629
|
+
for (const sizeName of Object.keys(tokens.buttons.sizes)) {
|
|
630
|
+
globalStyles += `\n.btn-${sizeName} {
|
|
631
|
+
padding: var(--button-${sizeName}-padding-y) var(--button-${sizeName}-padding-x);
|
|
632
|
+
font-size: var(--button-${sizeName}-font-size);
|
|
633
|
+
line-height: var(--button-${sizeName}-line-height);
|
|
634
|
+
border-radius: var(--button-${sizeName}-border-radius);
|
|
635
|
+
gap: var(--button-${sizeName}-gap);
|
|
636
|
+
}`;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Variant classes
|
|
641
|
+
const variants = Object.keys(tokens.buttons).filter(key => key !== 'sizes');
|
|
642
|
+
for (const variantName of variants) {
|
|
643
|
+
globalStyles += `\n.btn-${variantName} {
|
|
644
|
+
background-color: var(--button-${variantName}-bg);
|
|
645
|
+
color: var(--button-${variantName}-text);
|
|
646
|
+
border-color: var(--button-${variantName}-border);
|
|
647
|
+
}
|
|
648
|
+
.btn-${variantName}:hover {
|
|
649
|
+
background-color: var(--button-${variantName}-bg-hover);
|
|
650
|
+
border-color: var(--button-${variantName}-border-hover);
|
|
651
|
+
}`;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Add responsive media queries for textStyles (OUTSIDE @theme block!)
|
|
656
|
+
if (tokens.textStyles) {
|
|
657
|
+
const breakpointKeys = ['sm', 'md', 'lg', 'xl', '2xl'];
|
|
658
|
+
const breakpointValues = {
|
|
659
|
+
sm: '640px',
|
|
660
|
+
md: '768px',
|
|
661
|
+
lg: '1024px',
|
|
662
|
+
xl: '1280px',
|
|
663
|
+
'2xl': '1536px'
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
for (const bp of breakpointKeys) {
|
|
667
|
+
const mediaQueryLines = [];
|
|
668
|
+
|
|
669
|
+
for (const [styleName, style] of Object.entries(tokens.textStyles)) {
|
|
670
|
+
const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
671
|
+
|
|
672
|
+
// Font size
|
|
673
|
+
if (style.fontSize && typeof style.fontSize === 'object' && style.fontSize[bp]) {
|
|
674
|
+
mediaQueryLines.push(` --text-${kebabName}-font-size: ${style.fontSize[bp]};`);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Line height
|
|
678
|
+
if (style.lineHeight && typeof style.lineHeight === 'object' && style.lineHeight[bp]) {
|
|
679
|
+
mediaQueryLines.push(` --text-${kebabName}-line-height: ${style.lineHeight[bp]};`);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Letter spacing
|
|
683
|
+
if (style.letterSpacing && typeof style.letterSpacing === 'object' && style.letterSpacing[bp]) {
|
|
684
|
+
mediaQueryLines.push(` --text-${kebabName}-letter-spacing: ${style.letterSpacing[bp]};`);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (mediaQueryLines.length > 0) {
|
|
689
|
+
globalStyles += `\n\n@media (min-width: ${breakpointValues[bp]}) {\n :root {\n`;
|
|
690
|
+
globalStyles += mediaQueryLines.join('\n');
|
|
691
|
+
globalStyles += '\n }\n}';
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
return { themeVars, globalStyles };
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Generate Tailwind Config from Design Tokens (for Tailwind v3 - legacy)
|
|
701
|
+
*/
|
|
702
|
+
export function generateTailwindConfig(tokens) {
|
|
703
|
+
return {
|
|
704
|
+
theme: {
|
|
705
|
+
extend: {
|
|
706
|
+
colors: {
|
|
707
|
+
// Brand colors
|
|
708
|
+
primary: {
|
|
709
|
+
DEFAULT: tokens.colors?.primary || '#ea580c',
|
|
710
|
+
dark: tokens.colors?.primaryDark || '#c2410c',
|
|
711
|
+
light: tokens.colors?.primaryLight || '#fb923c'
|
|
712
|
+
},
|
|
713
|
+
secondary: {
|
|
714
|
+
DEFAULT: tokens.colors?.secondary || '#6366f1',
|
|
715
|
+
dark: tokens.colors?.secondaryDark || '#4f46e5',
|
|
716
|
+
light: tokens.colors?.secondaryLight || '#818cf8'
|
|
717
|
+
},
|
|
718
|
+
// Semantic colors
|
|
719
|
+
success: {
|
|
720
|
+
DEFAULT: tokens.colors?.success || '#10b981',
|
|
721
|
+
dark: tokens.colors?.successDark || '#059669'
|
|
722
|
+
},
|
|
723
|
+
warning: {
|
|
724
|
+
DEFAULT: tokens.colors?.warning || '#f59e0b',
|
|
725
|
+
dark: tokens.colors?.warningDark || '#d97706'
|
|
726
|
+
},
|
|
727
|
+
error: {
|
|
728
|
+
DEFAULT: tokens.colors?.error || '#ef4444',
|
|
729
|
+
dark: tokens.colors?.errorDark || '#dc2626'
|
|
730
|
+
},
|
|
731
|
+
info: {
|
|
732
|
+
DEFAULT: tokens.colors?.info || '#3b82f6',
|
|
733
|
+
dark: tokens.colors?.infoDark || '#2563eb'
|
|
734
|
+
}
|
|
735
|
+
},
|
|
736
|
+
fontFamily: {
|
|
737
|
+
heading: tokens.typography?.fontFamily?.heading?.split(',') || ['Inter', 'system-ui', 'sans-serif'],
|
|
738
|
+
body: tokens.typography?.fontFamily?.body?.split(',') || ['Inter', 'system-ui', 'sans-serif'],
|
|
739
|
+
mono: tokens.typography?.fontFamily?.mono?.split(',') || ['ui-monospace', 'monospace']
|
|
740
|
+
},
|
|
741
|
+
fontSize: tokens.typography?.fontSize || {},
|
|
742
|
+
fontWeight: tokens.typography?.fontWeight || {},
|
|
743
|
+
lineHeight: tokens.typography?.lineHeight || {},
|
|
744
|
+
letterSpacing: tokens.typography?.letterSpacing || {},
|
|
745
|
+
spacing: tokens.spacing || {},
|
|
746
|
+
borderRadius: tokens.borderRadius || {},
|
|
747
|
+
boxShadow: tokens.boxShadow || {},
|
|
748
|
+
maxWidth: tokens.container || {}
|
|
749
|
+
}
|
|
750
|
+
},
|
|
751
|
+
safelist: [
|
|
752
|
+
// Brand colors
|
|
753
|
+
'bg-primary', 'bg-primary-dark', 'bg-primary-light',
|
|
754
|
+
'bg-secondary', 'bg-secondary-dark', 'bg-secondary-light',
|
|
755
|
+
'text-primary', 'text-primary-dark', 'text-primary-light',
|
|
756
|
+
'text-secondary', 'text-secondary-dark', 'text-secondary-light',
|
|
757
|
+
'border-primary', 'border-secondary',
|
|
758
|
+
// Semantic colors
|
|
759
|
+
'bg-success', 'bg-warning', 'bg-error', 'bg-info',
|
|
760
|
+
'text-success', 'text-warning', 'text-error', 'text-info',
|
|
761
|
+
// Background tokens
|
|
762
|
+
'bg-base', 'bg-elevated', 'bg-lifted',
|
|
763
|
+
'bg-accent-base', 'bg-accent-elevated', 'bg-accent-lifted',
|
|
764
|
+
// Text tokens
|
|
765
|
+
'text-base', 'text-subtle', 'text-muted',
|
|
766
|
+
'text-accent-base', 'text-accent-subtle', 'text-accent-muted',
|
|
767
|
+
// Text styles
|
|
768
|
+
'text-display', 'text-heading-1', 'text-heading-2', 'text-heading-3',
|
|
769
|
+
'text-overline-display', 'text-overline-heading-1', 'text-overline-heading-2', 'text-overline-heading-3',
|
|
770
|
+
'text-lead', 'text-body', 'text-body-small',
|
|
771
|
+
'text-caption', 'text-label'
|
|
772
|
+
]
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Generate CSS Variables from Design Tokens
|
|
778
|
+
*/
|
|
779
|
+
export function generateCSSFromTokens(tokens) {
|
|
780
|
+
const lines = [':root {'];
|
|
781
|
+
|
|
782
|
+
// Colors
|
|
783
|
+
for (const [key, value] of Object.entries(tokens.colors || {})) {
|
|
784
|
+
const cssVarName = `--color-${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
|
|
785
|
+
lines.push(` ${cssVarName}: ${value};`);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Typography - Font Families
|
|
789
|
+
for (const [key, value] of Object.entries(tokens.typography?.fontFamily || {})) {
|
|
790
|
+
lines.push(` --font-${key}: ${value};`);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Typography - Font Sizes
|
|
794
|
+
for (const [key, value] of Object.entries(tokens.typography?.fontSize || {})) {
|
|
795
|
+
lines.push(` --text-${key}: ${value};`);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// Typography - Font Weights
|
|
799
|
+
for (const [key, value] of Object.entries(tokens.typography?.fontWeight || {})) {
|
|
800
|
+
lines.push(` --font-${key}: ${value};`);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Typography - Line Heights
|
|
804
|
+
for (const [key, value] of Object.entries(tokens.typography?.lineHeight || {})) {
|
|
805
|
+
lines.push(` --leading-${key}: ${value};`);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Typography - Letter Spacing
|
|
809
|
+
for (const [key, value] of Object.entries(tokens.typography?.letterSpacing || {})) {
|
|
810
|
+
lines.push(` --tracking-${key}: ${value};`);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Spacing
|
|
814
|
+
if (typeof tokens.spacing === 'object' && tokens.spacing !== null) {
|
|
815
|
+
// Object format: { '0': '0', '1': '0.25rem', '2': '0.5rem', ... }
|
|
816
|
+
for (const [key, value] of Object.entries(tokens.spacing)) {
|
|
817
|
+
lines.push(` --spacing-${key.replace('.', '-')}: ${value};`);
|
|
818
|
+
}
|
|
819
|
+
} else if (typeof tokens.spacing === 'string') {
|
|
820
|
+
// String format (base unit): '0.25rem' - Tailwind v4 will auto-generate scale
|
|
821
|
+
// Output base spacing variable for Tailwind v4
|
|
822
|
+
lines.push(` --spacing: ${tokens.spacing};`);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Container
|
|
826
|
+
for (const [key, value] of Object.entries(tokens.container || {})) {
|
|
827
|
+
lines.push(` --container-${key}: ${value};`);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// Border Width
|
|
831
|
+
if (typeof tokens.borderWidth === 'object' && tokens.borderWidth !== null) {
|
|
832
|
+
for (const [key, value] of Object.entries(tokens.borderWidth)) {
|
|
833
|
+
const varName = key === 'DEFAULT' ? '--border-width' : `--border-width-${key}`;
|
|
834
|
+
lines.push(` ${varName}: ${value};`);
|
|
835
|
+
}
|
|
836
|
+
} else if (typeof tokens.borderWidth === 'string') {
|
|
837
|
+
lines.push(` --border-width: ${tokens.borderWidth};`);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Border Radius
|
|
841
|
+
if (typeof tokens.borderRadius === 'object' && tokens.borderRadius !== null) {
|
|
842
|
+
for (const [key, value] of Object.entries(tokens.borderRadius)) {
|
|
843
|
+
const varName = key === 'DEFAULT' ? '--radius' : `--radius-${key}`;
|
|
844
|
+
lines.push(` ${varName}: ${value};`);
|
|
845
|
+
}
|
|
846
|
+
} else if (typeof tokens.borderRadius === 'string') {
|
|
847
|
+
lines.push(` --radius: ${tokens.borderRadius};`);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Box Shadow
|
|
851
|
+
for (const [key, value] of Object.entries(tokens.boxShadow || {})) {
|
|
852
|
+
const varName = key === 'DEFAULT' ? '--shadow' : `--shadow-${key}`;
|
|
853
|
+
lines.push(` ${varName}: ${value};`);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
lines.push('}');
|
|
857
|
+
|
|
858
|
+
// Add global body font-family as baseline
|
|
859
|
+
lines.push('');
|
|
860
|
+
lines.push('/* Global baseline font */');
|
|
861
|
+
lines.push('body {');
|
|
862
|
+
lines.push(' font-family: var(--font-body);');
|
|
863
|
+
lines.push('}');
|
|
864
|
+
|
|
865
|
+
// Generate utility classes for text styles
|
|
866
|
+
if (tokens.textStyles) {
|
|
867
|
+
lines.push('');
|
|
868
|
+
lines.push('/* Text Style Utilities */');
|
|
869
|
+
for (const [styleName, style] of Object.entries(tokens.textStyles)) {
|
|
870
|
+
const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
871
|
+
const className = `text-${kebabName}`;
|
|
872
|
+
|
|
873
|
+
lines.push(`.${className} {`);
|
|
874
|
+
if (style.fontFamily) {
|
|
875
|
+
const fontVar = `--font-${style.fontFamily}`;
|
|
876
|
+
lines.push(` font-family: var(${fontVar});`);
|
|
877
|
+
}
|
|
878
|
+
if (style.fontWeight) {
|
|
879
|
+
lines.push(` font-weight: ${style.fontWeight};`);
|
|
880
|
+
}
|
|
881
|
+
if (style.fontSize) {
|
|
882
|
+
const fontSize = typeof style.fontSize === 'object' ? style.fontSize.base : style.fontSize;
|
|
883
|
+
lines.push(` font-size: ${fontSize};`);
|
|
884
|
+
}
|
|
885
|
+
if (style.lineHeight) {
|
|
886
|
+
const lineHeight = typeof style.lineHeight === 'object' ? style.lineHeight.base : style.lineHeight;
|
|
887
|
+
lines.push(` line-height: ${lineHeight};`);
|
|
888
|
+
}
|
|
889
|
+
if (style.letterSpacing) {
|
|
890
|
+
const letterSpacing = typeof style.letterSpacing === 'object' ? style.letterSpacing.base : style.letterSpacing;
|
|
891
|
+
lines.push(` letter-spacing: ${letterSpacing};`);
|
|
892
|
+
}
|
|
893
|
+
if (style.textTransform) {
|
|
894
|
+
lines.push(` text-transform: ${style.textTransform};`);
|
|
895
|
+
}
|
|
896
|
+
if (style.textColor) {
|
|
897
|
+
const colorVar = `--color-${style.textColor.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
|
|
898
|
+
lines.push(` color: var(${colorVar});`);
|
|
899
|
+
}
|
|
900
|
+
lines.push('}');
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// Add responsive media queries for textStyles
|
|
904
|
+
const breakpointKeys = ['md', 'lg', 'xl', '2xl'];
|
|
905
|
+
const breakpointValues = {
|
|
906
|
+
md: '768px',
|
|
907
|
+
lg: '1024px',
|
|
908
|
+
xl: '1280px',
|
|
909
|
+
'2xl': '1536px'
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
for (const bp of breakpointKeys) {
|
|
913
|
+
const mediaQueryLines = [];
|
|
914
|
+
|
|
915
|
+
for (const [styleName, style] of Object.entries(tokens.textStyles)) {
|
|
916
|
+
const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
917
|
+
const className = `text-${kebabName}`;
|
|
918
|
+
const hasResponsive = (
|
|
919
|
+
(style.fontSize && typeof style.fontSize === 'object' && style.fontSize[bp]) ||
|
|
920
|
+
(style.lineHeight && typeof style.lineHeight === 'object' && style.lineHeight[bp]) ||
|
|
921
|
+
(style.letterSpacing && typeof style.letterSpacing === 'object' && style.letterSpacing[bp])
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
if (hasResponsive) {
|
|
925
|
+
mediaQueryLines.push(` .${className} {`);
|
|
926
|
+
if (style.fontSize && typeof style.fontSize === 'object' && style.fontSize[bp]) {
|
|
927
|
+
mediaQueryLines.push(` font-size: ${style.fontSize[bp]};`);
|
|
928
|
+
}
|
|
929
|
+
if (style.lineHeight && typeof style.lineHeight === 'object' && style.lineHeight[bp]) {
|
|
930
|
+
mediaQueryLines.push(` line-height: ${style.lineHeight[bp]};`);
|
|
931
|
+
}
|
|
932
|
+
if (style.letterSpacing && typeof style.letterSpacing === 'object' && style.letterSpacing[bp]) {
|
|
933
|
+
mediaQueryLines.push(` letter-spacing: ${style.letterSpacing[bp]};`);
|
|
934
|
+
}
|
|
935
|
+
mediaQueryLines.push(` }`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (mediaQueryLines.length > 0) {
|
|
940
|
+
lines.push('');
|
|
941
|
+
lines.push(`@media (min-width: ${breakpointValues[bp]}) {`);
|
|
942
|
+
lines.push(...mediaQueryLines);
|
|
943
|
+
lines.push('}');
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Generate button utility classes
|
|
949
|
+
if (tokens.buttons) {
|
|
950
|
+
lines.push('');
|
|
951
|
+
lines.push('/* Button Utilities */');
|
|
952
|
+
|
|
953
|
+
// Helper to convert hex to rgba with opacity
|
|
954
|
+
const hexToRgba = (hex, alpha) => {
|
|
955
|
+
if (!hex || hex === 'transparent') return 'transparent';
|
|
956
|
+
hex = hex.replace('#', '');
|
|
957
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
958
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
959
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
960
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
// Shadow presets
|
|
964
|
+
const shadowPresets = {
|
|
965
|
+
none: 'none',
|
|
966
|
+
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
967
|
+
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
968
|
+
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
969
|
+
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
970
|
+
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
// Gradient direction mapping
|
|
974
|
+
const directionMap = {
|
|
975
|
+
'to-t': 'to top',
|
|
976
|
+
'to-tr': 'to top right',
|
|
977
|
+
'to-r': 'to right',
|
|
978
|
+
'to-br': 'to bottom right',
|
|
979
|
+
'to-b': 'to bottom',
|
|
980
|
+
'to-bl': 'to bottom left',
|
|
981
|
+
'to-l': 'to left',
|
|
982
|
+
'to-tl': 'to top left'
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// Base button class
|
|
986
|
+
lines.push('.btn {');
|
|
987
|
+
lines.push(' display: inline-flex;');
|
|
988
|
+
lines.push(' align-items: center;');
|
|
989
|
+
lines.push(' justify-content: center;');
|
|
990
|
+
lines.push(' font-weight: 500;');
|
|
991
|
+
lines.push(' border-style: solid;');
|
|
992
|
+
lines.push(' transition: all 0.15s ease-in-out;');
|
|
993
|
+
lines.push(' cursor: pointer;');
|
|
994
|
+
lines.push(' text-decoration: none;');
|
|
995
|
+
lines.push('}');
|
|
996
|
+
|
|
997
|
+
// Size classes with direct values
|
|
998
|
+
if (tokens.buttons.sizes) {
|
|
999
|
+
for (const [sizeName, size] of Object.entries(tokens.buttons.sizes)) {
|
|
1000
|
+
lines.push(`.btn-${sizeName} {`);
|
|
1001
|
+
lines.push(` padding: ${size.paddingY}px ${size.paddingX}px;`);
|
|
1002
|
+
lines.push(` font-size: ${size.fontSize}px;`);
|
|
1003
|
+
lines.push(` line-height: ${size.lineHeight}px;`);
|
|
1004
|
+
lines.push(` min-height: ${size.minHeight}px;`);
|
|
1005
|
+
lines.push(` border-radius: ${size.borderRadius}px;`);
|
|
1006
|
+
lines.push(` border-width: ${size.borderWidth}px;`);
|
|
1007
|
+
lines.push(` gap: ${size.gap}px;`);
|
|
1008
|
+
lines.push('}');
|
|
1009
|
+
|
|
1010
|
+
// Icon size
|
|
1011
|
+
lines.push(`.btn-${sizeName} iconify-icon {`);
|
|
1012
|
+
lines.push(` font-size: ${size.iconSize}px;`);
|
|
1013
|
+
lines.push('}');
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// Variant classes with gradients, opacity, shadows
|
|
1018
|
+
const variants = Object.keys(tokens.buttons).filter(key => key !== 'sizes');
|
|
1019
|
+
for (const variantName of variants) {
|
|
1020
|
+
const variant = tokens.buttons[variantName];
|
|
1021
|
+
|
|
1022
|
+
const bgColor = tokens.colors[variant.bgColor] || variant.bgColor;
|
|
1023
|
+
const textColor = tokens.colors[variant.textColor] || variant.textColor;
|
|
1024
|
+
const borderColor = tokens.colors[variant.borderColor] || variant.borderColor;
|
|
1025
|
+
const opacity = (variant.opacity || 100) / 100;
|
|
1026
|
+
|
|
1027
|
+
lines.push(`.btn-${variantName} {`);
|
|
1028
|
+
|
|
1029
|
+
// Background with opacity and gradient support
|
|
1030
|
+
if (variant.bgGradient) {
|
|
1031
|
+
const fromColor = tokens.colors[variant.bgGradient.from] || variant.bgGradient.from;
|
|
1032
|
+
const toColor = tokens.colors[variant.bgGradient.to] || variant.bgGradient.to;
|
|
1033
|
+
const direction = directionMap[variant.bgGradient.direction] || 'to bottom right';
|
|
1034
|
+
const fromRgba = hexToRgba(fromColor, opacity);
|
|
1035
|
+
const toRgba = hexToRgba(toColor, opacity);
|
|
1036
|
+
lines.push(` background: linear-gradient(${direction}, ${fromRgba}, ${toRgba});`);
|
|
1037
|
+
} else {
|
|
1038
|
+
lines.push(` background-color: ${hexToRgba(bgColor, opacity)};`);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
lines.push(` color: ${textColor};`);
|
|
1042
|
+
lines.push(` border-color: ${borderColor};`);
|
|
1043
|
+
|
|
1044
|
+
// Shadow
|
|
1045
|
+
if (variant.shadow && variant.shadow !== 'none') {
|
|
1046
|
+
lines.push(` box-shadow: ${shadowPresets[variant.shadow]};`);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
// Backdrop blur
|
|
1050
|
+
if (variant.backdropBlur) {
|
|
1051
|
+
lines.push(` backdrop-filter: blur(${variant.backdropBlur}px);`);
|
|
1052
|
+
lines.push(` -webkit-backdrop-filter: blur(${variant.backdropBlur}px);`);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
lines.push('}');
|
|
1056
|
+
|
|
1057
|
+
// Hover state
|
|
1058
|
+
const bgColorHover = variant.bgColorHover ? (tokens.colors[variant.bgColorHover] || variant.bgColorHover) : bgColor;
|
|
1059
|
+
const textColorHover = variant.textColorHover ? (tokens.colors[variant.textColorHover] || variant.textColorHover) : textColor;
|
|
1060
|
+
const borderColorHover = variant.borderColorHover ? (tokens.colors[variant.borderColorHover] || variant.borderColorHover) : borderColor;
|
|
1061
|
+
const opacityHover = (variant.opacityHover !== undefined ? variant.opacityHover : (variant.opacity || 100)) / 100;
|
|
1062
|
+
|
|
1063
|
+
lines.push(`.btn-${variantName}:hover {`);
|
|
1064
|
+
|
|
1065
|
+
// Hover background with opacity and gradient support
|
|
1066
|
+
if (variant.bgGradientHover) {
|
|
1067
|
+
const fromColor = tokens.colors[variant.bgGradientHover.from] || variant.bgGradientHover.from;
|
|
1068
|
+
const toColor = tokens.colors[variant.bgGradientHover.to] || variant.bgGradientHover.to;
|
|
1069
|
+
const direction = directionMap[variant.bgGradientHover.direction] || 'to bottom right';
|
|
1070
|
+
const fromRgba = hexToRgba(fromColor, opacityHover);
|
|
1071
|
+
const toRgba = hexToRgba(toColor, opacityHover);
|
|
1072
|
+
lines.push(` background: linear-gradient(${direction}, ${fromRgba}, ${toRgba});`);
|
|
1073
|
+
} else if (variant.bgGradient && !variant.bgColorHover) {
|
|
1074
|
+
// Keep gradient on hover if no hover color specified
|
|
1075
|
+
const fromColor = tokens.colors[variant.bgGradient.from] || variant.bgGradient.from;
|
|
1076
|
+
const toColor = tokens.colors[variant.bgGradient.to] || variant.bgGradient.to;
|
|
1077
|
+
const direction = directionMap[variant.bgGradient.direction] || 'to bottom right';
|
|
1078
|
+
const fromRgba = hexToRgba(fromColor, opacityHover);
|
|
1079
|
+
const toRgba = hexToRgba(toColor, opacityHover);
|
|
1080
|
+
lines.push(` background: linear-gradient(${direction}, ${fromRgba}, ${toRgba});`);
|
|
1081
|
+
} else {
|
|
1082
|
+
lines.push(` background-color: ${hexToRgba(bgColorHover, opacityHover)};`);
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
if (variant.textColorHover) {
|
|
1086
|
+
lines.push(` color: ${textColorHover};`);
|
|
1087
|
+
}
|
|
1088
|
+
lines.push(` border-color: ${borderColorHover};`);
|
|
1089
|
+
|
|
1090
|
+
// Hover shadow
|
|
1091
|
+
if (variant.shadowHover && variant.shadowHover !== 'none') {
|
|
1092
|
+
lines.push(` box-shadow: ${shadowPresets[variant.shadowHover]};`);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Hover backdrop blur
|
|
1096
|
+
if (variant.backdropBlurHover !== undefined && variant.backdropBlurHover !== null) {
|
|
1097
|
+
if (variant.backdropBlurHover === 0) {
|
|
1098
|
+
lines.push(` backdrop-filter: none;`);
|
|
1099
|
+
lines.push(` -webkit-backdrop-filter: none;`);
|
|
1100
|
+
} else {
|
|
1101
|
+
lines.push(` backdrop-filter: blur(${variant.backdropBlurHover}px);`);
|
|
1102
|
+
lines.push(` -webkit-backdrop-filter: blur(${variant.backdropBlurHover}px);`);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
lines.push('}');
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// Generate utility classes for semantic colors
|
|
1111
|
+
if (tokens.colors) {
|
|
1112
|
+
lines.push('');
|
|
1113
|
+
lines.push('/* Semantic Color Utilities */');
|
|
1114
|
+
|
|
1115
|
+
// Background colors
|
|
1116
|
+
const bgColors = [
|
|
1117
|
+
'bgBase', 'bgElevated', 'bgLifted',
|
|
1118
|
+
'bgAccentBase', 'bgAccentElevated', 'bgAccentLifted'
|
|
1119
|
+
];
|
|
1120
|
+
for (const colorKey of bgColors) {
|
|
1121
|
+
if (tokens.colors[colorKey]) {
|
|
1122
|
+
const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('bg-', '');
|
|
1123
|
+
const className = `bg-${kebabName}`;
|
|
1124
|
+
const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
|
|
1125
|
+
lines.push(`.${className} {`);
|
|
1126
|
+
lines.push(` background-color: var(${colorVar});`);
|
|
1127
|
+
lines.push('}');
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Text colors
|
|
1132
|
+
const textColors = [
|
|
1133
|
+
'textBase', 'textSubtle', 'textMuted',
|
|
1134
|
+
'textAccentBase', 'textAccentSubtle', 'textAccentMuted'
|
|
1135
|
+
];
|
|
1136
|
+
for (const colorKey of textColors) {
|
|
1137
|
+
if (tokens.colors[colorKey]) {
|
|
1138
|
+
const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('text-', '');
|
|
1139
|
+
const className = `text-${kebabName}`;
|
|
1140
|
+
const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
|
|
1141
|
+
lines.push(`.${className} {`);
|
|
1142
|
+
lines.push(` color: var(${colorVar});`);
|
|
1143
|
+
lines.push('}');
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Border colors
|
|
1148
|
+
const borderColors = [
|
|
1149
|
+
'borderBase', 'borderSubtle', 'borderMuted'
|
|
1150
|
+
];
|
|
1151
|
+
for (const colorKey of borderColors) {
|
|
1152
|
+
if (tokens.colors[colorKey]) {
|
|
1153
|
+
const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('border-', '');
|
|
1154
|
+
const className = `border-${kebabName}`;
|
|
1155
|
+
const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
|
|
1156
|
+
lines.push(`.${className} {`);
|
|
1157
|
+
lines.push(` border-color: var(${colorVar});`);
|
|
1158
|
+
lines.push('}');
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
return lines.join('\n');
|
|
1164
|
+
}
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { bundleIsland, bundleComponentIslands } from './bundler.js';
|
|
|
5
5
|
import { deduplicateCSS } from './css-deduplicator.js';
|
|
6
6
|
import { markdownToHtml, processMarkdownProps } from './markdown.js';
|
|
7
7
|
import TemplateProcessor, { templateProcessor } from './template-processor.js';
|
|
8
|
+
import { defaultDesignTokens, generateTailwindV4Theme, generateTailwindConfig, generateCSSFromTokens } from './design-tokens.js';
|
|
8
9
|
import { readFileSync } from 'fs';
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
11
|
import { dirname, join } from 'path';
|
|
@@ -17,4 +18,4 @@ function getMotionRuntime() {
|
|
|
17
18
|
return readFileSync(join(__dirname, '../dist/motion-runtime.min.js'), 'utf-8');
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export { build, generateComponentCSS, generateTailwindCSS, extractTailwindClasses, cleanComponentHTML, bundleIsland, bundleComponentIslands, deduplicateCSS, markdownToHtml, processMarkdownProps, getMotionRuntime, TemplateProcessor, templateProcessor };
|
|
21
|
+
export { build, generateComponentCSS, generateTailwindCSS, extractTailwindClasses, cleanComponentHTML, bundleIsland, bundleComponentIslands, deduplicateCSS, markdownToHtml, processMarkdownProps, getMotionRuntime, TemplateProcessor, templateProcessor, defaultDesignTokens, generateTailwindV4Theme, generateTailwindConfig, generateCSSFromTokens };
|