@cwcss/crosswind 0.1.5 → 0.1.6

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 (86) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +390 -0
  3. package/dist/build.d.ts +24 -0
  4. package/dist/config.d.ts +5 -0
  5. package/dist/generator.d.ts +31 -0
  6. package/dist/index.d.ts +10 -0
  7. package/dist/index.js +12798 -0
  8. package/dist/parser.d.ts +42 -0
  9. package/dist/plugin.d.ts +22 -0
  10. package/dist/preflight-forms.d.ts +5 -0
  11. package/dist/preflight.d.ts +2 -0
  12. package/dist/rules-advanced.d.ts +27 -0
  13. package/dist/rules-effects.d.ts +25 -0
  14. package/dist/rules-forms.d.ts +7 -0
  15. package/dist/rules-grid.d.ts +13 -0
  16. package/dist/rules-interactivity.d.ts +41 -0
  17. package/dist/rules-layout.d.ts +26 -0
  18. package/dist/rules-transforms.d.ts +33 -0
  19. package/dist/rules-typography.d.ts +41 -0
  20. package/dist/rules.d.ts +39 -0
  21. package/dist/scanner.d.ts +18 -0
  22. package/dist/transformer-compile-class.d.ts +37 -0
  23. package/{src/types.ts → dist/types.d.ts} +17 -86
  24. package/package.json +1 -1
  25. package/PLUGIN.md +0 -235
  26. package/benchmark/framework-comparison.bench.ts +0 -850
  27. package/bin/cli.ts +0 -365
  28. package/bin/crosswind +0 -0
  29. package/bin/headwind +0 -0
  30. package/build.ts +0 -8
  31. package/crosswind.config.ts +0 -9
  32. package/example/comprehensive.html +0 -70
  33. package/example/index.html +0 -21
  34. package/example/output.css +0 -236
  35. package/examples/plugin/README.md +0 -112
  36. package/examples/plugin/build.ts +0 -32
  37. package/examples/plugin/src/index.html +0 -34
  38. package/examples/plugin/src/index.ts +0 -7
  39. package/headwind +0 -2
  40. package/src/build.ts +0 -101
  41. package/src/config.ts +0 -529
  42. package/src/generator.ts +0 -2173
  43. package/src/index.ts +0 -10
  44. package/src/parser.ts +0 -1471
  45. package/src/plugin.ts +0 -118
  46. package/src/preflight-forms.ts +0 -229
  47. package/src/preflight.ts +0 -388
  48. package/src/rules-advanced.ts +0 -477
  49. package/src/rules-effects.ts +0 -461
  50. package/src/rules-forms.ts +0 -103
  51. package/src/rules-grid.ts +0 -241
  52. package/src/rules-interactivity.ts +0 -525
  53. package/src/rules-layout.ts +0 -385
  54. package/src/rules-transforms.ts +0 -412
  55. package/src/rules-typography.ts +0 -486
  56. package/src/rules.ts +0 -809
  57. package/src/scanner.ts +0 -84
  58. package/src/transformer-compile-class.ts +0 -275
  59. package/test/advanced-features.test.ts +0 -911
  60. package/test/arbitrary.test.ts +0 -396
  61. package/test/attributify.test.ts +0 -592
  62. package/test/bracket-syntax.test.ts +0 -1133
  63. package/test/build.test.ts +0 -99
  64. package/test/colors.test.ts +0 -934
  65. package/test/flexbox.test.ts +0 -669
  66. package/test/generator.test.ts +0 -597
  67. package/test/grid.test.ts +0 -584
  68. package/test/layout.test.ts +0 -404
  69. package/test/modifiers.test.ts +0 -417
  70. package/test/parser.test.ts +0 -564
  71. package/test/performance-regression.test.ts +0 -376
  72. package/test/performance.test.ts +0 -568
  73. package/test/plugin.test.ts +0 -160
  74. package/test/scanner.test.ts +0 -94
  75. package/test/sizing.test.ts +0 -481
  76. package/test/spacing.test.ts +0 -394
  77. package/test/transformer-compile-class.test.ts +0 -287
  78. package/test/transforms.test.ts +0 -448
  79. package/test/typography.test.ts +0 -632
  80. package/test/variants-form-states.test.ts +0 -225
  81. package/test/variants-group-peer.test.ts +0 -66
  82. package/test/variants-media.test.ts +0 -213
  83. package/test/variants-positional.test.ts +0 -58
  84. package/test/variants-pseudo-elements.test.ts +0 -47
  85. package/test/variants-state.test.ts +0 -62
  86. package/tsconfig.json +0 -18
@@ -1,934 +0,0 @@
1
- import { describe, expect, it } from 'bun:test'
2
- import { defaultConfig } from '../src/config'
3
- import { CSSGenerator } from '../src/generator'
4
-
5
- describe('Color Utilities', () => {
6
- describe('Text colors', () => {
7
- it('should generate text-blue-500', () => {
8
- const gen = new CSSGenerator(defaultConfig)
9
- gen.generate('text-blue-500')
10
- expect(gen.toCSS(false)).toContain('color: oklch(62.3% 0.214 259.815);')
11
- })
12
-
13
- it('should generate text-gray-800', () => {
14
- const gen = new CSSGenerator(defaultConfig)
15
- gen.generate('text-gray-800')
16
- expect(gen.toCSS(false)).toContain('color: oklch(27.8% 0.033 256.848);')
17
- })
18
-
19
- it('should generate text-red-500', () => {
20
- const gen = new CSSGenerator(defaultConfig)
21
- gen.generate('text-red-500')
22
- expect(gen.toCSS(false)).toContain('color: oklch(63.7% 0.237 25.331);')
23
- })
24
-
25
- it('should generate text-white', () => {
26
- const gen = new CSSGenerator(defaultConfig)
27
- gen.generate('text-white')
28
- expect(gen.toCSS(false)).toContain('color: #fff;')
29
- })
30
-
31
- it('should generate text-black', () => {
32
- const gen = new CSSGenerator(defaultConfig)
33
- gen.generate('text-black')
34
- expect(gen.toCSS(false)).toContain('color: #000;')
35
- })
36
- })
37
-
38
- describe('Background colors', () => {
39
- it('should generate bg-blue-500', () => {
40
- const gen = new CSSGenerator(defaultConfig)
41
- gen.generate('bg-blue-500')
42
- expect(gen.toCSS(false)).toContain('background-color: oklch(62.3% 0.214 259.815);')
43
- })
44
-
45
- it('should generate bg-gray-100', () => {
46
- const gen = new CSSGenerator(defaultConfig)
47
- gen.generate('bg-gray-100')
48
- expect(gen.toCSS(false)).toContain('background-color: oklch(96.7% 0.003 264.542);')
49
- })
50
-
51
- it('should support arbitrary color', () => {
52
- const gen = new CSSGenerator(defaultConfig)
53
- gen.generate('bg-[#ff0000]')
54
- expect(gen.toCSS(false)).toContain('background-color: #ff0000;')
55
- })
56
- })
57
-
58
- describe('Border colors', () => {
59
- it('should generate border-gray-300', () => {
60
- const gen = new CSSGenerator(defaultConfig)
61
- gen.generate('border-gray-300')
62
- expect(gen.toCSS(false)).toContain('border-color: oklch(87.2% 0.01 258.338);')
63
- })
64
-
65
- it('should generate border-blue-500', () => {
66
- const gen = new CSSGenerator(defaultConfig)
67
- gen.generate('border-blue-500')
68
- expect(gen.toCSS(false)).toContain('border-color: oklch(62.3% 0.214 259.815);')
69
- })
70
- })
71
-
72
- describe('Color opacity modifiers', () => {
73
- it('should generate background with opacity', () => {
74
- const gen = new CSSGenerator(defaultConfig)
75
- gen.generate('bg-blue-500/50')
76
- const css = gen.toCSS(false)
77
- expect(css).toContain('background-color: oklch(62.3% 0.214 259.815 / 0.5);')
78
- })
79
-
80
- it('should generate text with opacity', () => {
81
- const gen = new CSSGenerator(defaultConfig)
82
- gen.generate('text-red-500/75')
83
- const css = gen.toCSS(false)
84
- expect(css).toContain('color: oklch(63.7% 0.237 25.331 / 0.75);')
85
- })
86
-
87
- it('should generate border with opacity', () => {
88
- const gen = new CSSGenerator(defaultConfig)
89
- gen.generate('border-gray-500/25')
90
- const css = gen.toCSS(false)
91
- expect(css).toContain('border-color: oklch(55.1% 0.027 264.364 / 0.25);')
92
- })
93
- })
94
- })
95
-
96
- describe('Edge Cases', () => {
97
- describe('Arbitrary color values', () => {
98
- it('should handle hex colors with 3 digits', () => {
99
- const gen = new CSSGenerator(defaultConfig)
100
- gen.generate('bg-[#f00]')
101
- expect(gen.toCSS(false)).toContain('background-color: #f00;')
102
- })
103
-
104
- it('should handle hex colors with 6 digits', () => {
105
- const gen = new CSSGenerator(defaultConfig)
106
- gen.generate('bg-[#ff0000]')
107
- expect(gen.toCSS(false)).toContain('background-color: #ff0000;')
108
- })
109
-
110
- it('should handle hex colors with 8 digits (with alpha)', () => {
111
- const gen = new CSSGenerator(defaultConfig)
112
- gen.generate('bg-[#ff0000ff]')
113
- expect(gen.toCSS(false)).toContain('background-color: #ff0000ff;')
114
- })
115
-
116
- it('should handle rgb() colors', () => {
117
- const gen = new CSSGenerator(defaultConfig)
118
- gen.generate('bg-[rgb(255,0,0)]')
119
- expect(gen.toCSS(false)).toContain('background-color: rgb(255,0,0);')
120
- })
121
-
122
- it('should handle rgba() colors', () => {
123
- const gen = new CSSGenerator(defaultConfig)
124
- gen.generate('bg-[rgba(255,0,0,0.5)]')
125
- expect(gen.toCSS(false)).toContain('background-color: rgba(255,0,0,0.5);')
126
- })
127
-
128
- it('should handle hsl() colors', () => {
129
- const gen = new CSSGenerator(defaultConfig)
130
- gen.generate('bg-[hsl(0,100%,50%)]')
131
- expect(gen.toCSS(false)).toContain('background-color: hsl(0,100%,50%);')
132
- })
133
-
134
- it('should handle hsla() colors', () => {
135
- const gen = new CSSGenerator(defaultConfig)
136
- gen.generate('bg-[hsla(0,100%,50%,0.5)]')
137
- expect(gen.toCSS(false)).toContain('background-color: hsla(0,100%,50%,0.5);')
138
- })
139
-
140
- it('should handle CSS color keywords', () => {
141
- const gen = new CSSGenerator(defaultConfig)
142
- gen.generate('bg-[transparent]')
143
- expect(gen.toCSS(false)).toContain('background-color: transparent;')
144
- })
145
-
146
- it('should handle currentColor', () => {
147
- const gen = new CSSGenerator(defaultConfig)
148
- gen.generate('bg-[currentColor]')
149
- expect(gen.toCSS(false)).toContain('background-color: currentColor;')
150
- })
151
-
152
- it('should handle CSS variables in colors', () => {
153
- const gen = new CSSGenerator(defaultConfig)
154
- gen.generate('bg-[var(--primary-color)]')
155
- expect(gen.toCSS(false)).toContain('background-color: var(--primary-color);')
156
- })
157
- })
158
-
159
- describe('Opacity modifiers comprehensive', () => {
160
- it('should handle 0% opacity', () => {
161
- const gen = new CSSGenerator(defaultConfig)
162
- gen.generate('bg-blue-500/0')
163
- const css = gen.toCSS(false)
164
- expect(css).toContain('background-color: oklch(62.3% 0.214 259.815 / 0);')
165
- })
166
-
167
- it('should handle 100% opacity', () => {
168
- const gen = new CSSGenerator(defaultConfig)
169
- gen.generate('bg-blue-500/100')
170
- const css = gen.toCSS(false)
171
- expect(css).toContain('background-color: oklch(62.3% 0.214 259.815 / 1);')
172
- })
173
-
174
- it('should handle text color with opacity', () => {
175
- const gen = new CSSGenerator(defaultConfig)
176
- gen.generate('text-blue-500/50')
177
- const css = gen.toCSS(false)
178
- expect(css).toContain('color: oklch(62.3% 0.214 259.815 / 0.5);')
179
- })
180
-
181
- it('should handle border color with opacity', () => {
182
- const gen = new CSSGenerator(defaultConfig)
183
- gen.generate('border-blue-500/50')
184
- const css = gen.toCSS(false)
185
- expect(css).toContain('border-color: oklch(62.3% 0.214 259.815 / 0.5);')
186
- })
187
-
188
- it('should reject invalid opacity values above 100', () => {
189
- const gen = new CSSGenerator(defaultConfig)
190
- gen.generate('bg-blue-500/150')
191
- const css = gen.toCSS(false)
192
- // Invalid opacity should not generate any CSS
193
- expect(css).not.toContain('background-color')
194
- })
195
-
196
- it('should reject negative opacity values', () => {
197
- const gen = new CSSGenerator(defaultConfig)
198
- gen.generate('bg-red-500/-50')
199
- const css = gen.toCSS(false)
200
- // Negative opacity should not generate any CSS
201
- expect(css).not.toContain('background-color')
202
- })
203
-
204
- it('should reject non-numeric opacity values', () => {
205
- const gen = new CSSGenerator(defaultConfig)
206
- gen.generate('bg-green-500/abc')
207
- const css = gen.toCSS(false)
208
- // Non-numeric opacity should not generate any CSS
209
- expect(css).not.toContain('background-color')
210
- })
211
-
212
- it('should handle ring color with opacity', () => {
213
- const gen = new CSSGenerator(defaultConfig)
214
- gen.generate('ring-blue-500/50')
215
- const css = gen.toCSS(false)
216
- expect(css).toBeDefined()
217
- })
218
-
219
- it('should handle divide color with opacity', () => {
220
- const gen = new CSSGenerator(defaultConfig)
221
- gen.generate('divide-blue-500/50')
222
- const css = gen.toCSS(false)
223
- expect(css).toBeDefined()
224
- })
225
-
226
- it('should handle arbitrary hex color with opacity', () => {
227
- const gen = new CSSGenerator(defaultConfig)
228
- gen.generate('text-[#ff0000]/50')
229
- const css = gen.toCSS(false)
230
- expect(css).toContain('color: rgb(255 0 0 / 0.5);')
231
- })
232
-
233
- it('should handle arbitrary hex color with opacity for background', () => {
234
- const gen = new CSSGenerator(defaultConfig)
235
- gen.generate('bg-[#00ff00]/75')
236
- const css = gen.toCSS(false)
237
- expect(css).toContain('background-color: rgb(0 255 0 / 0.75);')
238
- })
239
- })
240
-
241
- describe('Color with variants', () => {
242
- it('should handle color with hover', () => {
243
- const gen = new CSSGenerator(defaultConfig)
244
- gen.generate('hover:bg-red-500')
245
- const css = gen.toCSS(false)
246
- expect(css).toContain(':hover')
247
- expect(css).toContain('background-color: oklch(63.7% 0.237 25.331);')
248
- })
249
-
250
- it('should handle color with focus', () => {
251
- const gen = new CSSGenerator(defaultConfig)
252
- gen.generate('focus:text-blue-500')
253
- const css = gen.toCSS(false)
254
- expect(css).toContain(':focus')
255
- expect(css).toContain('color: oklch(62.3% 0.214 259.815);')
256
- })
257
-
258
- it('should handle color with responsive', () => {
259
- const gen = new CSSGenerator(defaultConfig)
260
- gen.generate('md:bg-green-500')
261
- const css = gen.toCSS(false)
262
- expect(css).toContain('@media (min-width: 768px)')
263
- expect(css).toContain('background-color: oklch(72.3% 0.219 149.579);')
264
- })
265
-
266
- it('should handle color with important', () => {
267
- const gen = new CSSGenerator(defaultConfig)
268
- gen.generate('!bg-blue-500')
269
- expect(gen.toCSS(false)).toContain('background-color: oklch(62.3% 0.214 259.815) !important;')
270
- })
271
-
272
- it('should handle color with dark mode', () => {
273
- const gen = new CSSGenerator(defaultConfig)
274
- gen.generate('dark:bg-gray-900')
275
- const css = gen.toCSS(false)
276
- expect(css).toContain('.dark')
277
- expect(css).toContain('background-color: oklch(21% 0.034 264.665);')
278
- })
279
-
280
- it('should handle color opacity with hover', () => {
281
- const gen = new CSSGenerator(defaultConfig)
282
- gen.generate('hover:bg-blue-500/75')
283
- const css = gen.toCSS(false)
284
- expect(css).toContain(':hover')
285
- expect(css).toContain('background-color: oklch(62.3% 0.214 259.815 / 0.75);')
286
- })
287
-
288
- it('should handle multiple variant combinations', () => {
289
- const gen = new CSSGenerator(defaultConfig)
290
- gen.generate('dark:md:hover:bg-blue-500/50')
291
- const css = gen.toCSS(false)
292
- expect(css).toContain('.dark')
293
- expect(css).toContain('@media (min-width: 768px)')
294
- expect(css).toContain(':hover')
295
- expect(css).toContain('background-color')
296
- })
297
- })
298
-
299
- describe('All color shades', () => {
300
- it('should handle 50 shade', () => {
301
- const gen = new CSSGenerator(defaultConfig)
302
- gen.generate('bg-gray-50')
303
- expect(gen.toCSS(false)).toContain('background-color: oklch(98.5% 0.002 247.839);')
304
- })
305
-
306
- it('should handle 950 shade', () => {
307
- const gen = new CSSGenerator(defaultConfig)
308
- gen.generate('bg-gray-950')
309
- expect(gen.toCSS(false)).toContain('background-color:')
310
- })
311
-
312
- it('should handle all middle shades', () => {
313
- const gen = new CSSGenerator(defaultConfig)
314
- const shades = ['100', '200', '300', '400', '500', '600', '700', '800', '900']
315
- for (const shade of shades) {
316
- gen.generate(`bg-blue-${shade}`)
317
- }
318
- const css = gen.toCSS(false)
319
- expect(css).toBeDefined()
320
- expect(css.length).toBeGreaterThan(0)
321
- })
322
- })
323
-
324
- describe('Special color cases', () => {
325
- it('should handle inherit', () => {
326
- const gen = new CSSGenerator(defaultConfig)
327
- gen.generate('bg-inherit')
328
- expect(gen.toCSS(false)).toContain('background-color: inherit;')
329
- })
330
-
331
- it('should handle transparent', () => {
332
- const gen = new CSSGenerator(defaultConfig)
333
- gen.generate('bg-transparent')
334
- expect(gen.toCSS(false)).toContain('background-color: transparent;')
335
- })
336
-
337
- it('should handle current', () => {
338
- const gen = new CSSGenerator(defaultConfig)
339
- gen.generate('bg-current')
340
- expect(gen.toCSS(false)).toContain('background-color: currentColor;')
341
- })
342
-
343
- it('should handle text-inherit', () => {
344
- const gen = new CSSGenerator(defaultConfig)
345
- gen.generate('text-inherit')
346
- expect(gen.toCSS(false)).toContain('color: inherit;')
347
- })
348
-
349
- it('should handle text-transparent', () => {
350
- const gen = new CSSGenerator(defaultConfig)
351
- gen.generate('text-transparent')
352
- expect(gen.toCSS(false)).toContain('color: transparent;')
353
- })
354
-
355
- it('should handle text-current', () => {
356
- const gen = new CSSGenerator(defaultConfig)
357
- gen.generate('text-current')
358
- expect(gen.toCSS(false)).toContain('color: currentColor;')
359
- })
360
- })
361
-
362
- describe('Advanced color formats', () => {
363
- it('should handle 3-digit hex colors', () => {
364
- const gen = new CSSGenerator(defaultConfig)
365
- gen.generate('bg-[#fff]')
366
- gen.generate('text-[#000]')
367
- const css = gen.toCSS(false)
368
- expect(css).toContain('#fff')
369
- expect(css).toContain('#000')
370
- })
371
-
372
- it('should handle 8-digit hex colors with alpha', () => {
373
- const gen = new CSSGenerator(defaultConfig)
374
- gen.generate('bg-[#ff000080]')
375
- const css = gen.toCSS(false)
376
- expect(css).toContain('#ff000080')
377
- })
378
-
379
- it('should handle rgb() notation', () => {
380
- const gen = new CSSGenerator(defaultConfig)
381
- gen.generate('bg-[rgb(255,0,0)]')
382
- const css = gen.toCSS(false)
383
- expect(css).toContain('rgb(255,0,0)')
384
- })
385
-
386
- it('should handle rgba() notation', () => {
387
- const gen = new CSSGenerator(defaultConfig)
388
- gen.generate('bg-[rgba(255,0,0,0.5)]')
389
- const css = gen.toCSS(false)
390
- expect(css).toContain('rgba(255,0,0,0.5)')
391
- })
392
-
393
- it('should handle hsl() notation', () => {
394
- const gen = new CSSGenerator(defaultConfig)
395
- gen.generate('bg-[hsl(0,100%,50%)]')
396
- const css = gen.toCSS(false)
397
- expect(css).toContain('hsl(0,100%,50%)')
398
- })
399
-
400
- it('should handle hsla() notation', () => {
401
- const gen = new CSSGenerator(defaultConfig)
402
- gen.generate('bg-[hsla(0,100%,50%,0.5)]')
403
- const css = gen.toCSS(false)
404
- expect(css).toContain('hsla(0,100%,50%,0.5)')
405
- })
406
-
407
- it('should handle oklch() notation', () => {
408
- const gen = new CSSGenerator(defaultConfig)
409
- gen.generate('bg-[oklch(0.5_0.2_180)]')
410
- const css = gen.toCSS(false)
411
- expect(css).toContain('oklch')
412
- })
413
-
414
- it('should handle color() notation', () => {
415
- const gen = new CSSGenerator(defaultConfig)
416
- gen.generate('bg-[color(display-p3_1_0_0)]')
417
- const css = gen.toCSS(false)
418
- expect(css).toContain('color(')
419
- })
420
-
421
- it('should handle nonexistent color shades gracefully', () => {
422
- const gen = new CSSGenerator(defaultConfig)
423
- gen.generate('bg-blue-999')
424
- gen.generate('text-red-1')
425
- // Should not crash, may not generate CSS
426
- expect(() => gen.toCSS(false)).not.toThrow()
427
- })
428
-
429
- it('should handle color with opacity modifier', () => {
430
- const gen = new CSSGenerator(defaultConfig)
431
- gen.generate('bg-blue-500/50')
432
- gen.generate('text-red-500/75')
433
- // May or may not be implemented, but should not crash
434
- expect(() => gen.toCSS(false)).not.toThrow()
435
- })
436
- })
437
-
438
- describe('Multi-segment color names', () => {
439
- describe('Two-segment color names (e.g. blue-gray)', () => {
440
- it('should generate bg-blue-gray-50', () => {
441
- const config = {
442
- ...defaultConfig,
443
- theme: {
444
- ...defaultConfig.theme,
445
- colors: {
446
- ...defaultConfig.theme.colors,
447
- 'blue-gray': {
448
- 50: '#f8fafc',
449
- 100: '#f1f5f9',
450
- 200: '#e2e8f0',
451
- 300: '#cbd5e1',
452
- 400: '#94a3b8',
453
- 500: '#64748b',
454
- 600: '#475569',
455
- 700: '#334155',
456
- 800: '#1e293b',
457
- 900: '#0f172a',
458
- },
459
- },
460
- },
461
- }
462
- const gen = new CSSGenerator(config)
463
- gen.generate('bg-blue-gray-50')
464
- expect(gen.toCSS(false)).toContain('background-color: #f8fafc;')
465
- })
466
-
467
- it('should generate text-blue-gray-500', () => {
468
- const config = {
469
- ...defaultConfig,
470
- theme: {
471
- ...defaultConfig.theme,
472
- colors: {
473
- ...defaultConfig.theme.colors,
474
- 'blue-gray': {
475
- 500: '#64748b',
476
- },
477
- },
478
- },
479
- }
480
- const gen = new CSSGenerator(config)
481
- gen.generate('text-blue-gray-500')
482
- expect(gen.toCSS(false)).toContain('color: #64748b;')
483
- })
484
-
485
- it('should generate border-blue-gray-200', () => {
486
- const config = {
487
- ...defaultConfig,
488
- theme: {
489
- ...defaultConfig.theme,
490
- colors: {
491
- ...defaultConfig.theme.colors,
492
- 'blue-gray': {
493
- 200: '#e2e8f0',
494
- },
495
- },
496
- },
497
- }
498
- const gen = new CSSGenerator(config)
499
- gen.generate('border-blue-gray-200')
500
- expect(gen.toCSS(false)).toContain('border-color: #e2e8f0;')
501
- })
502
-
503
- it('should handle all shades of blue-gray', () => {
504
- const config = {
505
- ...defaultConfig,
506
- theme: {
507
- ...defaultConfig.theme,
508
- colors: {
509
- ...defaultConfig.theme.colors,
510
- 'blue-gray': {
511
- 50: '#f8fafc',
512
- 100: '#f1f5f9',
513
- 200: '#e2e8f0',
514
- 300: '#cbd5e1',
515
- 400: '#94a3b8',
516
- 500: '#64748b',
517
- 600: '#475569',
518
- 700: '#334155',
519
- 800: '#1e293b',
520
- 900: '#0f172a',
521
- 950: '#020617',
522
- },
523
- },
524
- },
525
- }
526
- const gen = new CSSGenerator(config)
527
- const shades = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']
528
-
529
- for (const shade of shades) {
530
- gen.generate(`bg-blue-gray-${shade}`)
531
- }
532
-
533
- const css = gen.toCSS(false)
534
- expect(css).toContain('background-color: #f8fafc;') // 50
535
- expect(css).toContain('background-color: #64748b;') // 500
536
- expect(css).toContain('background-color: #0f172a;') // 900
537
- expect(css).toContain('background-color: #020617;') // 950
538
- })
539
- })
540
-
541
- describe('Three-segment color names (e.g. ocean-blue-green)', () => {
542
- it('should generate bg-ocean-blue-green with single value', () => {
543
- const config = {
544
- ...defaultConfig,
545
- theme: {
546
- ...defaultConfig.theme,
547
- colors: {
548
- ...defaultConfig.theme.colors,
549
- 'ocean-blue-green': '#084E77',
550
- },
551
- },
552
- }
553
- const gen = new CSSGenerator(config)
554
- gen.generate('bg-ocean-blue-green')
555
- expect(gen.toCSS(false)).toContain('background-color: #084E77;')
556
- })
557
-
558
- it('should generate text-ocean-blue-green', () => {
559
- const config = {
560
- ...defaultConfig,
561
- theme: {
562
- ...defaultConfig.theme,
563
- colors: {
564
- ...defaultConfig.theme.colors,
565
- 'ocean-blue-green': '#084E77',
566
- },
567
- },
568
- }
569
- const gen = new CSSGenerator(config)
570
- gen.generate('text-ocean-blue-green')
571
- expect(gen.toCSS(false)).toContain('color: #084E77;')
572
- })
573
-
574
- it('should handle three-segment color with shades', () => {
575
- const config = {
576
- ...defaultConfig,
577
- theme: {
578
- ...defaultConfig.theme,
579
- colors: {
580
- ...defaultConfig.theme.colors,
581
- 'deep-ocean-blue': {
582
- 100: '#e0f2fe',
583
- 500: '#0284c7',
584
- 900: '#0c4a6e',
585
- },
586
- },
587
- },
588
- }
589
- const gen = new CSSGenerator(config)
590
- gen.generate('bg-deep-ocean-blue-100')
591
- gen.generate('bg-deep-ocean-blue-500')
592
- gen.generate('bg-deep-ocean-blue-900')
593
-
594
- const css = gen.toCSS(false)
595
- expect(css).toContain('background-color: #e0f2fe;')
596
- expect(css).toContain('background-color: #0284c7;')
597
- expect(css).toContain('background-color: #0c4a6e;')
598
- })
599
- })
600
-
601
- describe('Multi-segment colors with opacity modifiers', () => {
602
- it('should handle blue-gray-500 with opacity', () => {
603
- const config = {
604
- ...defaultConfig,
605
- theme: {
606
- ...defaultConfig.theme,
607
- colors: {
608
- ...defaultConfig.theme.colors,
609
- 'blue-gray': {
610
- 500: '#64748b',
611
- },
612
- },
613
- },
614
- }
615
- const gen = new CSSGenerator(config)
616
- gen.generate('bg-blue-gray-500/50')
617
-
618
- const css = gen.toCSS(false)
619
- // Hex #64748b converts to rgb(100 116 139 / 0.5)
620
- expect(css).toContain('background-color: rgb(100 116 139 / 0.5);')
621
- })
622
-
623
- it('should handle ocean-blue-green with opacity', () => {
624
- const config = {
625
- ...defaultConfig,
626
- theme: {
627
- ...defaultConfig.theme,
628
- colors: {
629
- ...defaultConfig.theme.colors,
630
- 'ocean-blue-green': '#084E77',
631
- },
632
- },
633
- }
634
- const gen = new CSSGenerator(config)
635
- gen.generate('text-ocean-blue-green/75')
636
-
637
- const css = gen.toCSS(false)
638
- // Hex #084E77 converts to rgb(8 78 119 / 0.75)
639
- expect(css).toContain('color: rgb(8 78 119 / 0.75);')
640
- })
641
-
642
- it('should handle three-segment color with shade and opacity', () => {
643
- const config = {
644
- ...defaultConfig,
645
- theme: {
646
- ...defaultConfig.theme,
647
- colors: {
648
- ...defaultConfig.theme.colors,
649
- 'deep-ocean-blue': {
650
- 500: '#0284c7',
651
- },
652
- },
653
- },
654
- }
655
- const gen = new CSSGenerator(config)
656
- gen.generate('bg-deep-ocean-blue-500/25')
657
-
658
- const css = gen.toCSS(false)
659
- // Hex #0284c7 converts to rgb(2 132 199 / 0.25)
660
- expect(css).toContain('background-color: rgb(2 132 199 / 0.25);')
661
- })
662
- })
663
-
664
- describe('Multi-segment colors with variants', () => {
665
- it('should handle hover:bg-blue-gray-50', () => {
666
- const config = {
667
- ...defaultConfig,
668
- theme: {
669
- ...defaultConfig.theme,
670
- colors: {
671
- ...defaultConfig.theme.colors,
672
- 'blue-gray': {
673
- 50: '#f8fafc',
674
- },
675
- },
676
- },
677
- }
678
- const gen = new CSSGenerator(config)
679
- gen.generate('hover:bg-blue-gray-50')
680
-
681
- const css = gen.toCSS(false)
682
- expect(css).toContain(':hover')
683
- expect(css).toContain('background-color: #f8fafc;')
684
- })
685
-
686
- it('should handle focus:text-blue-gray-700', () => {
687
- const config = {
688
- ...defaultConfig,
689
- theme: {
690
- ...defaultConfig.theme,
691
- colors: {
692
- ...defaultConfig.theme.colors,
693
- 'blue-gray': {
694
- 700: '#334155',
695
- },
696
- },
697
- },
698
- }
699
- const gen = new CSSGenerator(config)
700
- gen.generate('focus:text-blue-gray-700')
701
-
702
- const css = gen.toCSS(false)
703
- expect(css).toContain(':focus')
704
- expect(css).toContain('color: #334155;')
705
- })
706
-
707
- it('should handle md:bg-ocean-blue-green', () => {
708
- const config = {
709
- ...defaultConfig,
710
- theme: {
711
- ...defaultConfig.theme,
712
- colors: {
713
- ...defaultConfig.theme.colors,
714
- 'ocean-blue-green': '#084E77',
715
- },
716
- },
717
- }
718
- const gen = new CSSGenerator(config)
719
- gen.generate('md:bg-ocean-blue-green')
720
-
721
- const css = gen.toCSS(false)
722
- expect(css).toContain('@media (min-width: 768px)')
723
- expect(css).toContain('background-color: #084E77;')
724
- })
725
-
726
- it('should handle dark:hover:bg-blue-gray-800', () => {
727
- const config = {
728
- ...defaultConfig,
729
- theme: {
730
- ...defaultConfig.theme,
731
- colors: {
732
- ...defaultConfig.theme.colors,
733
- 'blue-gray': {
734
- 800: '#1e293b',
735
- },
736
- },
737
- },
738
- }
739
- const gen = new CSSGenerator(config)
740
- gen.generate('dark:hover:bg-blue-gray-800')
741
-
742
- const css = gen.toCSS(false)
743
- expect(css).toContain('.dark')
744
- expect(css).toContain(':hover')
745
- expect(css).toContain('background-color: #1e293b;')
746
- })
747
-
748
- it('should handle complex variant combinations with opacity', () => {
749
- const config = {
750
- ...defaultConfig,
751
- theme: {
752
- ...defaultConfig.theme,
753
- colors: {
754
- ...defaultConfig.theme.colors,
755
- 'blue-gray': {
756
- 600: '#475569',
757
- },
758
- },
759
- },
760
- }
761
- const gen = new CSSGenerator(config)
762
- gen.generate('dark:md:hover:bg-blue-gray-600/50')
763
-
764
- const css = gen.toCSS(false)
765
- expect(css).toContain('.dark')
766
- expect(css).toContain('@media (min-width: 768px)')
767
- expect(css).toContain(':hover')
768
- // Hex #475569 converts to rgb(71 85 105 / 0.5)
769
- expect(css).toContain('background-color: rgb(71 85 105 / 0.5);')
770
- })
771
- })
772
-
773
- describe('Edge cases for multi-segment colors', () => {
774
- it('should not confuse two-segment color with regular color', () => {
775
- const config = {
776
- ...defaultConfig,
777
- theme: {
778
- ...defaultConfig.theme,
779
- colors: {
780
- ...defaultConfig.theme.colors,
781
- 'blue-gray': {
782
- 500: '#64748b',
783
- },
784
- },
785
- },
786
- }
787
- const gen = new CSSGenerator(config)
788
- gen.generate('bg-blue-500')
789
- gen.generate('bg-blue-gray-500')
790
-
791
- const css = gen.toCSS(false)
792
- // blue-500 uses oklch from default config
793
- expect(css).toContain('oklch(62.3% 0.214 259.815)')
794
- // blue-gray-500 uses custom hex
795
- expect(css).toContain('background-color: #64748b;')
796
- })
797
-
798
- it('should handle color name that looks like shade number', () => {
799
- const config = {
800
- ...defaultConfig,
801
- theme: {
802
- ...defaultConfig.theme,
803
- colors: {
804
- ...defaultConfig.theme.colors,
805
- 'slate-blue': {
806
- 500: '#6b7cc7',
807
- },
808
- },
809
- },
810
- }
811
- const gen = new CSSGenerator(config)
812
- gen.generate('bg-slate-blue-500')
813
- expect(gen.toCSS(false)).toContain('background-color: #6b7cc7;')
814
- })
815
-
816
- it('should handle four-segment color names', () => {
817
- const config = {
818
- ...defaultConfig,
819
- theme: {
820
- ...defaultConfig.theme,
821
- colors: {
822
- ...defaultConfig.theme.colors,
823
- 'ultra-light-sky-blue': {
824
- 300: '#87ceeb',
825
- },
826
- },
827
- },
828
- }
829
- const gen = new CSSGenerator(config)
830
- gen.generate('bg-ultra-light-sky-blue-300')
831
- expect(gen.toCSS(false)).toContain('background-color: #87ceeb;')
832
- })
833
-
834
- it('should handle missing shade gracefully', () => {
835
- const config = {
836
- ...defaultConfig,
837
- theme: {
838
- ...defaultConfig.theme,
839
- colors: {
840
- ...defaultConfig.theme.colors,
841
- 'blue-gray': {
842
- 500: '#64748b',
843
- },
844
- },
845
- },
846
- }
847
- const gen = new CSSGenerator(config)
848
- gen.generate('bg-blue-gray-999')
849
- expect(() => gen.toCSS(false)).not.toThrow()
850
- })
851
-
852
- it('should handle nonexistent multi-segment color', () => {
853
- const config = defaultConfig
854
- const gen = new CSSGenerator(config)
855
- gen.generate('bg-fake-multi-segment-500')
856
- expect(() => gen.toCSS(false)).not.toThrow()
857
- })
858
- })
859
-
860
- describe('Real-world color palettes', () => {
861
- it('should support slate-gray palette', () => {
862
- const config = {
863
- ...defaultConfig,
864
- theme: {
865
- ...defaultConfig.theme,
866
- colors: {
867
- ...defaultConfig.theme.colors,
868
- 'slate-gray': {
869
- 50: '#f8fafc',
870
- 500: '#64748b',
871
- 900: '#0f172a',
872
- },
873
- },
874
- },
875
- }
876
- const gen = new CSSGenerator(config)
877
- gen.generate('bg-slate-gray-50')
878
- gen.generate('text-slate-gray-500')
879
- gen.generate('border-slate-gray-900')
880
-
881
- const css = gen.toCSS(false)
882
- expect(css).toContain('background-color: #f8fafc;')
883
- expect(css).toContain('color: #64748b;')
884
- expect(css).toContain('border-color: #0f172a;')
885
- })
886
-
887
- it('should support cool-gray palette', () => {
888
- const config = {
889
- ...defaultConfig,
890
- theme: {
891
- ...defaultConfig.theme,
892
- colors: {
893
- ...defaultConfig.theme.colors,
894
- 'cool-gray': {
895
- 100: '#f3f4f6',
896
- 600: '#4b5563',
897
- },
898
- },
899
- },
900
- }
901
- const gen = new CSSGenerator(config)
902
- gen.generate('bg-cool-gray-100')
903
- gen.generate('text-cool-gray-600')
904
-
905
- const css = gen.toCSS(false)
906
- expect(css).toContain('background-color: #f3f4f6;')
907
- expect(css).toContain('color: #4b5563;')
908
- })
909
-
910
- it('should support warm-gray palette', () => {
911
- const config = {
912
- ...defaultConfig,
913
- theme: {
914
- ...defaultConfig.theme,
915
- colors: {
916
- ...defaultConfig.theme.colors,
917
- 'warm-gray': {
918
- 200: '#e7e5e4',
919
- 700: '#44403c',
920
- },
921
- },
922
- },
923
- }
924
- const gen = new CSSGenerator(config)
925
- gen.generate('bg-warm-gray-200')
926
- gen.generate('border-warm-gray-700')
927
-
928
- const css = gen.toCSS(false)
929
- expect(css).toContain('background-color: #e7e5e4;')
930
- expect(css).toContain('border-color: #44403c;')
931
- })
932
- })
933
- })
934
- })