streamlit-react-components 1.7.2__py3-none-any.whl → 1.7.4__py3-none-any.whl

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.
@@ -0,0 +1,1536 @@
1
+ """
2
+ Tailwind CSS to Python CSS dictionary converter.
3
+
4
+ This module provides a comprehensive mapping of Tailwind CSS utility classes
5
+ to their CSS equivalents, enabling Tailwind-like styling in Python/Streamlit.
6
+
7
+ Supports:
8
+ - All standard Tailwind classes (~2100+)
9
+ - Opacity modifiers (bg-blue-500/50)
10
+ - Variant prefixes (hover:, focus:, active:)
11
+ """
12
+
13
+ from typing import Dict, Tuple, Any, Union
14
+ import re
15
+
16
+ # =============================================================================
17
+ # TAILWIND COLOR PALETTE (Official Tailwind v3 colors)
18
+ # =============================================================================
19
+
20
+ COLORS: Dict[str, Dict[str, str]] = {
21
+ "slate": {
22
+ "50": "#f8fafc", "100": "#f1f5f9", "200": "#e2e8f0", "300": "#cbd5e1",
23
+ "400": "#94a3b8", "500": "#64748b", "600": "#475569", "700": "#334155",
24
+ "800": "#1e293b", "900": "#0f172a", "950": "#020617",
25
+ },
26
+ "gray": {
27
+ "50": "#f9fafb", "100": "#f3f4f6", "200": "#e5e7eb", "300": "#d1d5db",
28
+ "400": "#9ca3af", "500": "#6b7280", "600": "#4b5563", "700": "#374151",
29
+ "800": "#1f2937", "900": "#111827", "950": "#030712",
30
+ },
31
+ "zinc": {
32
+ "50": "#fafafa", "100": "#f4f4f5", "200": "#e4e4e7", "300": "#d4d4d8",
33
+ "400": "#a1a1aa", "500": "#71717a", "600": "#52525b", "700": "#3f3f46",
34
+ "800": "#27272a", "900": "#18181b", "950": "#09090b",
35
+ },
36
+ "neutral": {
37
+ "50": "#fafafa", "100": "#f5f5f5", "200": "#e5e5e5", "300": "#d4d4d4",
38
+ "400": "#a3a3a3", "500": "#737373", "600": "#525252", "700": "#404040",
39
+ "800": "#262626", "900": "#171717", "950": "#0a0a0a",
40
+ },
41
+ "stone": {
42
+ "50": "#fafaf9", "100": "#f5f5f4", "200": "#e7e5e4", "300": "#d6d3d1",
43
+ "400": "#a8a29e", "500": "#78716c", "600": "#57534e", "700": "#44403c",
44
+ "800": "#292524", "900": "#1c1917", "950": "#0c0a09",
45
+ },
46
+ "red": {
47
+ "50": "#fef2f2", "100": "#fee2e2", "200": "#fecaca", "300": "#fca5a5",
48
+ "400": "#f87171", "500": "#ef4444", "600": "#dc2626", "700": "#b91c1c",
49
+ "800": "#991b1b", "900": "#7f1d1d", "950": "#450a0a",
50
+ },
51
+ "orange": {
52
+ "50": "#fff7ed", "100": "#ffedd5", "200": "#fed7aa", "300": "#fdba74",
53
+ "400": "#fb923c", "500": "#f97316", "600": "#ea580c", "700": "#c2410c",
54
+ "800": "#9a3412", "900": "#7c2d12", "950": "#431407",
55
+ },
56
+ "amber": {
57
+ "50": "#fffbeb", "100": "#fef3c7", "200": "#fde68a", "300": "#fcd34d",
58
+ "400": "#fbbf24", "500": "#f59e0b", "600": "#d97706", "700": "#b45309",
59
+ "800": "#92400e", "900": "#78350f", "950": "#451a03",
60
+ },
61
+ "yellow": {
62
+ "50": "#fefce8", "100": "#fef9c3", "200": "#fef08a", "300": "#fde047",
63
+ "400": "#facc15", "500": "#eab308", "600": "#ca8a04", "700": "#a16207",
64
+ "800": "#854d0e", "900": "#713f12", "950": "#422006",
65
+ },
66
+ "lime": {
67
+ "50": "#f7fee7", "100": "#ecfccb", "200": "#d9f99d", "300": "#bef264",
68
+ "400": "#a3e635", "500": "#84cc16", "600": "#65a30d", "700": "#4d7c0f",
69
+ "800": "#3f6212", "900": "#365314", "950": "#1a2e05",
70
+ },
71
+ "green": {
72
+ "50": "#f0fdf4", "100": "#dcfce7", "200": "#bbf7d0", "300": "#86efac",
73
+ "400": "#4ade80", "500": "#22c55e", "600": "#16a34a", "700": "#15803d",
74
+ "800": "#166534", "900": "#14532d", "950": "#052e16",
75
+ },
76
+ "emerald": {
77
+ "50": "#ecfdf5", "100": "#d1fae5", "200": "#a7f3d0", "300": "#6ee7b7",
78
+ "400": "#34d399", "500": "#10b981", "600": "#059669", "700": "#047857",
79
+ "800": "#065f46", "900": "#064e3b", "950": "#022c22",
80
+ },
81
+ "teal": {
82
+ "50": "#f0fdfa", "100": "#ccfbf1", "200": "#99f6e4", "300": "#5eead4",
83
+ "400": "#2dd4bf", "500": "#14b8a6", "600": "#0d9488", "700": "#0f766e",
84
+ "800": "#115e59", "900": "#134e4a", "950": "#042f2e",
85
+ },
86
+ "cyan": {
87
+ "50": "#ecfeff", "100": "#cffafe", "200": "#a5f3fc", "300": "#67e8f9",
88
+ "400": "#22d3ee", "500": "#06b6d4", "600": "#0891b2", "700": "#0e7490",
89
+ "800": "#155e75", "900": "#164e63", "950": "#083344",
90
+ },
91
+ "sky": {
92
+ "50": "#f0f9ff", "100": "#e0f2fe", "200": "#bae6fd", "300": "#7dd3fc",
93
+ "400": "#38bdf8", "500": "#0ea5e9", "600": "#0284c7", "700": "#0369a1",
94
+ "800": "#075985", "900": "#0c4a6e", "950": "#082f49",
95
+ },
96
+ "blue": {
97
+ "50": "#eff6ff", "100": "#dbeafe", "200": "#bfdbfe", "300": "#93c5fd",
98
+ "400": "#60a5fa", "500": "#3b82f6", "600": "#2563eb", "700": "#1d4ed8",
99
+ "800": "#1e40af", "900": "#1e3a8a", "950": "#172554",
100
+ },
101
+ "indigo": {
102
+ "50": "#eef2ff", "100": "#e0e7ff", "200": "#c7d2fe", "300": "#a5b4fc",
103
+ "400": "#818cf8", "500": "#6366f1", "600": "#4f46e5", "700": "#4338ca",
104
+ "800": "#3730a3", "900": "#312e81", "950": "#1e1b4b",
105
+ },
106
+ "violet": {
107
+ "50": "#f5f3ff", "100": "#ede9fe", "200": "#ddd6fe", "300": "#c4b5fd",
108
+ "400": "#a78bfa", "500": "#8b5cf6", "600": "#7c3aed", "700": "#6d28d9",
109
+ "800": "#5b21b6", "900": "#4c1d95", "950": "#2e1065",
110
+ },
111
+ "purple": {
112
+ "50": "#faf5ff", "100": "#f3e8ff", "200": "#e9d5ff", "300": "#d8b4fe",
113
+ "400": "#c084fc", "500": "#a855f7", "600": "#9333ea", "700": "#7e22ce",
114
+ "800": "#6b21a8", "900": "#581c87", "950": "#3b0764",
115
+ },
116
+ "fuchsia": {
117
+ "50": "#fdf4ff", "100": "#fae8ff", "200": "#f5d0fe", "300": "#f0abfc",
118
+ "400": "#e879f9", "500": "#d946ef", "600": "#c026d3", "700": "#a21caf",
119
+ "800": "#86198f", "900": "#701a75", "950": "#4a044e",
120
+ },
121
+ "pink": {
122
+ "50": "#fdf2f8", "100": "#fce7f3", "200": "#fbcfe8", "300": "#f9a8d4",
123
+ "400": "#f472b6", "500": "#ec4899", "600": "#db2777", "700": "#be185d",
124
+ "800": "#9d174d", "900": "#831843", "950": "#500724",
125
+ },
126
+ "rose": {
127
+ "50": "#fff1f2", "100": "#ffe4e6", "200": "#fecdd3", "300": "#fda4af",
128
+ "400": "#fb7185", "500": "#f43f5e", "600": "#e11d48", "700": "#be123c",
129
+ "800": "#9f1239", "900": "#881337", "950": "#4c0519",
130
+ },
131
+ }
132
+
133
+ # Special colors
134
+ SPECIAL_COLORS: Dict[str, str] = {
135
+ "black": "#000000",
136
+ "white": "#ffffff",
137
+ "transparent": "transparent",
138
+ "current": "currentColor",
139
+ "inherit": "inherit",
140
+ }
141
+
142
+ # =============================================================================
143
+ # SPACING SCALE
144
+ # =============================================================================
145
+
146
+ SPACING: Dict[str, str] = {
147
+ "0": "0px",
148
+ "px": "1px",
149
+ "0.5": "0.125rem",
150
+ "1": "0.25rem",
151
+ "1.5": "0.375rem",
152
+ "2": "0.5rem",
153
+ "2.5": "0.625rem",
154
+ "3": "0.75rem",
155
+ "3.5": "0.875rem",
156
+ "4": "1rem",
157
+ "5": "1.25rem",
158
+ "6": "1.5rem",
159
+ "7": "1.75rem",
160
+ "8": "2rem",
161
+ "9": "2.25rem",
162
+ "10": "2.5rem",
163
+ "11": "2.75rem",
164
+ "12": "3rem",
165
+ "14": "3.5rem",
166
+ "16": "4rem",
167
+ "20": "5rem",
168
+ "24": "6rem",
169
+ "28": "7rem",
170
+ "32": "8rem",
171
+ "36": "9rem",
172
+ "40": "10rem",
173
+ "44": "11rem",
174
+ "48": "12rem",
175
+ "52": "13rem",
176
+ "56": "14rem",
177
+ "60": "15rem",
178
+ "64": "16rem",
179
+ "72": "18rem",
180
+ "80": "20rem",
181
+ "96": "24rem",
182
+ }
183
+
184
+ # =============================================================================
185
+ # STATIC MAPPINGS
186
+ # =============================================================================
187
+
188
+ # Typography
189
+ FONT_SIZE: Dict[str, Dict[str, str]] = {
190
+ "text-xs": {"font-size": "0.75rem", "line-height": "1rem"},
191
+ "text-sm": {"font-size": "0.875rem", "line-height": "1.25rem"},
192
+ "text-base": {"font-size": "1rem", "line-height": "1.5rem"},
193
+ "text-lg": {"font-size": "1.125rem", "line-height": "1.75rem"},
194
+ "text-xl": {"font-size": "1.25rem", "line-height": "1.75rem"},
195
+ "text-2xl": {"font-size": "1.5rem", "line-height": "2rem"},
196
+ "text-3xl": {"font-size": "1.875rem", "line-height": "2.25rem"},
197
+ "text-4xl": {"font-size": "2.25rem", "line-height": "2.5rem"},
198
+ "text-5xl": {"font-size": "3rem", "line-height": "1"},
199
+ "text-6xl": {"font-size": "3.75rem", "line-height": "1"},
200
+ "text-7xl": {"font-size": "4.5rem", "line-height": "1"},
201
+ "text-8xl": {"font-size": "6rem", "line-height": "1"},
202
+ "text-9xl": {"font-size": "8rem", "line-height": "1"},
203
+ }
204
+
205
+ FONT_WEIGHT: Dict[str, str] = {
206
+ "font-thin": "100",
207
+ "font-extralight": "200",
208
+ "font-light": "300",
209
+ "font-normal": "400",
210
+ "font-medium": "500",
211
+ "font-semibold": "600",
212
+ "font-bold": "700",
213
+ "font-extrabold": "800",
214
+ "font-black": "900",
215
+ }
216
+
217
+ LINE_HEIGHT: Dict[str, str] = {
218
+ "leading-none": "1",
219
+ "leading-tight": "1.25",
220
+ "leading-snug": "1.375",
221
+ "leading-normal": "1.5",
222
+ "leading-relaxed": "1.625",
223
+ "leading-loose": "2",
224
+ "leading-3": "0.75rem",
225
+ "leading-4": "1rem",
226
+ "leading-5": "1.25rem",
227
+ "leading-6": "1.5rem",
228
+ "leading-7": "1.75rem",
229
+ "leading-8": "2rem",
230
+ "leading-9": "2.25rem",
231
+ "leading-10": "2.5rem",
232
+ }
233
+
234
+ LETTER_SPACING: Dict[str, str] = {
235
+ "tracking-tighter": "-0.05em",
236
+ "tracking-tight": "-0.025em",
237
+ "tracking-normal": "0em",
238
+ "tracking-wide": "0.025em",
239
+ "tracking-wider": "0.05em",
240
+ "tracking-widest": "0.1em",
241
+ }
242
+
243
+ TEXT_ALIGN: Dict[str, str] = {
244
+ "text-left": "left",
245
+ "text-center": "center",
246
+ "text-right": "right",
247
+ "text-justify": "justify",
248
+ "text-start": "start",
249
+ "text-end": "end",
250
+ }
251
+
252
+ TEXT_TRANSFORM: Dict[str, str] = {
253
+ "uppercase": "uppercase",
254
+ "lowercase": "lowercase",
255
+ "capitalize": "capitalize",
256
+ "normal-case": "none",
257
+ }
258
+
259
+ TEXT_DECORATION: Dict[str, str] = {
260
+ "underline": "underline",
261
+ "overline": "overline",
262
+ "line-through": "line-through",
263
+ "no-underline": "none",
264
+ }
265
+
266
+ TEXT_OVERFLOW: Dict[str, Dict[str, str]] = {
267
+ "truncate": {
268
+ "overflow": "hidden",
269
+ "text-overflow": "ellipsis",
270
+ "white-space": "nowrap",
271
+ },
272
+ "text-ellipsis": {"text-overflow": "ellipsis"},
273
+ "text-clip": {"text-overflow": "clip"},
274
+ }
275
+
276
+ WHITESPACE: Dict[str, str] = {
277
+ "whitespace-normal": "normal",
278
+ "whitespace-nowrap": "nowrap",
279
+ "whitespace-pre": "pre",
280
+ "whitespace-pre-line": "pre-line",
281
+ "whitespace-pre-wrap": "pre-wrap",
282
+ "whitespace-break-spaces": "break-spaces",
283
+ }
284
+
285
+ WORD_BREAK: Dict[str, Dict[str, str]] = {
286
+ "break-normal": {"overflow-wrap": "normal", "word-break": "normal"},
287
+ "break-words": {"overflow-wrap": "break-word"},
288
+ "break-all": {"word-break": "break-all"},
289
+ "break-keep": {"word-break": "keep-all"},
290
+ }
291
+
292
+ # Border radius
293
+ BORDER_RADIUS: Dict[str, str] = {
294
+ "rounded-none": "0px",
295
+ "rounded-sm": "0.125rem",
296
+ "rounded": "0.25rem",
297
+ "rounded-md": "0.375rem",
298
+ "rounded-lg": "0.5rem",
299
+ "rounded-xl": "0.75rem",
300
+ "rounded-2xl": "1rem",
301
+ "rounded-3xl": "1.5rem",
302
+ "rounded-full": "9999px",
303
+ }
304
+
305
+ BORDER_WIDTH: Dict[str, str] = {
306
+ "border": "1px",
307
+ "border-0": "0px",
308
+ "border-2": "2px",
309
+ "border-4": "4px",
310
+ "border-8": "8px",
311
+ }
312
+
313
+ BORDER_STYLE: Dict[str, str] = {
314
+ "border-solid": "solid",
315
+ "border-dashed": "dashed",
316
+ "border-dotted": "dotted",
317
+ "border-double": "double",
318
+ "border-hidden": "hidden",
319
+ "border-none": "none",
320
+ }
321
+
322
+ # Layout
323
+ DISPLAY: Dict[str, str] = {
324
+ "block": "block",
325
+ "inline-block": "inline-block",
326
+ "inline": "inline",
327
+ "flex": "flex",
328
+ "inline-flex": "inline-flex",
329
+ "table": "table",
330
+ "inline-table": "inline-table",
331
+ "table-caption": "table-caption",
332
+ "table-cell": "table-cell",
333
+ "table-column": "table-column",
334
+ "table-column-group": "table-column-group",
335
+ "table-footer-group": "table-footer-group",
336
+ "table-header-group": "table-header-group",
337
+ "table-row-group": "table-row-group",
338
+ "table-row": "table-row",
339
+ "flow-root": "flow-root",
340
+ "grid": "grid",
341
+ "inline-grid": "inline-grid",
342
+ "contents": "contents",
343
+ "list-item": "list-item",
344
+ "hidden": "none",
345
+ }
346
+
347
+ FLEX_DIRECTION: Dict[str, str] = {
348
+ "flex-row": "row",
349
+ "flex-row-reverse": "row-reverse",
350
+ "flex-col": "column",
351
+ "flex-col-reverse": "column-reverse",
352
+ }
353
+
354
+ FLEX_WRAP: Dict[str, str] = {
355
+ "flex-wrap": "wrap",
356
+ "flex-wrap-reverse": "wrap-reverse",
357
+ "flex-nowrap": "nowrap",
358
+ }
359
+
360
+ FLEX: Dict[str, str] = {
361
+ "flex-1": "1 1 0%",
362
+ "flex-auto": "1 1 auto",
363
+ "flex-initial": "0 1 auto",
364
+ "flex-none": "none",
365
+ }
366
+
367
+ FLEX_GROW: Dict[str, str] = {
368
+ "grow": "1",
369
+ "grow-0": "0",
370
+ }
371
+
372
+ FLEX_SHRINK: Dict[str, str] = {
373
+ "shrink": "1",
374
+ "shrink-0": "0",
375
+ }
376
+
377
+ JUSTIFY_CONTENT: Dict[str, str] = {
378
+ "justify-normal": "normal",
379
+ "justify-start": "flex-start",
380
+ "justify-end": "flex-end",
381
+ "justify-center": "center",
382
+ "justify-between": "space-between",
383
+ "justify-around": "space-around",
384
+ "justify-evenly": "space-evenly",
385
+ "justify-stretch": "stretch",
386
+ }
387
+
388
+ ALIGN_ITEMS: Dict[str, str] = {
389
+ "items-start": "flex-start",
390
+ "items-end": "flex-end",
391
+ "items-center": "center",
392
+ "items-baseline": "baseline",
393
+ "items-stretch": "stretch",
394
+ }
395
+
396
+ ALIGN_SELF: Dict[str, str] = {
397
+ "self-auto": "auto",
398
+ "self-start": "flex-start",
399
+ "self-end": "flex-end",
400
+ "self-center": "center",
401
+ "self-stretch": "stretch",
402
+ "self-baseline": "baseline",
403
+ }
404
+
405
+ ALIGN_CONTENT: Dict[str, str] = {
406
+ "content-normal": "normal",
407
+ "content-center": "center",
408
+ "content-start": "flex-start",
409
+ "content-end": "flex-end",
410
+ "content-between": "space-between",
411
+ "content-around": "space-around",
412
+ "content-evenly": "space-evenly",
413
+ "content-baseline": "baseline",
414
+ "content-stretch": "stretch",
415
+ }
416
+
417
+ # Positioning
418
+ POSITION: Dict[str, str] = {
419
+ "static": "static",
420
+ "fixed": "fixed",
421
+ "absolute": "absolute",
422
+ "relative": "relative",
423
+ "sticky": "sticky",
424
+ }
425
+
426
+ Z_INDEX: Dict[str, str] = {
427
+ "z-0": "0",
428
+ "z-10": "10",
429
+ "z-20": "20",
430
+ "z-30": "30",
431
+ "z-40": "40",
432
+ "z-50": "50",
433
+ "z-auto": "auto",
434
+ }
435
+
436
+ # Sizing
437
+ WIDTH_SPECIAL: Dict[str, str] = {
438
+ "w-auto": "auto",
439
+ "w-full": "100%",
440
+ "w-screen": "100vw",
441
+ "w-svw": "100svw",
442
+ "w-lvw": "100lvw",
443
+ "w-dvw": "100dvw",
444
+ "w-min": "min-content",
445
+ "w-max": "max-content",
446
+ "w-fit": "fit-content",
447
+ }
448
+
449
+ HEIGHT_SPECIAL: Dict[str, str] = {
450
+ "h-auto": "auto",
451
+ "h-full": "100%",
452
+ "h-screen": "100vh",
453
+ "h-svh": "100svh",
454
+ "h-lvh": "100lvh",
455
+ "h-dvh": "100dvh",
456
+ "h-min": "min-content",
457
+ "h-max": "max-content",
458
+ "h-fit": "fit-content",
459
+ }
460
+
461
+ MIN_WIDTH: Dict[str, str] = {
462
+ "min-w-0": "0px",
463
+ "min-w-full": "100%",
464
+ "min-w-min": "min-content",
465
+ "min-w-max": "max-content",
466
+ "min-w-fit": "fit-content",
467
+ }
468
+
469
+ MAX_WIDTH: Dict[str, str] = {
470
+ "max-w-0": "0rem",
471
+ "max-w-none": "none",
472
+ "max-w-xs": "20rem",
473
+ "max-w-sm": "24rem",
474
+ "max-w-md": "28rem",
475
+ "max-w-lg": "32rem",
476
+ "max-w-xl": "36rem",
477
+ "max-w-2xl": "42rem",
478
+ "max-w-3xl": "48rem",
479
+ "max-w-4xl": "56rem",
480
+ "max-w-5xl": "64rem",
481
+ "max-w-6xl": "72rem",
482
+ "max-w-7xl": "80rem",
483
+ "max-w-full": "100%",
484
+ "max-w-min": "min-content",
485
+ "max-w-max": "max-content",
486
+ "max-w-fit": "fit-content",
487
+ "max-w-prose": "65ch",
488
+ "max-w-screen-sm": "640px",
489
+ "max-w-screen-md": "768px",
490
+ "max-w-screen-lg": "1024px",
491
+ "max-w-screen-xl": "1280px",
492
+ "max-w-screen-2xl": "1536px",
493
+ }
494
+
495
+ MIN_HEIGHT: Dict[str, str] = {
496
+ "min-h-0": "0px",
497
+ "min-h-full": "100%",
498
+ "min-h-screen": "100vh",
499
+ "min-h-svh": "100svh",
500
+ "min-h-lvh": "100lvh",
501
+ "min-h-dvh": "100dvh",
502
+ "min-h-min": "min-content",
503
+ "min-h-max": "max-content",
504
+ "min-h-fit": "fit-content",
505
+ }
506
+
507
+ MAX_HEIGHT: Dict[str, str] = {
508
+ "max-h-none": "none",
509
+ "max-h-full": "100%",
510
+ "max-h-screen": "100vh",
511
+ "max-h-svh": "100svh",
512
+ "max-h-lvh": "100lvh",
513
+ "max-h-dvh": "100dvh",
514
+ "max-h-min": "min-content",
515
+ "max-h-max": "max-content",
516
+ "max-h-fit": "fit-content",
517
+ }
518
+
519
+ # Fraction widths
520
+ WIDTH_FRACTIONS: Dict[str, str] = {
521
+ "w-1/2": "50%",
522
+ "w-1/3": "33.333333%",
523
+ "w-2/3": "66.666667%",
524
+ "w-1/4": "25%",
525
+ "w-2/4": "50%",
526
+ "w-3/4": "75%",
527
+ "w-1/5": "20%",
528
+ "w-2/5": "40%",
529
+ "w-3/5": "60%",
530
+ "w-4/5": "80%",
531
+ "w-1/6": "16.666667%",
532
+ "w-2/6": "33.333333%",
533
+ "w-3/6": "50%",
534
+ "w-4/6": "66.666667%",
535
+ "w-5/6": "83.333333%",
536
+ "w-1/12": "8.333333%",
537
+ "w-2/12": "16.666667%",
538
+ "w-3/12": "25%",
539
+ "w-4/12": "33.333333%",
540
+ "w-5/12": "41.666667%",
541
+ "w-6/12": "50%",
542
+ "w-7/12": "58.333333%",
543
+ "w-8/12": "66.666667%",
544
+ "w-9/12": "75%",
545
+ "w-10/12": "83.333333%",
546
+ "w-11/12": "91.666667%",
547
+ }
548
+
549
+ HEIGHT_FRACTIONS: Dict[str, str] = {
550
+ "h-1/2": "50%",
551
+ "h-1/3": "33.333333%",
552
+ "h-2/3": "66.666667%",
553
+ "h-1/4": "25%",
554
+ "h-2/4": "50%",
555
+ "h-3/4": "75%",
556
+ "h-1/5": "20%",
557
+ "h-2/5": "40%",
558
+ "h-3/5": "60%",
559
+ "h-4/5": "80%",
560
+ "h-1/6": "16.666667%",
561
+ "h-2/6": "33.333333%",
562
+ "h-3/6": "50%",
563
+ "h-4/6": "66.666667%",
564
+ "h-5/6": "83.333333%",
565
+ }
566
+
567
+ # Effects
568
+ SHADOW: Dict[str, str] = {
569
+ "shadow-sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
570
+ "shadow": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
571
+ "shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
572
+ "shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
573
+ "shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
574
+ "shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
575
+ "shadow-inner": "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)",
576
+ "shadow-none": "0 0 #0000",
577
+ }
578
+
579
+ OPACITY: Dict[str, str] = {
580
+ "opacity-0": "0",
581
+ "opacity-5": "0.05",
582
+ "opacity-10": "0.1",
583
+ "opacity-15": "0.15",
584
+ "opacity-20": "0.2",
585
+ "opacity-25": "0.25",
586
+ "opacity-30": "0.3",
587
+ "opacity-35": "0.35",
588
+ "opacity-40": "0.4",
589
+ "opacity-45": "0.45",
590
+ "opacity-50": "0.5",
591
+ "opacity-55": "0.55",
592
+ "opacity-60": "0.6",
593
+ "opacity-65": "0.65",
594
+ "opacity-70": "0.7",
595
+ "opacity-75": "0.75",
596
+ "opacity-80": "0.8",
597
+ "opacity-85": "0.85",
598
+ "opacity-90": "0.9",
599
+ "opacity-95": "0.95",
600
+ "opacity-100": "1",
601
+ }
602
+
603
+ BLUR: Dict[str, str] = {
604
+ "blur-none": "blur(0)",
605
+ "blur-sm": "blur(4px)",
606
+ "blur": "blur(8px)",
607
+ "blur-md": "blur(12px)",
608
+ "blur-lg": "blur(16px)",
609
+ "blur-xl": "blur(24px)",
610
+ "blur-2xl": "blur(40px)",
611
+ "blur-3xl": "blur(64px)",
612
+ }
613
+
614
+ # Backgrounds
615
+ BG_GRADIENT: Dict[str, str] = {
616
+ "bg-gradient-to-t": "linear-gradient(to top, var(--tw-gradient-stops))",
617
+ "bg-gradient-to-tr": "linear-gradient(to top right, var(--tw-gradient-stops))",
618
+ "bg-gradient-to-r": "linear-gradient(to right, var(--tw-gradient-stops))",
619
+ "bg-gradient-to-br": "linear-gradient(to bottom right, var(--tw-gradient-stops))",
620
+ "bg-gradient-to-b": "linear-gradient(to bottom, var(--tw-gradient-stops))",
621
+ "bg-gradient-to-bl": "linear-gradient(to bottom left, var(--tw-gradient-stops))",
622
+ "bg-gradient-to-l": "linear-gradient(to left, var(--tw-gradient-stops))",
623
+ "bg-gradient-to-tl": "linear-gradient(to top left, var(--tw-gradient-stops))",
624
+ }
625
+
626
+ BG_SIZE: Dict[str, str] = {
627
+ "bg-auto": "auto",
628
+ "bg-cover": "cover",
629
+ "bg-contain": "contain",
630
+ }
631
+
632
+ BG_POSITION: Dict[str, str] = {
633
+ "bg-bottom": "bottom",
634
+ "bg-center": "center",
635
+ "bg-left": "left",
636
+ "bg-left-bottom": "left bottom",
637
+ "bg-left-top": "left top",
638
+ "bg-right": "right",
639
+ "bg-right-bottom": "right bottom",
640
+ "bg-right-top": "right top",
641
+ "bg-top": "top",
642
+ }
643
+
644
+ BG_REPEAT: Dict[str, str] = {
645
+ "bg-repeat": "repeat",
646
+ "bg-no-repeat": "no-repeat",
647
+ "bg-repeat-x": "repeat-x",
648
+ "bg-repeat-y": "repeat-y",
649
+ "bg-repeat-round": "round",
650
+ "bg-repeat-space": "space",
651
+ }
652
+
653
+ # Overflow
654
+ OVERFLOW: Dict[str, str] = {
655
+ "overflow-auto": "auto",
656
+ "overflow-hidden": "hidden",
657
+ "overflow-clip": "clip",
658
+ "overflow-visible": "visible",
659
+ "overflow-scroll": "scroll",
660
+ "overflow-x-auto": "auto",
661
+ "overflow-y-auto": "auto",
662
+ "overflow-x-hidden": "hidden",
663
+ "overflow-y-hidden": "hidden",
664
+ "overflow-x-clip": "clip",
665
+ "overflow-y-clip": "clip",
666
+ "overflow-x-visible": "visible",
667
+ "overflow-y-visible": "visible",
668
+ "overflow-x-scroll": "scroll",
669
+ "overflow-y-scroll": "scroll",
670
+ }
671
+
672
+ # Transitions
673
+ TRANSITION: Dict[str, Dict[str, str]] = {
674
+ "transition-none": {"transition-property": "none"},
675
+ "transition-all": {
676
+ "transition-property": "all",
677
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
678
+ "transition-duration": "150ms",
679
+ },
680
+ "transition": {
681
+ "transition-property": "color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter",
682
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
683
+ "transition-duration": "150ms",
684
+ },
685
+ "transition-colors": {
686
+ "transition-property": "color, background-color, border-color, text-decoration-color, fill, stroke",
687
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
688
+ "transition-duration": "150ms",
689
+ },
690
+ "transition-opacity": {
691
+ "transition-property": "opacity",
692
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
693
+ "transition-duration": "150ms",
694
+ },
695
+ "transition-shadow": {
696
+ "transition-property": "box-shadow",
697
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
698
+ "transition-duration": "150ms",
699
+ },
700
+ "transition-transform": {
701
+ "transition-property": "transform",
702
+ "transition-timing-function": "cubic-bezier(0.4, 0, 0.2, 1)",
703
+ "transition-duration": "150ms",
704
+ },
705
+ }
706
+
707
+ DURATION: Dict[str, str] = {
708
+ "duration-0": "0s",
709
+ "duration-75": "75ms",
710
+ "duration-100": "100ms",
711
+ "duration-150": "150ms",
712
+ "duration-200": "200ms",
713
+ "duration-300": "300ms",
714
+ "duration-500": "500ms",
715
+ "duration-700": "700ms",
716
+ "duration-1000": "1000ms",
717
+ }
718
+
719
+ TIMING_FUNCTION: Dict[str, str] = {
720
+ "ease-linear": "linear",
721
+ "ease-in": "cubic-bezier(0.4, 0, 1, 1)",
722
+ "ease-out": "cubic-bezier(0, 0, 0.2, 1)",
723
+ "ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
724
+ }
725
+
726
+ DELAY: Dict[str, str] = {
727
+ "delay-0": "0s",
728
+ "delay-75": "75ms",
729
+ "delay-100": "100ms",
730
+ "delay-150": "150ms",
731
+ "delay-200": "200ms",
732
+ "delay-300": "300ms",
733
+ "delay-500": "500ms",
734
+ "delay-700": "700ms",
735
+ "delay-1000": "1000ms",
736
+ }
737
+
738
+ # Interactivity
739
+ CURSOR: Dict[str, str] = {
740
+ "cursor-auto": "auto",
741
+ "cursor-default": "default",
742
+ "cursor-pointer": "pointer",
743
+ "cursor-wait": "wait",
744
+ "cursor-text": "text",
745
+ "cursor-move": "move",
746
+ "cursor-help": "help",
747
+ "cursor-not-allowed": "not-allowed",
748
+ "cursor-none": "none",
749
+ "cursor-context-menu": "context-menu",
750
+ "cursor-progress": "progress",
751
+ "cursor-cell": "cell",
752
+ "cursor-crosshair": "crosshair",
753
+ "cursor-vertical-text": "vertical-text",
754
+ "cursor-alias": "alias",
755
+ "cursor-copy": "copy",
756
+ "cursor-no-drop": "no-drop",
757
+ "cursor-grab": "grab",
758
+ "cursor-grabbing": "grabbing",
759
+ "cursor-all-scroll": "all-scroll",
760
+ "cursor-col-resize": "col-resize",
761
+ "cursor-row-resize": "row-resize",
762
+ "cursor-n-resize": "n-resize",
763
+ "cursor-e-resize": "e-resize",
764
+ "cursor-s-resize": "s-resize",
765
+ "cursor-w-resize": "w-resize",
766
+ "cursor-ne-resize": "ne-resize",
767
+ "cursor-nw-resize": "nw-resize",
768
+ "cursor-se-resize": "se-resize",
769
+ "cursor-sw-resize": "sw-resize",
770
+ "cursor-ew-resize": "ew-resize",
771
+ "cursor-ns-resize": "ns-resize",
772
+ "cursor-nesw-resize": "nesw-resize",
773
+ "cursor-nwse-resize": "nwse-resize",
774
+ "cursor-zoom-in": "zoom-in",
775
+ "cursor-zoom-out": "zoom-out",
776
+ }
777
+
778
+ USER_SELECT: Dict[str, str] = {
779
+ "select-none": "none",
780
+ "select-text": "text",
781
+ "select-all": "all",
782
+ "select-auto": "auto",
783
+ }
784
+
785
+ POINTER_EVENTS: Dict[str, str] = {
786
+ "pointer-events-none": "none",
787
+ "pointer-events-auto": "auto",
788
+ }
789
+
790
+ # Object fit/position
791
+ OBJECT_FIT: Dict[str, str] = {
792
+ "object-contain": "contain",
793
+ "object-cover": "cover",
794
+ "object-fill": "fill",
795
+ "object-none": "none",
796
+ "object-scale-down": "scale-down",
797
+ }
798
+
799
+ OBJECT_POSITION: Dict[str, str] = {
800
+ "object-bottom": "bottom",
801
+ "object-center": "center",
802
+ "object-left": "left",
803
+ "object-left-bottom": "left bottom",
804
+ "object-left-top": "left top",
805
+ "object-right": "right",
806
+ "object-right-bottom": "right bottom",
807
+ "object-right-top": "right top",
808
+ "object-top": "top",
809
+ }
810
+
811
+ # Visibility
812
+ VISIBILITY: Dict[str, str] = {
813
+ "visible": "visible",
814
+ "invisible": "hidden",
815
+ "collapse": "collapse",
816
+ }
817
+
818
+ # Box sizing
819
+ BOX_SIZING: Dict[str, str] = {
820
+ "box-border": "border-box",
821
+ "box-content": "content-box",
822
+ }
823
+
824
+ # Aspect ratio
825
+ ASPECT_RATIO: Dict[str, str] = {
826
+ "aspect-auto": "auto",
827
+ "aspect-square": "1 / 1",
828
+ "aspect-video": "16 / 9",
829
+ }
830
+
831
+ # Grid
832
+ GRID_TEMPLATE_COLUMNS: Dict[str, str] = {
833
+ "grid-cols-1": "repeat(1, minmax(0, 1fr))",
834
+ "grid-cols-2": "repeat(2, minmax(0, 1fr))",
835
+ "grid-cols-3": "repeat(3, minmax(0, 1fr))",
836
+ "grid-cols-4": "repeat(4, minmax(0, 1fr))",
837
+ "grid-cols-5": "repeat(5, minmax(0, 1fr))",
838
+ "grid-cols-6": "repeat(6, minmax(0, 1fr))",
839
+ "grid-cols-7": "repeat(7, minmax(0, 1fr))",
840
+ "grid-cols-8": "repeat(8, minmax(0, 1fr))",
841
+ "grid-cols-9": "repeat(9, minmax(0, 1fr))",
842
+ "grid-cols-10": "repeat(10, minmax(0, 1fr))",
843
+ "grid-cols-11": "repeat(11, minmax(0, 1fr))",
844
+ "grid-cols-12": "repeat(12, minmax(0, 1fr))",
845
+ "grid-cols-none": "none",
846
+ "grid-cols-subgrid": "subgrid",
847
+ }
848
+
849
+ GRID_TEMPLATE_ROWS: Dict[str, str] = {
850
+ "grid-rows-1": "repeat(1, minmax(0, 1fr))",
851
+ "grid-rows-2": "repeat(2, minmax(0, 1fr))",
852
+ "grid-rows-3": "repeat(3, minmax(0, 1fr))",
853
+ "grid-rows-4": "repeat(4, minmax(0, 1fr))",
854
+ "grid-rows-5": "repeat(5, minmax(0, 1fr))",
855
+ "grid-rows-6": "repeat(6, minmax(0, 1fr))",
856
+ "grid-rows-none": "none",
857
+ "grid-rows-subgrid": "subgrid",
858
+ }
859
+
860
+ GRID_COLUMN: Dict[str, str] = {
861
+ "col-auto": "auto",
862
+ "col-span-1": "span 1 / span 1",
863
+ "col-span-2": "span 2 / span 2",
864
+ "col-span-3": "span 3 / span 3",
865
+ "col-span-4": "span 4 / span 4",
866
+ "col-span-5": "span 5 / span 5",
867
+ "col-span-6": "span 6 / span 6",
868
+ "col-span-7": "span 7 / span 7",
869
+ "col-span-8": "span 8 / span 8",
870
+ "col-span-9": "span 9 / span 9",
871
+ "col-span-10": "span 10 / span 10",
872
+ "col-span-11": "span 11 / span 11",
873
+ "col-span-12": "span 12 / span 12",
874
+ "col-span-full": "1 / -1",
875
+ }
876
+
877
+ GRID_ROW: Dict[str, str] = {
878
+ "row-auto": "auto",
879
+ "row-span-1": "span 1 / span 1",
880
+ "row-span-2": "span 2 / span 2",
881
+ "row-span-3": "span 3 / span 3",
882
+ "row-span-4": "span 4 / span 4",
883
+ "row-span-5": "span 5 / span 5",
884
+ "row-span-6": "span 6 / span 6",
885
+ "row-span-full": "1 / -1",
886
+ }
887
+
888
+ GRID_AUTO_FLOW: Dict[str, str] = {
889
+ "grid-flow-row": "row",
890
+ "grid-flow-col": "column",
891
+ "grid-flow-dense": "dense",
892
+ "grid-flow-row-dense": "row dense",
893
+ "grid-flow-col-dense": "column dense",
894
+ }
895
+
896
+ GRID_AUTO_COLUMNS: Dict[str, str] = {
897
+ "auto-cols-auto": "auto",
898
+ "auto-cols-min": "min-content",
899
+ "auto-cols-max": "max-content",
900
+ "auto-cols-fr": "minmax(0, 1fr)",
901
+ }
902
+
903
+ GRID_AUTO_ROWS: Dict[str, str] = {
904
+ "auto-rows-auto": "auto",
905
+ "auto-rows-min": "min-content",
906
+ "auto-rows-max": "max-content",
907
+ "auto-rows-fr": "minmax(0, 1fr)",
908
+ }
909
+
910
+ PLACE_CONTENT: Dict[str, str] = {
911
+ "place-content-center": "center",
912
+ "place-content-start": "start",
913
+ "place-content-end": "end",
914
+ "place-content-between": "space-between",
915
+ "place-content-around": "space-around",
916
+ "place-content-evenly": "space-evenly",
917
+ "place-content-baseline": "baseline",
918
+ "place-content-stretch": "stretch",
919
+ }
920
+
921
+ PLACE_ITEMS: Dict[str, str] = {
922
+ "place-items-start": "start",
923
+ "place-items-end": "end",
924
+ "place-items-center": "center",
925
+ "place-items-baseline": "baseline",
926
+ "place-items-stretch": "stretch",
927
+ }
928
+
929
+ PLACE_SELF: Dict[str, str] = {
930
+ "place-self-auto": "auto",
931
+ "place-self-start": "start",
932
+ "place-self-end": "end",
933
+ "place-self-center": "center",
934
+ "place-self-stretch": "stretch",
935
+ }
936
+
937
+ # Ring (outline-like)
938
+ RING_WIDTH: Dict[str, Dict[str, str]] = {
939
+ "ring-0": {"box-shadow": "var(--tw-ring-inset) 0 0 0 0px var(--tw-ring-color)"},
940
+ "ring-1": {"box-shadow": "var(--tw-ring-inset) 0 0 0 1px var(--tw-ring-color)"},
941
+ "ring-2": {"box-shadow": "var(--tw-ring-inset) 0 0 0 2px var(--tw-ring-color)"},
942
+ "ring": {"box-shadow": "var(--tw-ring-inset) 0 0 0 3px var(--tw-ring-color)"},
943
+ "ring-4": {"box-shadow": "var(--tw-ring-inset) 0 0 0 4px var(--tw-ring-color)"},
944
+ "ring-8": {"box-shadow": "var(--tw-ring-inset) 0 0 0 8px var(--tw-ring-color)"},
945
+ "ring-inset": {"--tw-ring-inset": "inset"},
946
+ }
947
+
948
+ OUTLINE_STYLE: Dict[str, Dict[str, str]] = {
949
+ "outline-none": {"outline": "2px solid transparent", "outline-offset": "2px"},
950
+ "outline": {"outline-style": "solid"},
951
+ "outline-dashed": {"outline-style": "dashed"},
952
+ "outline-dotted": {"outline-style": "dotted"},
953
+ "outline-double": {"outline-style": "double"},
954
+ }
955
+
956
+ OUTLINE_WIDTH: Dict[str, str] = {
957
+ "outline-0": "0px",
958
+ "outline-1": "1px",
959
+ "outline-2": "2px",
960
+ "outline-4": "4px",
961
+ "outline-8": "8px",
962
+ }
963
+
964
+ OUTLINE_OFFSET: Dict[str, str] = {
965
+ "outline-offset-0": "0px",
966
+ "outline-offset-1": "1px",
967
+ "outline-offset-2": "2px",
968
+ "outline-offset-4": "4px",
969
+ "outline-offset-8": "8px",
970
+ }
971
+
972
+
973
+ # =============================================================================
974
+ # UTILITY FUNCTIONS
975
+ # =============================================================================
976
+
977
+ def hex_to_rgba(hex_color: str, opacity: float) -> str:
978
+ """Convert hex color to rgba string.
979
+
980
+ Args:
981
+ hex_color: Hex color string (e.g., "#3b82f6")
982
+ opacity: Opacity value from 0-100
983
+
984
+ Returns:
985
+ RGBA string (e.g., "rgba(59, 130, 246, 0.5)")
986
+ """
987
+ hex_color = hex_color.lstrip("#")
988
+ r = int(hex_color[0:2], 16)
989
+ g = int(hex_color[2:4], 16)
990
+ b = int(hex_color[4:6], 16)
991
+ return f"rgba({r}, {g}, {b}, {opacity / 100})"
992
+
993
+
994
+ def get_color(color_name: str, shade: str = None) -> str:
995
+ """Get hex color from color name and optional shade.
996
+
997
+ Args:
998
+ color_name: Color name (e.g., "blue", "slate", "white")
999
+ shade: Optional shade (e.g., "500", "900")
1000
+
1001
+ Returns:
1002
+ Hex color string or special color value
1003
+ """
1004
+ if color_name in SPECIAL_COLORS:
1005
+ return SPECIAL_COLORS[color_name]
1006
+
1007
+ if color_name in COLORS and shade:
1008
+ return COLORS[color_name].get(shade, COLORS[color_name]["500"])
1009
+
1010
+ return None
1011
+
1012
+
1013
+ def parse_color_class(class_name: str) -> Tuple[str, str, float]:
1014
+ """Parse a color class like 'bg-blue-500/50' into components.
1015
+
1016
+ Args:
1017
+ class_name: Tailwind class name
1018
+
1019
+ Returns:
1020
+ Tuple of (property_prefix, hex_color, opacity)
1021
+ opacity is 100 if not specified
1022
+ """
1023
+ # Check for opacity modifier
1024
+ opacity = 100.0
1025
+ if "/" in class_name:
1026
+ class_name, opacity_str = class_name.rsplit("/", 1)
1027
+ try:
1028
+ opacity = float(opacity_str)
1029
+ except ValueError:
1030
+ opacity = 100.0
1031
+
1032
+ # Parse the class
1033
+ parts = class_name.split("-")
1034
+ if len(parts) < 2:
1035
+ return None, None, opacity
1036
+
1037
+ prefix = parts[0]
1038
+ color_parts = parts[1:]
1039
+
1040
+ # Handle special colors (bg-white, text-black, etc.)
1041
+ if len(color_parts) == 1 and color_parts[0] in SPECIAL_COLORS:
1042
+ return prefix, SPECIAL_COLORS[color_parts[0]], opacity
1043
+
1044
+ # Handle regular colors (bg-blue-500, text-slate-400, etc.)
1045
+ if len(color_parts) >= 2:
1046
+ color_name = color_parts[0]
1047
+ shade = color_parts[1]
1048
+ if color_name in COLORS and shade in COLORS[color_name]:
1049
+ return prefix, COLORS[color_name][shade], opacity
1050
+
1051
+ return None, None, opacity
1052
+
1053
+
1054
+ def _resolve_single_class(class_name: str) -> Dict[str, str]:
1055
+ """Convert a single Tailwind class to CSS properties.
1056
+
1057
+ Args:
1058
+ class_name: Single Tailwind class name (without variant prefix)
1059
+
1060
+ Returns:
1061
+ Dictionary of CSS properties
1062
+ """
1063
+ result = {}
1064
+
1065
+ # Check static mappings first
1066
+ if class_name in FONT_SIZE:
1067
+ return FONT_SIZE[class_name].copy()
1068
+
1069
+ if class_name in FONT_WEIGHT:
1070
+ return {"font-weight": FONT_WEIGHT[class_name]}
1071
+
1072
+ if class_name in LINE_HEIGHT:
1073
+ return {"line-height": LINE_HEIGHT[class_name]}
1074
+
1075
+ if class_name in LETTER_SPACING:
1076
+ return {"letter-spacing": LETTER_SPACING[class_name]}
1077
+
1078
+ if class_name in TEXT_ALIGN:
1079
+ return {"text-align": TEXT_ALIGN[class_name]}
1080
+
1081
+ if class_name in TEXT_TRANSFORM:
1082
+ return {"text-transform": TEXT_TRANSFORM[class_name]}
1083
+
1084
+ if class_name in TEXT_DECORATION:
1085
+ return {"text-decoration-line": TEXT_DECORATION[class_name]}
1086
+
1087
+ if class_name in TEXT_OVERFLOW:
1088
+ return TEXT_OVERFLOW[class_name].copy()
1089
+
1090
+ if class_name in WHITESPACE:
1091
+ return {"white-space": WHITESPACE[class_name]}
1092
+
1093
+ if class_name in WORD_BREAK:
1094
+ return WORD_BREAK[class_name].copy()
1095
+
1096
+ if class_name in DISPLAY:
1097
+ return {"display": DISPLAY[class_name]}
1098
+
1099
+ if class_name in FLEX_DIRECTION:
1100
+ return {"flex-direction": FLEX_DIRECTION[class_name]}
1101
+
1102
+ if class_name in FLEX_WRAP:
1103
+ return {"flex-wrap": FLEX_WRAP[class_name]}
1104
+
1105
+ if class_name in FLEX:
1106
+ return {"flex": FLEX[class_name]}
1107
+
1108
+ if class_name in FLEX_GROW:
1109
+ return {"flex-grow": FLEX_GROW[class_name]}
1110
+
1111
+ if class_name in FLEX_SHRINK:
1112
+ return {"flex-shrink": FLEX_SHRINK[class_name]}
1113
+
1114
+ if class_name in JUSTIFY_CONTENT:
1115
+ return {"justify-content": JUSTIFY_CONTENT[class_name]}
1116
+
1117
+ if class_name in ALIGN_ITEMS:
1118
+ return {"align-items": ALIGN_ITEMS[class_name]}
1119
+
1120
+ if class_name in ALIGN_SELF:
1121
+ return {"align-self": ALIGN_SELF[class_name]}
1122
+
1123
+ if class_name in ALIGN_CONTENT:
1124
+ return {"align-content": ALIGN_CONTENT[class_name]}
1125
+
1126
+ if class_name in POSITION:
1127
+ return {"position": POSITION[class_name]}
1128
+
1129
+ if class_name in Z_INDEX:
1130
+ return {"z-index": Z_INDEX[class_name]}
1131
+
1132
+ if class_name in WIDTH_SPECIAL:
1133
+ return {"width": WIDTH_SPECIAL[class_name]}
1134
+
1135
+ if class_name in HEIGHT_SPECIAL:
1136
+ return {"height": HEIGHT_SPECIAL[class_name]}
1137
+
1138
+ if class_name in WIDTH_FRACTIONS:
1139
+ return {"width": WIDTH_FRACTIONS[class_name]}
1140
+
1141
+ if class_name in HEIGHT_FRACTIONS:
1142
+ return {"height": HEIGHT_FRACTIONS[class_name]}
1143
+
1144
+ if class_name in MIN_WIDTH:
1145
+ return {"min-width": MIN_WIDTH[class_name]}
1146
+
1147
+ if class_name in MAX_WIDTH:
1148
+ return {"max-width": MAX_WIDTH[class_name]}
1149
+
1150
+ if class_name in MIN_HEIGHT:
1151
+ return {"min-height": MIN_HEIGHT[class_name]}
1152
+
1153
+ if class_name in MAX_HEIGHT:
1154
+ return {"max-height": MAX_HEIGHT[class_name]}
1155
+
1156
+ if class_name in SHADOW:
1157
+ return {"box-shadow": SHADOW[class_name]}
1158
+
1159
+ if class_name in OPACITY:
1160
+ return {"opacity": OPACITY[class_name]}
1161
+
1162
+ if class_name in BLUR:
1163
+ return {"filter": BLUR[class_name]}
1164
+
1165
+ if class_name in BG_GRADIENT:
1166
+ return {"background-image": BG_GRADIENT[class_name]}
1167
+
1168
+ if class_name in BG_SIZE:
1169
+ return {"background-size": BG_SIZE[class_name]}
1170
+
1171
+ if class_name in BG_POSITION:
1172
+ return {"background-position": BG_POSITION[class_name]}
1173
+
1174
+ if class_name in BG_REPEAT:
1175
+ return {"background-repeat": BG_REPEAT[class_name]}
1176
+
1177
+ if class_name in TRANSITION:
1178
+ return TRANSITION[class_name].copy()
1179
+
1180
+ if class_name in DURATION:
1181
+ return {"transition-duration": DURATION[class_name]}
1182
+
1183
+ if class_name in TIMING_FUNCTION:
1184
+ return {"transition-timing-function": TIMING_FUNCTION[class_name]}
1185
+
1186
+ if class_name in DELAY:
1187
+ return {"transition-delay": DELAY[class_name]}
1188
+
1189
+ if class_name in CURSOR:
1190
+ return {"cursor": CURSOR[class_name]}
1191
+
1192
+ if class_name in USER_SELECT:
1193
+ return {"user-select": USER_SELECT[class_name]}
1194
+
1195
+ if class_name in POINTER_EVENTS:
1196
+ return {"pointer-events": POINTER_EVENTS[class_name]}
1197
+
1198
+ if class_name in OBJECT_FIT:
1199
+ return {"object-fit": OBJECT_FIT[class_name]}
1200
+
1201
+ if class_name in OBJECT_POSITION:
1202
+ return {"object-position": OBJECT_POSITION[class_name]}
1203
+
1204
+ if class_name in VISIBILITY:
1205
+ return {"visibility": VISIBILITY[class_name]}
1206
+
1207
+ if class_name in BOX_SIZING:
1208
+ return {"box-sizing": BOX_SIZING[class_name]}
1209
+
1210
+ if class_name in ASPECT_RATIO:
1211
+ return {"aspect-ratio": ASPECT_RATIO[class_name]}
1212
+
1213
+ if class_name in GRID_TEMPLATE_COLUMNS:
1214
+ return {"grid-template-columns": GRID_TEMPLATE_COLUMNS[class_name]}
1215
+
1216
+ if class_name in GRID_TEMPLATE_ROWS:
1217
+ return {"grid-template-rows": GRID_TEMPLATE_ROWS[class_name]}
1218
+
1219
+ if class_name in GRID_COLUMN:
1220
+ return {"grid-column": GRID_COLUMN[class_name]}
1221
+
1222
+ if class_name in GRID_ROW:
1223
+ return {"grid-row": GRID_ROW[class_name]}
1224
+
1225
+ if class_name in GRID_AUTO_FLOW:
1226
+ return {"grid-auto-flow": GRID_AUTO_FLOW[class_name]}
1227
+
1228
+ if class_name in GRID_AUTO_COLUMNS:
1229
+ return {"grid-auto-columns": GRID_AUTO_COLUMNS[class_name]}
1230
+
1231
+ if class_name in GRID_AUTO_ROWS:
1232
+ return {"grid-auto-rows": GRID_AUTO_ROWS[class_name]}
1233
+
1234
+ if class_name in PLACE_CONTENT:
1235
+ return {"place-content": PLACE_CONTENT[class_name]}
1236
+
1237
+ if class_name in PLACE_ITEMS:
1238
+ return {"place-items": PLACE_ITEMS[class_name]}
1239
+
1240
+ if class_name in PLACE_SELF:
1241
+ return {"place-self": PLACE_SELF[class_name]}
1242
+
1243
+ if class_name in RING_WIDTH:
1244
+ return RING_WIDTH[class_name].copy()
1245
+
1246
+ if class_name in OUTLINE_STYLE:
1247
+ return OUTLINE_STYLE[class_name].copy()
1248
+
1249
+ if class_name in OUTLINE_WIDTH:
1250
+ return {"outline-width": OUTLINE_WIDTH[class_name]}
1251
+
1252
+ if class_name in OUTLINE_OFFSET:
1253
+ return {"outline-offset": OUTLINE_OFFSET[class_name]}
1254
+
1255
+ # Handle overflow (needs special handling for x/y variants)
1256
+ if class_name.startswith("overflow-"):
1257
+ if class_name.startswith("overflow-x-"):
1258
+ val = class_name.replace("overflow-x-", "")
1259
+ return {"overflow-x": OVERFLOW.get(f"overflow-{val}", val)}
1260
+ elif class_name.startswith("overflow-y-"):
1261
+ val = class_name.replace("overflow-y-", "")
1262
+ return {"overflow-y": OVERFLOW.get(f"overflow-{val}", val)}
1263
+ elif class_name in OVERFLOW:
1264
+ return {"overflow": OVERFLOW[class_name]}
1265
+
1266
+ # Handle border radius
1267
+ if class_name.startswith("rounded"):
1268
+ # Check for directional variants
1269
+ if class_name in BORDER_RADIUS:
1270
+ return {"border-radius": BORDER_RADIUS[class_name]}
1271
+
1272
+ # Parse directional rounded classes like rounded-t-lg, rounded-tl-xl
1273
+ match = re.match(r"rounded-([trbl]{1,2})-?(.+)?", class_name)
1274
+ if match:
1275
+ direction = match.group(1)
1276
+ size = match.group(2) or ""
1277
+ size_key = f"rounded-{size}" if size else "rounded"
1278
+ radius = BORDER_RADIUS.get(size_key, "0.25rem")
1279
+
1280
+ direction_map = {
1281
+ "t": ["border-top-left-radius", "border-top-right-radius"],
1282
+ "r": ["border-top-right-radius", "border-bottom-right-radius"],
1283
+ "b": ["border-bottom-left-radius", "border-bottom-right-radius"],
1284
+ "l": ["border-top-left-radius", "border-bottom-left-radius"],
1285
+ "tl": ["border-top-left-radius"],
1286
+ "tr": ["border-top-right-radius"],
1287
+ "bl": ["border-bottom-left-radius"],
1288
+ "br": ["border-bottom-right-radius"],
1289
+ }
1290
+ if direction in direction_map:
1291
+ for prop in direction_map[direction]:
1292
+ result[prop] = radius
1293
+ return result
1294
+
1295
+ # Handle border width
1296
+ if class_name.startswith("border"):
1297
+ # Border width
1298
+ if class_name in BORDER_WIDTH:
1299
+ return {"border-width": BORDER_WIDTH[class_name]}
1300
+
1301
+ # Border style
1302
+ if class_name in BORDER_STYLE:
1303
+ return {"border-style": BORDER_STYLE[class_name]}
1304
+
1305
+ # Check if this is a border color class first (border-{color}-{shade})
1306
+ # Must check this BEFORE directional patterns to avoid matching border-rose as border-r
1307
+ prefix, hex_color, opacity = parse_color_class(class_name)
1308
+ if hex_color and prefix == "border":
1309
+ if opacity < 100:
1310
+ color_value = hex_to_rgba(hex_color, opacity) if hex_color.startswith("#") else hex_color
1311
+ else:
1312
+ color_value = hex_color
1313
+ return {"border-color": color_value}
1314
+
1315
+ # Directional border widths - only match if followed by optional digit or end of string
1316
+ # Pattern: border-t, border-r, border-b, border-l, border-x, border-y
1317
+ # With optional width: border-t-2, border-r-4, etc.
1318
+ match = re.match(r"^border-([trblxy])(?:-(\d+))?$", class_name)
1319
+ if match:
1320
+ direction = match.group(1)
1321
+ width = match.group(2)
1322
+ width_val = f"{width}px" if width else "1px"
1323
+
1324
+ direction_map = {
1325
+ "t": ["border-top-width"],
1326
+ "r": ["border-right-width"],
1327
+ "b": ["border-bottom-width"],
1328
+ "l": ["border-left-width"],
1329
+ "x": ["border-left-width", "border-right-width"],
1330
+ "y": ["border-top-width", "border-bottom-width"],
1331
+ }
1332
+ if direction in direction_map:
1333
+ for prop in direction_map[direction]:
1334
+ result[prop] = width_val
1335
+ return result
1336
+
1337
+ # Handle spacing classes (padding, margin, gap)
1338
+ spacing_patterns = [
1339
+ (r"^p-(.+)$", "padding"),
1340
+ (r"^px-(.+)$", ["padding-left", "padding-right"]),
1341
+ (r"^py-(.+)$", ["padding-top", "padding-bottom"]),
1342
+ (r"^pt-(.+)$", "padding-top"),
1343
+ (r"^pr-(.+)$", "padding-right"),
1344
+ (r"^pb-(.+)$", "padding-bottom"),
1345
+ (r"^pl-(.+)$", "padding-left"),
1346
+ (r"^ps-(.+)$", "padding-inline-start"),
1347
+ (r"^pe-(.+)$", "padding-inline-end"),
1348
+ (r"^m-(.+)$", "margin"),
1349
+ (r"^mx-(.+)$", ["margin-left", "margin-right"]),
1350
+ (r"^my-(.+)$", ["margin-top", "margin-bottom"]),
1351
+ (r"^mt-(.+)$", "margin-top"),
1352
+ (r"^mr-(.+)$", "margin-right"),
1353
+ (r"^mb-(.+)$", "margin-bottom"),
1354
+ (r"^ml-(.+)$", "margin-left"),
1355
+ (r"^ms-(.+)$", "margin-inline-start"),
1356
+ (r"^me-(.+)$", "margin-inline-end"),
1357
+ (r"^gap-(.+)$", "gap"),
1358
+ (r"^gap-x-(.+)$", "column-gap"),
1359
+ (r"^gap-y-(.+)$", "row-gap"),
1360
+ (r"^w-(.+)$", "width"),
1361
+ (r"^h-(.+)$", "height"),
1362
+ (r"^min-w-(.+)$", "min-width"),
1363
+ (r"^max-w-(.+)$", "max-width"),
1364
+ (r"^min-h-(.+)$", "min-height"),
1365
+ (r"^max-h-(.+)$", "max-height"),
1366
+ (r"^inset-(.+)$", ["top", "right", "bottom", "left"]),
1367
+ (r"^inset-x-(.+)$", ["left", "right"]),
1368
+ (r"^inset-y-(.+)$", ["top", "bottom"]),
1369
+ (r"^top-(.+)$", "top"),
1370
+ (r"^right-(.+)$", "right"),
1371
+ (r"^bottom-(.+)$", "bottom"),
1372
+ (r"^left-(.+)$", "left"),
1373
+ (r"^start-(.+)$", "inset-inline-start"),
1374
+ (r"^end-(.+)$", "inset-inline-end"),
1375
+ ]
1376
+
1377
+ for pattern, css_prop in spacing_patterns:
1378
+ match = re.match(pattern, class_name)
1379
+ if match:
1380
+ value_key = match.group(1)
1381
+
1382
+ # Handle negative values
1383
+ negative = value_key.startswith("-")
1384
+ if negative:
1385
+ value_key = value_key[1:]
1386
+
1387
+ # Handle 'auto' value
1388
+ if value_key == "auto":
1389
+ css_value = "auto"
1390
+ elif value_key in SPACING:
1391
+ css_value = SPACING[value_key]
1392
+ if negative:
1393
+ css_value = f"-{css_value}"
1394
+ else:
1395
+ continue
1396
+
1397
+ if isinstance(css_prop, list):
1398
+ for prop in css_prop:
1399
+ result[prop] = css_value
1400
+ else:
1401
+ result[css_prop] = css_value
1402
+ return result
1403
+
1404
+ # Handle space-x and space-y (child spacing)
1405
+ if class_name.startswith("space-x-"):
1406
+ value_key = class_name[8:]
1407
+ if value_key in SPACING:
1408
+ # This creates a CSS variable approach
1409
+ return {"--tw-space-x-reverse": "0", "column-gap": SPACING[value_key]}
1410
+
1411
+ if class_name.startswith("space-y-"):
1412
+ value_key = class_name[8:]
1413
+ if value_key in SPACING:
1414
+ return {"--tw-space-y-reverse": "0", "row-gap": SPACING[value_key]}
1415
+
1416
+ # Handle color classes (bg-, text-, border-, ring-, from-, to-, via-)
1417
+ prefix, hex_color, opacity = parse_color_class(class_name)
1418
+ if hex_color:
1419
+ if opacity < 100:
1420
+ color_value = hex_to_rgba(hex_color, opacity) if hex_color.startswith("#") else hex_color
1421
+ else:
1422
+ color_value = hex_color
1423
+
1424
+ color_properties = {
1425
+ "bg": "background-color",
1426
+ "text": "color",
1427
+ "border": "border-color",
1428
+ "ring": "--tw-ring-color",
1429
+ "outline": "outline-color",
1430
+ "accent": "accent-color",
1431
+ "caret": "caret-color",
1432
+ "fill": "fill",
1433
+ "stroke": "stroke",
1434
+ "from": "--tw-gradient-from",
1435
+ "to": "--tw-gradient-to",
1436
+ "via": "--tw-gradient-via",
1437
+ }
1438
+
1439
+ if prefix in color_properties:
1440
+ return {color_properties[prefix]: color_value}
1441
+
1442
+ return result
1443
+
1444
+
1445
+ def tw(*classes: str) -> Dict[str, str]:
1446
+ """Convert Tailwind classes to a CSS dictionary (base styles only).
1447
+
1448
+ Args:
1449
+ *classes: Tailwind CSS class names
1450
+
1451
+ Returns:
1452
+ Dictionary mapping CSS property names to values
1453
+
1454
+ Example:
1455
+ >>> tw("bg-slate-800", "rounded-lg", "p-4")
1456
+ {'background-color': '#1e293b', 'border-radius': '0.5rem', 'padding': '1rem'}
1457
+ """
1458
+ result = {}
1459
+ for class_name in classes:
1460
+ # Skip variant prefixes for the simple tw() function
1461
+ if ":" in class_name:
1462
+ base_class = class_name.split(":")[-1]
1463
+ else:
1464
+ base_class = class_name
1465
+
1466
+ css = _resolve_single_class(base_class)
1467
+ result.update(css)
1468
+
1469
+ return result
1470
+
1471
+
1472
+ def parse_tailwind_classes(classes: Union[Tuple[str, ...], list]) -> Dict[str, Dict[str, str]]:
1473
+ """Parse Tailwind classes into categorized CSS dictionaries.
1474
+
1475
+ Supports variant prefixes: hover:, focus:, active:
1476
+
1477
+ Args:
1478
+ classes: Tuple or list of Tailwind class names
1479
+
1480
+ Returns:
1481
+ Dictionary with keys 'base', 'hover', 'focus', 'active',
1482
+ each containing a CSS properties dictionary
1483
+
1484
+ Example:
1485
+ >>> parse_tailwind_classes(("bg-slate-800", "hover:bg-slate-700", "p-4"))
1486
+ {
1487
+ 'base': {'background-color': '#1e293b', 'padding': '1rem'},
1488
+ 'hover': {'background-color': '#334155'},
1489
+ 'focus': {},
1490
+ 'active': {}
1491
+ }
1492
+ """
1493
+ result = {
1494
+ "base": {},
1495
+ "hover": {},
1496
+ "focus": {},
1497
+ "active": {},
1498
+ }
1499
+
1500
+ for class_name in classes:
1501
+ # Parse variant prefix
1502
+ variant = "base"
1503
+ base_class = class_name
1504
+
1505
+ if class_name.startswith("hover:"):
1506
+ variant = "hover"
1507
+ base_class = class_name[6:]
1508
+ elif class_name.startswith("focus:"):
1509
+ variant = "focus"
1510
+ base_class = class_name[6:]
1511
+ elif class_name.startswith("active:"):
1512
+ variant = "active"
1513
+ base_class = class_name[7:]
1514
+
1515
+ # Resolve the class
1516
+ css = _resolve_single_class(base_class)
1517
+ result[variant].update(css)
1518
+
1519
+ return result
1520
+
1521
+
1522
+ def tailwind_to_css(classes: str) -> Dict[str, str]:
1523
+ """Convert a space-separated string of Tailwind classes to CSS.
1524
+
1525
+ Args:
1526
+ classes: Space-separated Tailwind class names
1527
+
1528
+ Returns:
1529
+ Dictionary mapping CSS property names to values
1530
+
1531
+ Example:
1532
+ >>> tailwind_to_css("bg-blue-500 text-white p-4 rounded-lg")
1533
+ {'background-color': '#3b82f6', 'color': '#ffffff', 'padding': '1rem', 'border-radius': '0.5rem'}
1534
+ """
1535
+ class_list = classes.split()
1536
+ return tw(*class_list)