@cwcss/crosswind 0.1.5 → 0.2.0
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/LICENSE.md +21 -0
- package/README.md +52 -0
- package/dist/bin/cli.js +14615 -0
- package/dist/build.d.ts +24 -0
- package/dist/config.d.ts +5 -0
- package/dist/generator.d.ts +31 -0
- package/dist/index.d.ts +10 -0
- package/dist/parser.d.ts +42 -0
- package/dist/plugin.d.ts +22 -0
- package/dist/preflight-forms.d.ts +5 -0
- package/dist/preflight.d.ts +2 -0
- package/dist/rules-advanced.d.ts +27 -0
- package/dist/rules-effects.d.ts +25 -0
- package/dist/rules-forms.d.ts +7 -0
- package/dist/rules-grid.d.ts +13 -0
- package/dist/rules-interactivity.d.ts +41 -0
- package/dist/rules-layout.d.ts +26 -0
- package/dist/rules-transforms.d.ts +33 -0
- package/dist/rules-typography.d.ts +41 -0
- package/dist/rules.d.ts +39 -0
- package/dist/scanner.d.ts +18 -0
- package/dist/src/index.js +12848 -0
- package/dist/transformer-compile-class.d.ts +37 -0
- package/{src/types.ts → dist/types.d.ts} +17 -86
- package/package.json +2 -16
- package/PLUGIN.md +0 -235
- package/benchmark/framework-comparison.bench.ts +0 -850
- package/bin/cli.ts +0 -365
- package/bin/crosswind +0 -0
- package/bin/headwind +0 -0
- package/build.ts +0 -8
- package/crosswind.config.ts +0 -9
- package/example/comprehensive.html +0 -70
- package/example/index.html +0 -21
- package/example/output.css +0 -236
- package/examples/plugin/README.md +0 -112
- package/examples/plugin/build.ts +0 -32
- package/examples/plugin/src/index.html +0 -34
- package/examples/plugin/src/index.ts +0 -7
- package/headwind +0 -2
- package/src/build.ts +0 -101
- package/src/config.ts +0 -529
- package/src/generator.ts +0 -2173
- package/src/index.ts +0 -10
- package/src/parser.ts +0 -1471
- package/src/plugin.ts +0 -118
- package/src/preflight-forms.ts +0 -229
- package/src/preflight.ts +0 -388
- package/src/rules-advanced.ts +0 -477
- package/src/rules-effects.ts +0 -461
- package/src/rules-forms.ts +0 -103
- package/src/rules-grid.ts +0 -241
- package/src/rules-interactivity.ts +0 -525
- package/src/rules-layout.ts +0 -385
- package/src/rules-transforms.ts +0 -412
- package/src/rules-typography.ts +0 -486
- package/src/rules.ts +0 -809
- package/src/scanner.ts +0 -84
- package/src/transformer-compile-class.ts +0 -275
- package/test/advanced-features.test.ts +0 -911
- package/test/arbitrary.test.ts +0 -396
- package/test/attributify.test.ts +0 -592
- package/test/bracket-syntax.test.ts +0 -1133
- package/test/build.test.ts +0 -99
- package/test/colors.test.ts +0 -934
- package/test/flexbox.test.ts +0 -669
- package/test/generator.test.ts +0 -597
- package/test/grid.test.ts +0 -584
- package/test/layout.test.ts +0 -404
- package/test/modifiers.test.ts +0 -417
- package/test/parser.test.ts +0 -564
- package/test/performance-regression.test.ts +0 -376
- package/test/performance.test.ts +0 -568
- package/test/plugin.test.ts +0 -160
- package/test/scanner.test.ts +0 -94
- package/test/sizing.test.ts +0 -481
- package/test/spacing.test.ts +0 -394
- package/test/transformer-compile-class.test.ts +0 -287
- package/test/transforms.test.ts +0 -448
- package/test/typography.test.ts +0 -632
- package/test/variants-form-states.test.ts +0 -225
- package/test/variants-group-peer.test.ts +0 -66
- package/test/variants-media.test.ts +0 -213
- package/test/variants-positional.test.ts +0 -58
- package/test/variants-pseudo-elements.test.ts +0 -47
- package/test/variants-state.test.ts +0 -62
- package/tsconfig.json +0 -18
package/src/generator.ts
DELETED
|
@@ -1,2173 +0,0 @@
|
|
|
1
|
-
import type { CSSRule, CrosswindConfig, ParsedClass } from './types'
|
|
2
|
-
import type { UtilityRule } from './rules'
|
|
3
|
-
import { parseClass } from './parser'
|
|
4
|
-
import { builtInRules } from './rules'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Deep merge objects
|
|
8
|
-
*/
|
|
9
|
-
function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {
|
|
10
|
-
const result = { ...target }
|
|
11
|
-
for (const key in source) {
|
|
12
|
-
const sourceValue = source[key]
|
|
13
|
-
const targetValue = result[key]
|
|
14
|
-
if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {
|
|
15
|
-
result[key] = deepMerge(targetValue, sourceValue)
|
|
16
|
-
}
|
|
17
|
-
else if (sourceValue !== undefined) {
|
|
18
|
-
result[key] = sourceValue as any
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return result
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// =============================================================================
|
|
25
|
-
// STATIC UTILITY MAPS - Pre-computed at module load for O(1) lookup
|
|
26
|
-
// These never change and are shared across all CSSGenerator instances
|
|
27
|
-
// =============================================================================
|
|
28
|
-
|
|
29
|
-
// Display utilities - direct raw class to CSS value
|
|
30
|
-
const DISPLAY_MAP: Record<string, Record<string, string>> = {
|
|
31
|
-
'block': { display: 'block' },
|
|
32
|
-
'inline-block': { display: 'inline-block' },
|
|
33
|
-
'inline': { display: 'inline' },
|
|
34
|
-
'flex': { display: 'flex' },
|
|
35
|
-
'inline-flex': { display: 'inline-flex' },
|
|
36
|
-
'grid': { display: 'grid' },
|
|
37
|
-
'inline-grid': { display: 'inline-grid' },
|
|
38
|
-
'hidden': { display: 'none' },
|
|
39
|
-
'none': { display: 'none' },
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Flex direction - direct raw class to CSS
|
|
43
|
-
const FLEX_DIRECTION_MAP: Record<string, Record<string, string>> = {
|
|
44
|
-
'flex-row': { 'flex-direction': 'row' },
|
|
45
|
-
'flex-row-reverse': { 'flex-direction': 'row-reverse' },
|
|
46
|
-
'flex-col': { 'flex-direction': 'column' },
|
|
47
|
-
'flex-col-reverse': { 'flex-direction': 'column-reverse' },
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Flex wrap - direct raw class to CSS
|
|
51
|
-
const FLEX_WRAP_MAP: Record<string, Record<string, string>> = {
|
|
52
|
-
'flex-wrap': { 'flex-wrap': 'wrap' },
|
|
53
|
-
'flex-wrap-reverse': { 'flex-wrap': 'wrap-reverse' },
|
|
54
|
-
'flex-nowrap': { 'flex-wrap': 'nowrap' },
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Flex values - direct raw class to CSS
|
|
58
|
-
const FLEX_VALUES_MAP: Record<string, Record<string, string>> = {
|
|
59
|
-
'flex-1': { flex: '1 1 0%' },
|
|
60
|
-
'flex-auto': { flex: '1 1 auto' },
|
|
61
|
-
'flex-initial': { flex: '0 1 auto' },
|
|
62
|
-
'flex-none': { flex: 'none' },
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Grow/Shrink - direct raw class to CSS
|
|
66
|
-
const GROW_SHRINK_MAP: Record<string, Record<string, string>> = {
|
|
67
|
-
'grow': { 'flex-grow': '1' },
|
|
68
|
-
'grow-0': { 'flex-grow': '0' },
|
|
69
|
-
'shrink': { 'flex-shrink': '1' },
|
|
70
|
-
'shrink-0': { 'flex-shrink': '0' },
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Justify content - utility="justify", value lookup
|
|
74
|
-
const JUSTIFY_CONTENT_VALUES: Record<string, string> = {
|
|
75
|
-
start: 'flex-start',
|
|
76
|
-
end: 'flex-end',
|
|
77
|
-
center: 'center',
|
|
78
|
-
between: 'space-between',
|
|
79
|
-
around: 'space-around',
|
|
80
|
-
evenly: 'space-evenly',
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Align items - utility="items", value lookup
|
|
84
|
-
const ALIGN_ITEMS_VALUES: Record<string, string> = {
|
|
85
|
-
start: 'flex-start',
|
|
86
|
-
end: 'flex-end',
|
|
87
|
-
center: 'center',
|
|
88
|
-
baseline: 'baseline',
|
|
89
|
-
stretch: 'stretch',
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Align content - utility="content", value lookup
|
|
93
|
-
const ALIGN_CONTENT_VALUES: Record<string, string> = {
|
|
94
|
-
normal: 'normal',
|
|
95
|
-
center: 'center',
|
|
96
|
-
start: 'flex-start',
|
|
97
|
-
end: 'flex-end',
|
|
98
|
-
between: 'space-between',
|
|
99
|
-
around: 'space-around',
|
|
100
|
-
evenly: 'space-evenly',
|
|
101
|
-
baseline: 'baseline',
|
|
102
|
-
stretch: 'stretch',
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Align self - utility="self", value lookup
|
|
106
|
-
const ALIGN_SELF_VALUES: Record<string, string> = {
|
|
107
|
-
auto: 'auto',
|
|
108
|
-
start: 'flex-start',
|
|
109
|
-
end: 'flex-end',
|
|
110
|
-
center: 'center',
|
|
111
|
-
stretch: 'stretch',
|
|
112
|
-
baseline: 'baseline',
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Border style - direct raw class to CSS
|
|
116
|
-
const BORDER_STYLE_MAP: Record<string, Record<string, string>> = {
|
|
117
|
-
'border-solid': { 'border-style': 'solid' },
|
|
118
|
-
'border-dashed': { 'border-style': 'dashed' },
|
|
119
|
-
'border-dotted': { 'border-style': 'dotted' },
|
|
120
|
-
'border-double': { 'border-style': 'double' },
|
|
121
|
-
'border-none': { 'border-style': 'none' },
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Transform utilities - direct raw class to CSS
|
|
125
|
-
const TRANSFORM_MAP: Record<string, Record<string, string>> = {
|
|
126
|
-
'transform': { transform: 'translate(var(--hw-translate-x), var(--hw-translate-y)) rotate(var(--hw-rotate)) skewX(var(--hw-skew-x)) skewY(var(--hw-skew-y)) scaleX(var(--hw-scale-x)) scaleY(var(--hw-scale-y))' },
|
|
127
|
-
'transform-cpu': { transform: 'translate(var(--hw-translate-x), var(--hw-translate-y)) rotate(var(--hw-rotate)) skewX(var(--hw-skew-x)) skewY(var(--hw-skew-y)) scaleX(var(--hw-scale-x)) scaleY(var(--hw-scale-y))' },
|
|
128
|
-
'transform-gpu': { transform: 'translate3d(var(--hw-translate-x), var(--hw-translate-y), 0) rotate(var(--hw-rotate)) skewX(var(--hw-skew-x)) skewY(var(--hw-skew-y)) scaleX(var(--hw-scale-x)) scaleY(var(--hw-scale-y))' },
|
|
129
|
-
'transform-none': { transform: 'none' },
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Transition utilities - direct raw class to CSS
|
|
133
|
-
const TRANSITION_MAP: Record<string, Record<string, string>> = {
|
|
134
|
-
'transition-none': { 'transition-property': 'none' },
|
|
135
|
-
'transition-all': { 'transition-property': 'all' },
|
|
136
|
-
'transition': { 'transition-property': 'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter' },
|
|
137
|
-
'transition-colors': { 'transition-property': 'color, background-color, border-color, text-decoration-color, fill, stroke' },
|
|
138
|
-
'transition-opacity': { 'transition-property': 'opacity' },
|
|
139
|
-
'transition-shadow': { 'transition-property': 'box-shadow' },
|
|
140
|
-
'transition-transform': { 'transition-property': 'transform' },
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Timing functions - direct raw class to CSS
|
|
144
|
-
const TIMING_MAP: Record<string, Record<string, string>> = {
|
|
145
|
-
'ease-linear': { 'transition-timing-function': 'linear' },
|
|
146
|
-
'ease-in': { 'transition-timing-function': 'cubic-bezier(0.4, 0, 1, 1)' },
|
|
147
|
-
'ease-out': { 'transition-timing-function': 'cubic-bezier(0, 0, 0.2, 1)' },
|
|
148
|
-
'ease-in-out': { 'transition-timing-function': 'cubic-bezier(0.4, 0, 0.2, 1)' },
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Animation presets
|
|
152
|
-
const ANIMATION_MAP: Record<string, Record<string, string>> = {
|
|
153
|
-
'animate-none': { animation: 'none' },
|
|
154
|
-
'animate-spin': { animation: 'spin 1s linear infinite' },
|
|
155
|
-
'animate-ping': { animation: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite' },
|
|
156
|
-
'animate-pulse': { animation: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite' },
|
|
157
|
-
'animate-bounce': { animation: 'bounce 1s infinite' },
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Transform origin - utility="origin", value lookup
|
|
161
|
-
const TRANSFORM_ORIGIN_VALUES: Record<string, string> = {
|
|
162
|
-
'center': 'center',
|
|
163
|
-
'top': 'top',
|
|
164
|
-
'top-right': 'top right',
|
|
165
|
-
'right': 'right',
|
|
166
|
-
'bottom-right': 'bottom right',
|
|
167
|
-
'bottom': 'bottom',
|
|
168
|
-
'bottom-left': 'bottom left',
|
|
169
|
-
'left': 'left',
|
|
170
|
-
'top-left': 'top left',
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Grid template columns - utility="grid-cols", value lookup
|
|
174
|
-
const GRID_COLS_VALUES: Record<string, string> = {
|
|
175
|
-
'1': 'repeat(1, minmax(0, 1fr))',
|
|
176
|
-
'2': 'repeat(2, minmax(0, 1fr))',
|
|
177
|
-
'3': 'repeat(3, minmax(0, 1fr))',
|
|
178
|
-
'4': 'repeat(4, minmax(0, 1fr))',
|
|
179
|
-
'5': 'repeat(5, minmax(0, 1fr))',
|
|
180
|
-
'6': 'repeat(6, minmax(0, 1fr))',
|
|
181
|
-
'7': 'repeat(7, minmax(0, 1fr))',
|
|
182
|
-
'8': 'repeat(8, minmax(0, 1fr))',
|
|
183
|
-
'9': 'repeat(9, minmax(0, 1fr))',
|
|
184
|
-
'10': 'repeat(10, minmax(0, 1fr))',
|
|
185
|
-
'11': 'repeat(11, minmax(0, 1fr))',
|
|
186
|
-
'12': 'repeat(12, minmax(0, 1fr))',
|
|
187
|
-
'none': 'none',
|
|
188
|
-
'subgrid': 'subgrid',
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Grid template rows - utility="grid-rows", value lookup
|
|
192
|
-
const GRID_ROWS_VALUES: Record<string, string> = {
|
|
193
|
-
'1': 'repeat(1, minmax(0, 1fr))',
|
|
194
|
-
'2': 'repeat(2, minmax(0, 1fr))',
|
|
195
|
-
'3': 'repeat(3, minmax(0, 1fr))',
|
|
196
|
-
'4': 'repeat(4, minmax(0, 1fr))',
|
|
197
|
-
'5': 'repeat(5, minmax(0, 1fr))',
|
|
198
|
-
'6': 'repeat(6, minmax(0, 1fr))',
|
|
199
|
-
'none': 'none',
|
|
200
|
-
'subgrid': 'subgrid',
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Grid column span - utility="col", value lookup
|
|
204
|
-
const GRID_COL_VALUES: Record<string, string> = {
|
|
205
|
-
'auto': 'auto',
|
|
206
|
-
'span-1': 'span 1 / span 1',
|
|
207
|
-
'span-2': 'span 2 / span 2',
|
|
208
|
-
'span-3': 'span 3 / span 3',
|
|
209
|
-
'span-4': 'span 4 / span 4',
|
|
210
|
-
'span-5': 'span 5 / span 5',
|
|
211
|
-
'span-6': 'span 6 / span 6',
|
|
212
|
-
'span-7': 'span 7 / span 7',
|
|
213
|
-
'span-8': 'span 8 / span 8',
|
|
214
|
-
'span-9': 'span 9 / span 9',
|
|
215
|
-
'span-10': 'span 10 / span 10',
|
|
216
|
-
'span-11': 'span 11 / span 11',
|
|
217
|
-
'span-12': 'span 12 / span 12',
|
|
218
|
-
'span-full': '1 / -1',
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Grid row span - utility="row", value lookup
|
|
222
|
-
const GRID_ROW_VALUES: Record<string, string> = {
|
|
223
|
-
'auto': 'auto',
|
|
224
|
-
'span-1': 'span 1 / span 1',
|
|
225
|
-
'span-2': 'span 2 / span 2',
|
|
226
|
-
'span-3': 'span 3 / span 3',
|
|
227
|
-
'span-4': 'span 4 / span 4',
|
|
228
|
-
'span-5': 'span 5 / span 5',
|
|
229
|
-
'span-6': 'span 6 / span 6',
|
|
230
|
-
'span-full': '1 / -1',
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Grid auto flow - utility="grid-flow", value lookup
|
|
234
|
-
const GRID_FLOW_VALUES: Record<string, string> = {
|
|
235
|
-
'row': 'row',
|
|
236
|
-
'col': 'column',
|
|
237
|
-
'dense': 'dense',
|
|
238
|
-
'row-dense': 'row dense',
|
|
239
|
-
'col-dense': 'column dense',
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Auto cols/rows - utility="auto-cols"/"auto-rows", value lookup
|
|
243
|
-
const AUTO_COLS_ROWS_VALUES: Record<string, string> = {
|
|
244
|
-
'auto': 'auto',
|
|
245
|
-
'min': 'min-content',
|
|
246
|
-
'max': 'max-content',
|
|
247
|
-
'fr': 'minmax(0, 1fr)',
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Place content/items/self - utility="place", value lookup
|
|
251
|
-
const PLACE_CONTENT_VALUES: Record<string, string> = {
|
|
252
|
-
'center': 'center',
|
|
253
|
-
'start': 'start',
|
|
254
|
-
'end': 'end',
|
|
255
|
-
'between': 'space-between',
|
|
256
|
-
'around': 'space-around',
|
|
257
|
-
'evenly': 'space-evenly',
|
|
258
|
-
'stretch': 'stretch',
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Ring utilities - direct raw class to CSS
|
|
262
|
-
const RING_MAP: Record<string, Record<string, string>> = {
|
|
263
|
-
'ring': { 'box-shadow': '0 0 0 3px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
264
|
-
'ring-0': { 'box-shadow': '0 0 0 0px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
265
|
-
'ring-1': { 'box-shadow': '0 0 0 1px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
266
|
-
'ring-2': { 'box-shadow': '0 0 0 2px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
267
|
-
'ring-4': { 'box-shadow': '0 0 0 4px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
268
|
-
'ring-8': { 'box-shadow': '0 0 0 8px var(--hw-ring-color, rgba(59, 130, 246, 0.5))' },
|
|
269
|
-
'ring-inset': { '--hw-ring-inset': 'inset' },
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Shadow utilities - use CSS variable system for shadow color support
|
|
273
|
-
// --hw-shadow holds the default shadow, --hw-shadow-colored replaces colors with var(--hw-shadow-color)
|
|
274
|
-
// box-shadow references --hw-shadow which can be swapped to --hw-shadow-colored by a shadow-{color} utility
|
|
275
|
-
const SHADOW_MAP: Record<string, Record<string, string>> = {
|
|
276
|
-
'shadow-sm': {
|
|
277
|
-
'--hw-shadow': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
|
|
278
|
-
'--hw-shadow-colored': '0 1px 2px 0 var(--hw-shadow-color)',
|
|
279
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
280
|
-
},
|
|
281
|
-
'shadow': {
|
|
282
|
-
'--hw-shadow': '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
|
|
283
|
-
'--hw-shadow-colored': '0 1px 3px 0 var(--hw-shadow-color), 0 1px 2px -1px var(--hw-shadow-color)',
|
|
284
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
285
|
-
},
|
|
286
|
-
'shadow-md': {
|
|
287
|
-
'--hw-shadow': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
|
|
288
|
-
'--hw-shadow-colored': '0 4px 6px -1px var(--hw-shadow-color), 0 2px 4px -2px var(--hw-shadow-color)',
|
|
289
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
290
|
-
},
|
|
291
|
-
'shadow-lg': {
|
|
292
|
-
'--hw-shadow': '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',
|
|
293
|
-
'--hw-shadow-colored': '0 10px 15px -3px var(--hw-shadow-color), 0 4px 6px -4px var(--hw-shadow-color)',
|
|
294
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
295
|
-
},
|
|
296
|
-
'shadow-xl': {
|
|
297
|
-
'--hw-shadow': '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)',
|
|
298
|
-
'--hw-shadow-colored': '0 20px 25px -5px var(--hw-shadow-color), 0 8px 10px -6px var(--hw-shadow-color)',
|
|
299
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
300
|
-
},
|
|
301
|
-
'shadow-2xl': {
|
|
302
|
-
'--hw-shadow': '0 25px 50px -12px rgb(0 0 0 / 0.25)',
|
|
303
|
-
'--hw-shadow-colored': '0 25px 50px -12px var(--hw-shadow-color)',
|
|
304
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
305
|
-
},
|
|
306
|
-
'shadow-inner': {
|
|
307
|
-
'--hw-shadow': 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)',
|
|
308
|
-
'--hw-shadow-colored': 'inset 0 2px 4px 0 var(--hw-shadow-color)',
|
|
309
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
310
|
-
},
|
|
311
|
-
'shadow-none': {
|
|
312
|
-
'--hw-shadow': '0 0 #0000',
|
|
313
|
-
'box-shadow': 'var(--hw-ring-offset-shadow, 0 0 #0000), var(--hw-ring-shadow, 0 0 #0000), var(--hw-shadow)',
|
|
314
|
-
},
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Border radius - direct raw class to CSS
|
|
318
|
-
const BORDER_RADIUS_MAP: Record<string, Record<string, string>> = {
|
|
319
|
-
'rounded-none': { 'border-radius': '0px' },
|
|
320
|
-
'rounded-sm': { 'border-radius': '0.125rem' },
|
|
321
|
-
'rounded': { 'border-radius': '0.25rem' },
|
|
322
|
-
'rounded-md': { 'border-radius': '0.375rem' },
|
|
323
|
-
'rounded-lg': { 'border-radius': '0.5rem' },
|
|
324
|
-
'rounded-xl': { 'border-radius': '0.75rem' },
|
|
325
|
-
'rounded-2xl': { 'border-radius': '1rem' },
|
|
326
|
-
'rounded-3xl': { 'border-radius': '1.5rem' },
|
|
327
|
-
'rounded-full': { 'border-radius': '9999px' },
|
|
328
|
-
// Corner-specific rounded utilities
|
|
329
|
-
'rounded-t-none': { 'border-top-left-radius': '0px', 'border-top-right-radius': '0px' },
|
|
330
|
-
'rounded-t-sm': { 'border-top-left-radius': '0.125rem', 'border-top-right-radius': '0.125rem' },
|
|
331
|
-
'rounded-t-lg': { 'border-top-left-radius': '0.5rem', 'border-top-right-radius': '0.5rem' },
|
|
332
|
-
'rounded-r-lg': { 'border-top-right-radius': '0.5rem', 'border-bottom-right-radius': '0.5rem' },
|
|
333
|
-
'rounded-b-lg': { 'border-bottom-left-radius': '0.5rem', 'border-bottom-right-radius': '0.5rem' },
|
|
334
|
-
'rounded-l-lg': { 'border-top-left-radius': '0.5rem', 'border-bottom-left-radius': '0.5rem' },
|
|
335
|
-
'rounded-tl-lg': { 'border-top-left-radius': '0.5rem' },
|
|
336
|
-
'rounded-tr-lg': { 'border-top-right-radius': '0.5rem' },
|
|
337
|
-
'rounded-br-lg': { 'border-bottom-right-radius': '0.5rem' },
|
|
338
|
-
'rounded-bl-lg': { 'border-bottom-left-radius': '0.5rem' },
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Border width - direct raw class to CSS
|
|
342
|
-
const BORDER_WIDTH_MAP: Record<string, Record<string, string>> = {
|
|
343
|
-
'border': { 'border-width': '1px' },
|
|
344
|
-
'border-0': { 'border-width': '0px' },
|
|
345
|
-
'border-2': { 'border-width': '2px' },
|
|
346
|
-
'border-4': { 'border-width': '4px' },
|
|
347
|
-
'border-8': { 'border-width': '8px' },
|
|
348
|
-
// Side-specific border width
|
|
349
|
-
'border-t': { 'border-top-width': '1px' },
|
|
350
|
-
'border-r': { 'border-right-width': '1px' },
|
|
351
|
-
'border-b': { 'border-bottom-width': '1px' },
|
|
352
|
-
'border-l': { 'border-left-width': '1px' },
|
|
353
|
-
'border-t-0': { 'border-top-width': '0px' },
|
|
354
|
-
'border-r-0': { 'border-right-width': '0px' },
|
|
355
|
-
'border-b-0': { 'border-bottom-width': '0px' },
|
|
356
|
-
'border-l-0': { 'border-left-width': '0px' },
|
|
357
|
-
'border-t-2': { 'border-top-width': '2px' },
|
|
358
|
-
'border-r-2': { 'border-right-width': '2px' },
|
|
359
|
-
'border-b-2': { 'border-bottom-width': '2px' },
|
|
360
|
-
'border-l-2': { 'border-left-width': '2px' },
|
|
361
|
-
'border-t-4': { 'border-top-width': '4px' },
|
|
362
|
-
'border-r-4': { 'border-right-width': '4px' },
|
|
363
|
-
'border-b-4': { 'border-bottom-width': '4px' },
|
|
364
|
-
'border-l-4': { 'border-left-width': '4px' },
|
|
365
|
-
'border-x': { 'border-left-width': '1px', 'border-right-width': '1px' },
|
|
366
|
-
'border-y': { 'border-top-width': '1px', 'border-bottom-width': '1px' },
|
|
367
|
-
'border-x-0': { 'border-left-width': '0px', 'border-right-width': '0px' },
|
|
368
|
-
'border-y-0': { 'border-top-width': '0px', 'border-bottom-width': '0px' },
|
|
369
|
-
'border-x-2': { 'border-left-width': '2px', 'border-right-width': '2px' },
|
|
370
|
-
'border-y-2': { 'border-top-width': '2px', 'border-bottom-width': '2px' },
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Ring offset - direct raw class to CSS
|
|
374
|
-
const RING_OFFSET_MAP: Record<string, Record<string, string>> = {
|
|
375
|
-
'ring-offset-0': { '--hw-ring-offset-width': '0px' },
|
|
376
|
-
'ring-offset-1': { '--hw-ring-offset-width': '1px' },
|
|
377
|
-
'ring-offset-2': { '--hw-ring-offset-width': '2px' },
|
|
378
|
-
'ring-offset-4': { '--hw-ring-offset-width': '4px' },
|
|
379
|
-
'ring-offset-8': { '--hw-ring-offset-width': '8px' },
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Opacity utilities - direct raw class to CSS
|
|
383
|
-
const OPACITY_MAP: Record<string, Record<string, string>> = {
|
|
384
|
-
'opacity-0': { opacity: '0' },
|
|
385
|
-
'opacity-5': { opacity: '0.05' },
|
|
386
|
-
'opacity-10': { opacity: '0.1' },
|
|
387
|
-
'opacity-20': { opacity: '0.2' },
|
|
388
|
-
'opacity-25': { opacity: '0.25' },
|
|
389
|
-
'opacity-30': { opacity: '0.3' },
|
|
390
|
-
'opacity-40': { opacity: '0.4' },
|
|
391
|
-
'opacity-50': { opacity: '0.5' },
|
|
392
|
-
'opacity-60': { opacity: '0.6' },
|
|
393
|
-
'opacity-70': { opacity: '0.7' },
|
|
394
|
-
'opacity-75': { opacity: '0.75' },
|
|
395
|
-
'opacity-80': { opacity: '0.8' },
|
|
396
|
-
'opacity-90': { opacity: '0.9' },
|
|
397
|
-
'opacity-95': { opacity: '0.95' },
|
|
398
|
-
'opacity-100': { opacity: '1' },
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Pre-computed spacing values for O(1) lookup
|
|
402
|
-
const SPACING_VALUES: Record<string, string> = {
|
|
403
|
-
'0': '0',
|
|
404
|
-
'px': '1px',
|
|
405
|
-
'0.5': '0.125rem',
|
|
406
|
-
'1': '0.25rem',
|
|
407
|
-
'1.5': '0.375rem',
|
|
408
|
-
'2': '0.5rem',
|
|
409
|
-
'2.5': '0.625rem',
|
|
410
|
-
'3': '0.75rem',
|
|
411
|
-
'3.5': '0.875rem',
|
|
412
|
-
'4': '1rem',
|
|
413
|
-
'5': '1.25rem',
|
|
414
|
-
'6': '1.5rem',
|
|
415
|
-
'7': '1.75rem',
|
|
416
|
-
'8': '2rem',
|
|
417
|
-
'9': '2.25rem',
|
|
418
|
-
'10': '2.5rem',
|
|
419
|
-
'11': '2.75rem',
|
|
420
|
-
'12': '3rem',
|
|
421
|
-
'14': '3.5rem',
|
|
422
|
-
'16': '4rem',
|
|
423
|
-
'20': '5rem',
|
|
424
|
-
'24': '6rem',
|
|
425
|
-
'28': '7rem',
|
|
426
|
-
'32': '8rem',
|
|
427
|
-
'36': '9rem',
|
|
428
|
-
'40': '10rem',
|
|
429
|
-
'44': '11rem',
|
|
430
|
-
'48': '12rem',
|
|
431
|
-
'52': '13rem',
|
|
432
|
-
'56': '14rem',
|
|
433
|
-
'60': '15rem',
|
|
434
|
-
'64': '16rem',
|
|
435
|
-
'72': '18rem',
|
|
436
|
-
'80': '20rem',
|
|
437
|
-
'96': '24rem',
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Size values (spacing + special values)
|
|
441
|
-
const SIZE_VALUES: Record<string, string> = {
|
|
442
|
-
...SPACING_VALUES,
|
|
443
|
-
'auto': 'auto',
|
|
444
|
-
'full': '100%',
|
|
445
|
-
'screen': '100vw',
|
|
446
|
-
'min': 'min-content',
|
|
447
|
-
'max': 'max-content',
|
|
448
|
-
'fit': 'fit-content',
|
|
449
|
-
// Common fractions (using same precision as original implementation)
|
|
450
|
-
'1/2': '50%',
|
|
451
|
-
'1/3': '33.33333333333333%',
|
|
452
|
-
'2/3': '66.66666666666666%',
|
|
453
|
-
'1/4': '25%',
|
|
454
|
-
'2/4': '50%',
|
|
455
|
-
'3/4': '75%',
|
|
456
|
-
'1/5': '20%',
|
|
457
|
-
'2/5': '40%',
|
|
458
|
-
'3/5': '60%',
|
|
459
|
-
'4/5': '80%',
|
|
460
|
-
'1/6': '16.666666666666664%',
|
|
461
|
-
'2/6': '33.33333333333333%',
|
|
462
|
-
'3/6': '50%',
|
|
463
|
-
'4/6': '66.66666666666666%',
|
|
464
|
-
'5/6': '83.33333333333334%',
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Pre-computed color values for common Tailwind colors (O(1) lookup)
|
|
468
|
-
// These are the most commonly used colors in the benchmark
|
|
469
|
-
const COMMON_COLORS: Record<string, string> = {
|
|
470
|
-
// Gray
|
|
471
|
-
'gray-50': 'oklch(98.5% 0.002 247.839)', 'gray-100': 'oklch(96.7% 0.003 264.542)',
|
|
472
|
-
'gray-200': 'oklch(92.8% 0.006 264.531)', 'gray-300': 'oklch(87.2% 0.01 258.338)',
|
|
473
|
-
'gray-400': 'oklch(70.7% 0.022 261.325)', 'gray-500': 'oklch(55.1% 0.027 264.364)',
|
|
474
|
-
'gray-600': 'oklch(44.6% 0.03 256.802)', 'gray-700': 'oklch(37.3% 0.034 259.733)',
|
|
475
|
-
'gray-800': 'oklch(27.8% 0.033 256.848)', 'gray-900': 'oklch(21% 0.034 264.665)',
|
|
476
|
-
'gray-950': 'oklch(13% 0.028 261.692)',
|
|
477
|
-
// Red
|
|
478
|
-
'red-50': 'oklch(97.1% 0.013 17.38)', 'red-100': 'oklch(93.6% 0.032 17.717)',
|
|
479
|
-
'red-200': 'oklch(88.5% 0.062 18.334)', 'red-300': 'oklch(80.8% 0.114 19.571)',
|
|
480
|
-
'red-400': 'oklch(70.4% 0.191 22.216)', 'red-500': 'oklch(63.7% 0.237 25.331)',
|
|
481
|
-
'red-600': 'oklch(57.7% 0.245 27.325)', 'red-700': 'oklch(50.5% 0.213 27.518)',
|
|
482
|
-
'red-800': 'oklch(44.4% 0.177 26.899)', 'red-900': 'oklch(39.6% 0.141 25.723)',
|
|
483
|
-
'red-950': 'oklch(25.8% 0.092 26.042)',
|
|
484
|
-
// Blue
|
|
485
|
-
'blue-50': 'oklch(97% 0.014 254.604)', 'blue-100': 'oklch(93.2% 0.032 255.585)',
|
|
486
|
-
'blue-200': 'oklch(88.2% 0.059 254.128)', 'blue-300': 'oklch(80.9% 0.105 251.813)',
|
|
487
|
-
'blue-400': 'oklch(70.7% 0.165 254.624)', 'blue-500': 'oklch(62.3% 0.214 259.815)',
|
|
488
|
-
'blue-600': 'oklch(54.6% 0.245 262.881)', 'blue-700': 'oklch(48.8% 0.243 264.376)',
|
|
489
|
-
'blue-800': 'oklch(42.4% 0.199 265.638)', 'blue-900': 'oklch(37.9% 0.146 265.522)',
|
|
490
|
-
'blue-950': 'oklch(28.2% 0.091 267.935)',
|
|
491
|
-
// Green
|
|
492
|
-
'green-50': 'oklch(98.2% 0.018 155.826)', 'green-100': 'oklch(96.2% 0.044 156.743)',
|
|
493
|
-
'green-200': 'oklch(92.5% 0.084 155.995)', 'green-300': 'oklch(87.1% 0.15 154.449)',
|
|
494
|
-
'green-400': 'oklch(79.2% 0.209 151.711)', 'green-500': 'oklch(72.3% 0.219 149.579)',
|
|
495
|
-
'green-600': 'oklch(62.7% 0.194 149.214)', 'green-700': 'oklch(52.7% 0.154 150.069)',
|
|
496
|
-
'green-800': 'oklch(44.8% 0.119 151.328)', 'green-900': 'oklch(39.3% 0.095 152.535)',
|
|
497
|
-
'green-950': 'oklch(26.6% 0.065 152.934)',
|
|
498
|
-
// Yellow
|
|
499
|
-
'yellow-50': 'oklch(98.7% 0.026 102.212)', 'yellow-100': 'oklch(97.3% 0.071 103.193)',
|
|
500
|
-
'yellow-200': 'oklch(94.5% 0.129 101.54)', 'yellow-300': 'oklch(90.5% 0.182 98.111)',
|
|
501
|
-
'yellow-400': 'oklch(85.2% 0.199 91.936)', 'yellow-500': 'oklch(79.5% 0.184 86.047)',
|
|
502
|
-
'yellow-600': 'oklch(68.1% 0.162 75.834)', 'yellow-700': 'oklch(55.4% 0.135 66.442)',
|
|
503
|
-
'yellow-800': 'oklch(47.6% 0.114 61.907)', 'yellow-900': 'oklch(42.1% 0.095 57.708)',
|
|
504
|
-
'yellow-950': 'oklch(28.6% 0.066 53.813)',
|
|
505
|
-
// Purple
|
|
506
|
-
'purple-50': 'oklch(97.7% 0.014 308.299)', 'purple-100': 'oklch(94.6% 0.033 307.174)',
|
|
507
|
-
'purple-200': 'oklch(90.2% 0.063 306.703)', 'purple-300': 'oklch(82.7% 0.119 306.383)',
|
|
508
|
-
'purple-400': 'oklch(71.4% 0.203 305.504)', 'purple-500': 'oklch(62.7% 0.265 303.9)',
|
|
509
|
-
'purple-600': 'oklch(55.8% 0.288 302.321)', 'purple-700': 'oklch(49.6% 0.265 301.924)',
|
|
510
|
-
'purple-800': 'oklch(43.8% 0.218 303.724)', 'purple-900': 'oklch(38.1% 0.176 304.987)',
|
|
511
|
-
'purple-950': 'oklch(29.1% 0.149 302.717)',
|
|
512
|
-
// Pink
|
|
513
|
-
'pink-50': 'oklch(97.1% 0.014 343.198)', 'pink-100': 'oklch(94.8% 0.028 342.258)',
|
|
514
|
-
'pink-200': 'oklch(89.9% 0.061 343.231)', 'pink-300': 'oklch(82.3% 0.116 346.018)',
|
|
515
|
-
'pink-400': 'oklch(71.8% 0.202 349.761)', 'pink-500': 'oklch(65.6% 0.241 354.308)',
|
|
516
|
-
'pink-600': 'oklch(59.2% 0.249 0.584)', 'pink-700': 'oklch(52.5% 0.223 3.958)',
|
|
517
|
-
'pink-800': 'oklch(45.9% 0.187 3.815)', 'pink-900': 'oklch(40.8% 0.153 2.432)',
|
|
518
|
-
'pink-950': 'oklch(28.4% 0.109 3.907)',
|
|
519
|
-
// Indigo
|
|
520
|
-
'indigo-50': 'oklch(96.2% 0.018 272.314)', 'indigo-100': 'oklch(93% 0.034 272.788)',
|
|
521
|
-
'indigo-200': 'oklch(87% 0.065 274.039)', 'indigo-300': 'oklch(78.5% 0.115 274.713)',
|
|
522
|
-
'indigo-400': 'oklch(67.3% 0.182 276.935)', 'indigo-500': 'oklch(58.5% 0.233 277.117)',
|
|
523
|
-
'indigo-600': 'oklch(51.1% 0.262 276.966)', 'indigo-700': 'oklch(45.7% 0.24 277.023)',
|
|
524
|
-
'indigo-800': 'oklch(39.8% 0.195 277.366)', 'indigo-900': 'oklch(35.9% 0.144 278.697)',
|
|
525
|
-
'indigo-950': 'oklch(26.9% 0.096 280.79)',
|
|
526
|
-
// Cyan
|
|
527
|
-
'cyan-50': 'oklch(98.4% 0.019 200.873)', 'cyan-100': 'oklch(95.6% 0.045 203.388)',
|
|
528
|
-
'cyan-200': 'oklch(91.7% 0.08 205.041)', 'cyan-300': 'oklch(86.5% 0.127 207.078)',
|
|
529
|
-
'cyan-400': 'oklch(78.9% 0.154 211.53)', 'cyan-500': 'oklch(71.5% 0.143 215.221)',
|
|
530
|
-
'cyan-600': 'oklch(60.9% 0.126 221.723)', 'cyan-700': 'oklch(52% 0.105 223.128)',
|
|
531
|
-
'cyan-800': 'oklch(45% 0.085 224.283)', 'cyan-900': 'oklch(39.8% 0.07 227.392)',
|
|
532
|
-
'cyan-950': 'oklch(30.2% 0.056 229.695)',
|
|
533
|
-
// Emerald
|
|
534
|
-
'emerald-50': 'oklch(97.9% 0.021 166.113)', 'emerald-100': 'oklch(95% 0.052 163.051)',
|
|
535
|
-
'emerald-200': 'oklch(90.5% 0.093 164.15)', 'emerald-300': 'oklch(84.5% 0.143 164.978)',
|
|
536
|
-
'emerald-400': 'oklch(76.5% 0.177 163.223)', 'emerald-500': 'oklch(69.6% 0.17 162.48)',
|
|
537
|
-
'emerald-600': 'oklch(59.6% 0.145 163.225)', 'emerald-700': 'oklch(50.8% 0.118 165.612)',
|
|
538
|
-
'emerald-800': 'oklch(43.2% 0.095 166.913)', 'emerald-900': 'oklch(37.8% 0.077 168.94)',
|
|
539
|
-
'emerald-950': 'oklch(26.2% 0.051 172.552)',
|
|
540
|
-
// Special colors
|
|
541
|
-
'white': '#fff', 'black': '#000', 'transparent': 'transparent', 'current': 'currentColor',
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// =============================================================================
|
|
545
|
-
// TYPOGRAPHY UTILITIES - Fast path for font/text utilities
|
|
546
|
-
// =============================================================================
|
|
547
|
-
|
|
548
|
-
// Font weight - direct raw class to CSS
|
|
549
|
-
const FONT_WEIGHT_MAP: Record<string, Record<string, string>> = {
|
|
550
|
-
'font-thin': { 'font-weight': '100' },
|
|
551
|
-
'font-extralight': { 'font-weight': '200' },
|
|
552
|
-
'font-light': { 'font-weight': '300' },
|
|
553
|
-
'font-normal': { 'font-weight': '400' },
|
|
554
|
-
'font-medium': { 'font-weight': '500' },
|
|
555
|
-
'font-semibold': { 'font-weight': '600' },
|
|
556
|
-
'font-bold': { 'font-weight': '700' },
|
|
557
|
-
'font-extrabold': { 'font-weight': '800' },
|
|
558
|
-
'font-black': { 'font-weight': '900' },
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Font style - direct raw class to CSS
|
|
562
|
-
const FONT_STYLE_MAP: Record<string, Record<string, string>> = {
|
|
563
|
-
'italic': { 'font-style': 'italic' },
|
|
564
|
-
'not-italic': { 'font-style': 'normal' },
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// Text transform - direct raw class to CSS
|
|
568
|
-
const TEXT_TRANSFORM_MAP: Record<string, Record<string, string>> = {
|
|
569
|
-
'uppercase': { 'text-transform': 'uppercase' },
|
|
570
|
-
'lowercase': { 'text-transform': 'lowercase' },
|
|
571
|
-
'capitalize': { 'text-transform': 'capitalize' },
|
|
572
|
-
'normal-case': { 'text-transform': 'none' },
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Text decoration line - direct raw class to CSS
|
|
576
|
-
const TEXT_DECORATION_MAP: Record<string, Record<string, string>> = {
|
|
577
|
-
'underline': { 'text-decoration-line': 'underline' },
|
|
578
|
-
'overline': { 'text-decoration-line': 'overline' },
|
|
579
|
-
'line-through': { 'text-decoration-line': 'line-through' },
|
|
580
|
-
'no-underline': { 'text-decoration-line': 'none' },
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
// Text decoration style - direct raw class to CSS
|
|
584
|
-
const TEXT_DECORATION_STYLE_MAP: Record<string, Record<string, string>> = {
|
|
585
|
-
'decoration-solid': { 'text-decoration-style': 'solid' },
|
|
586
|
-
'decoration-double': { 'text-decoration-style': 'double' },
|
|
587
|
-
'decoration-dotted': { 'text-decoration-style': 'dotted' },
|
|
588
|
-
'decoration-dashed': { 'text-decoration-style': 'dashed' },
|
|
589
|
-
'decoration-wavy': { 'text-decoration-style': 'wavy' },
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// Text align - direct raw class to CSS
|
|
593
|
-
const TEXT_ALIGN_MAP: Record<string, Record<string, string>> = {
|
|
594
|
-
'text-left': { 'text-align': 'left' },
|
|
595
|
-
'text-center': { 'text-align': 'center' },
|
|
596
|
-
'text-right': { 'text-align': 'right' },
|
|
597
|
-
'text-justify': { 'text-align': 'justify' },
|
|
598
|
-
'text-start': { 'text-align': 'start' },
|
|
599
|
-
'text-end': { 'text-align': 'end' },
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// Text overflow - direct raw class to CSS
|
|
603
|
-
const TEXT_OVERFLOW_MAP: Record<string, Record<string, string>> = {
|
|
604
|
-
'truncate': { 'overflow': 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap' },
|
|
605
|
-
'text-ellipsis': { 'text-overflow': 'ellipsis' },
|
|
606
|
-
'text-clip': { 'text-overflow': 'clip' },
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// Text wrap - direct raw class to CSS
|
|
610
|
-
const TEXT_WRAP_MAP: Record<string, Record<string, string>> = {
|
|
611
|
-
'text-wrap': { 'text-wrap': 'wrap' },
|
|
612
|
-
'text-nowrap': { 'text-wrap': 'nowrap' },
|
|
613
|
-
'text-balance': { 'text-wrap': 'balance' },
|
|
614
|
-
'text-pretty': { 'text-wrap': 'pretty' },
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
// Whitespace - direct raw class to CSS
|
|
618
|
-
const WHITESPACE_MAP: Record<string, Record<string, string>> = {
|
|
619
|
-
'whitespace-normal': { 'white-space': 'normal' },
|
|
620
|
-
'whitespace-nowrap': { 'white-space': 'nowrap' },
|
|
621
|
-
'whitespace-pre': { 'white-space': 'pre' },
|
|
622
|
-
'whitespace-pre-line': { 'white-space': 'pre-line' },
|
|
623
|
-
'whitespace-pre-wrap': { 'white-space': 'pre-wrap' },
|
|
624
|
-
'whitespace-break-spaces': { 'white-space': 'break-spaces' },
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// Word break - direct raw class to CSS
|
|
628
|
-
const WORD_BREAK_MAP: Record<string, Record<string, string>> = {
|
|
629
|
-
'break-normal': { 'overflow-wrap': 'normal', 'word-break': 'normal' },
|
|
630
|
-
'break-words': { 'overflow-wrap': 'break-word' },
|
|
631
|
-
'break-all': { 'word-break': 'break-all' },
|
|
632
|
-
'break-keep': { 'word-break': 'keep-all' },
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// Vertical align - direct raw class to CSS
|
|
636
|
-
const VERTICAL_ALIGN_MAP: Record<string, Record<string, string>> = {
|
|
637
|
-
'align-baseline': { 'vertical-align': 'baseline' },
|
|
638
|
-
'align-top': { 'vertical-align': 'top' },
|
|
639
|
-
'align-middle': { 'vertical-align': 'middle' },
|
|
640
|
-
'align-bottom': { 'vertical-align': 'bottom' },
|
|
641
|
-
'align-text-top': { 'vertical-align': 'text-top' },
|
|
642
|
-
'align-text-bottom': { 'vertical-align': 'text-bottom' },
|
|
643
|
-
'align-sub': { 'vertical-align': 'sub' },
|
|
644
|
-
'align-super': { 'vertical-align': 'super' },
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// List style type - direct raw class to CSS
|
|
648
|
-
const LIST_STYLE_MAP: Record<string, Record<string, string>> = {
|
|
649
|
-
'list-none': { 'list-style-type': 'none' },
|
|
650
|
-
'list-disc': { 'list-style-type': 'disc' },
|
|
651
|
-
'list-decimal': { 'list-style-type': 'decimal' },
|
|
652
|
-
'list-inside': { 'list-style-position': 'inside' },
|
|
653
|
-
'list-outside': { 'list-style-position': 'outside' },
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
// Hyphens - direct raw class to CSS
|
|
657
|
-
const HYPHENS_MAP: Record<string, Record<string, string>> = {
|
|
658
|
-
'hyphens-none': { hyphens: 'none' },
|
|
659
|
-
'hyphens-manual': { hyphens: 'manual' },
|
|
660
|
-
'hyphens-auto': { hyphens: 'auto' },
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// =============================================================================
|
|
664
|
-
// LAYOUT UTILITIES - Fast path for layout/positioning
|
|
665
|
-
// =============================================================================
|
|
666
|
-
|
|
667
|
-
// Position - direct raw class to CSS
|
|
668
|
-
const POSITION_MAP: Record<string, Record<string, string>> = {
|
|
669
|
-
'static': { position: 'static' },
|
|
670
|
-
'fixed': { position: 'fixed' },
|
|
671
|
-
'absolute': { position: 'absolute' },
|
|
672
|
-
'relative': { position: 'relative' },
|
|
673
|
-
'sticky': { position: 'sticky' },
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// Visibility - direct raw class to CSS
|
|
677
|
-
const VISIBILITY_MAP: Record<string, Record<string, string>> = {
|
|
678
|
-
'visible': { visibility: 'visible' },
|
|
679
|
-
'invisible': { visibility: 'hidden' },
|
|
680
|
-
'collapse': { visibility: 'collapse' },
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// Float - direct raw class to CSS
|
|
684
|
-
const FLOAT_MAP: Record<string, Record<string, string>> = {
|
|
685
|
-
'float-left': { float: 'left' },
|
|
686
|
-
'float-right': { float: 'right' },
|
|
687
|
-
'float-none': { float: 'none' },
|
|
688
|
-
'float-start': { float: 'inline-start' },
|
|
689
|
-
'float-end': { float: 'inline-end' },
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// Clear - direct raw class to CSS
|
|
693
|
-
const CLEAR_MAP: Record<string, Record<string, string>> = {
|
|
694
|
-
'clear-left': { clear: 'left' },
|
|
695
|
-
'clear-right': { clear: 'right' },
|
|
696
|
-
'clear-both': { clear: 'both' },
|
|
697
|
-
'clear-none': { clear: 'none' },
|
|
698
|
-
'clear-start': { clear: 'inline-start' },
|
|
699
|
-
'clear-end': { clear: 'inline-end' },
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
// Isolation - direct raw class to CSS
|
|
703
|
-
const ISOLATION_MAP: Record<string, Record<string, string>> = {
|
|
704
|
-
'isolate': { isolation: 'isolate' },
|
|
705
|
-
'isolation-auto': { isolation: 'auto' },
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
// Object fit - direct raw class to CSS
|
|
709
|
-
const OBJECT_FIT_MAP: Record<string, Record<string, string>> = {
|
|
710
|
-
'object-contain': { 'object-fit': 'contain' },
|
|
711
|
-
'object-cover': { 'object-fit': 'cover' },
|
|
712
|
-
'object-fill': { 'object-fit': 'fill' },
|
|
713
|
-
'object-none': { 'object-fit': 'none' },
|
|
714
|
-
'object-scale-down': { 'object-fit': 'scale-down' },
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
// Object position - direct raw class to CSS
|
|
718
|
-
const OBJECT_POSITION_MAP: Record<string, Record<string, string>> = {
|
|
719
|
-
'object-bottom': { 'object-position': 'bottom' },
|
|
720
|
-
'object-center': { 'object-position': 'center' },
|
|
721
|
-
'object-left': { 'object-position': 'left' },
|
|
722
|
-
'object-left-bottom': { 'object-position': 'left bottom' },
|
|
723
|
-
'object-left-top': { 'object-position': 'left top' },
|
|
724
|
-
'object-right': { 'object-position': 'right' },
|
|
725
|
-
'object-right-bottom': { 'object-position': 'right bottom' },
|
|
726
|
-
'object-right-top': { 'object-position': 'right top' },
|
|
727
|
-
'object-top': { 'object-position': 'top' },
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// Overflow - direct raw class to CSS
|
|
731
|
-
const OVERFLOW_MAP: Record<string, Record<string, string>> = {
|
|
732
|
-
'overflow-auto': { overflow: 'auto' },
|
|
733
|
-
'overflow-hidden': { overflow: 'hidden' },
|
|
734
|
-
'overflow-clip': { overflow: 'clip' },
|
|
735
|
-
'overflow-visible': { overflow: 'visible' },
|
|
736
|
-
'overflow-scroll': { overflow: 'scroll' },
|
|
737
|
-
'overflow-x-auto': { 'overflow-x': 'auto' },
|
|
738
|
-
'overflow-x-hidden': { 'overflow-x': 'hidden' },
|
|
739
|
-
'overflow-x-clip': { 'overflow-x': 'clip' },
|
|
740
|
-
'overflow-x-visible': { 'overflow-x': 'visible' },
|
|
741
|
-
'overflow-x-scroll': { 'overflow-x': 'scroll' },
|
|
742
|
-
'overflow-y-auto': { 'overflow-y': 'auto' },
|
|
743
|
-
'overflow-y-hidden': { 'overflow-y': 'hidden' },
|
|
744
|
-
'overflow-y-clip': { 'overflow-y': 'clip' },
|
|
745
|
-
'overflow-y-visible': { 'overflow-y': 'visible' },
|
|
746
|
-
'overflow-y-scroll': { 'overflow-y': 'scroll' },
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
// Overscroll - direct raw class to CSS
|
|
750
|
-
const OVERSCROLL_MAP: Record<string, Record<string, string>> = {
|
|
751
|
-
'overscroll-auto': { 'overscroll-behavior': 'auto' },
|
|
752
|
-
'overscroll-contain': { 'overscroll-behavior': 'contain' },
|
|
753
|
-
'overscroll-none': { 'overscroll-behavior': 'none' },
|
|
754
|
-
'overscroll-x-auto': { 'overscroll-behavior-x': 'auto' },
|
|
755
|
-
'overscroll-x-contain': { 'overscroll-behavior-x': 'contain' },
|
|
756
|
-
'overscroll-x-none': { 'overscroll-behavior-x': 'none' },
|
|
757
|
-
'overscroll-y-auto': { 'overscroll-behavior-y': 'auto' },
|
|
758
|
-
'overscroll-y-contain': { 'overscroll-behavior-y': 'contain' },
|
|
759
|
-
'overscroll-y-none': { 'overscroll-behavior-y': 'none' },
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
// Z-index - direct raw class to CSS
|
|
763
|
-
const Z_INDEX_MAP: Record<string, Record<string, string>> = {
|
|
764
|
-
'z-0': { 'z-index': '0' },
|
|
765
|
-
'z-10': { 'z-index': '10' },
|
|
766
|
-
'z-20': { 'z-index': '20' },
|
|
767
|
-
'z-30': { 'z-index': '30' },
|
|
768
|
-
'z-40': { 'z-index': '40' },
|
|
769
|
-
'z-50': { 'z-index': '50' },
|
|
770
|
-
'z-auto': { 'z-index': 'auto' },
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// Aspect ratio - direct raw class to CSS
|
|
774
|
-
const ASPECT_RATIO_MAP: Record<string, Record<string, string>> = {
|
|
775
|
-
'aspect-auto': { 'aspect-ratio': 'auto' },
|
|
776
|
-
'aspect-square': { 'aspect-ratio': '1 / 1' },
|
|
777
|
-
'aspect-video': { 'aspect-ratio': '16 / 9' },
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// Box sizing - direct raw class to CSS
|
|
781
|
-
const BOX_SIZING_MAP: Record<string, Record<string, string>> = {
|
|
782
|
-
'box-border': { 'box-sizing': 'border-box' },
|
|
783
|
-
'box-content': { 'box-sizing': 'content-box' },
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// Box decoration break - direct raw class to CSS
|
|
787
|
-
const BOX_DECORATION_MAP: Record<string, Record<string, string>> = {
|
|
788
|
-
'box-decoration-clone': { 'box-decoration-break': 'clone' },
|
|
789
|
-
'box-decoration-slice': { 'box-decoration-break': 'slice' },
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// =============================================================================
|
|
793
|
-
// BACKGROUND UTILITIES - Fast path for background
|
|
794
|
-
// =============================================================================
|
|
795
|
-
|
|
796
|
-
// Background attachment - direct raw class to CSS
|
|
797
|
-
const BG_ATTACHMENT_MAP: Record<string, Record<string, string>> = {
|
|
798
|
-
'bg-fixed': { 'background-attachment': 'fixed' },
|
|
799
|
-
'bg-local': { 'background-attachment': 'local' },
|
|
800
|
-
'bg-scroll': { 'background-attachment': 'scroll' },
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
// Background clip - direct raw class to CSS
|
|
804
|
-
const BG_CLIP_MAP: Record<string, Record<string, string>> = {
|
|
805
|
-
'bg-clip-border': { 'background-clip': 'border-box' },
|
|
806
|
-
'bg-clip-padding': { 'background-clip': 'padding-box' },
|
|
807
|
-
'bg-clip-content': { 'background-clip': 'content-box' },
|
|
808
|
-
'bg-clip-text': { 'background-clip': 'text', '-webkit-background-clip': 'text' },
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
// Background origin - direct raw class to CSS
|
|
812
|
-
const BG_ORIGIN_MAP: Record<string, Record<string, string>> = {
|
|
813
|
-
'bg-origin-border': { 'background-origin': 'border-box' },
|
|
814
|
-
'bg-origin-padding': { 'background-origin': 'padding-box' },
|
|
815
|
-
'bg-origin-content': { 'background-origin': 'content-box' },
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
// Background position - direct raw class to CSS
|
|
819
|
-
const BG_POSITION_MAP: Record<string, Record<string, string>> = {
|
|
820
|
-
'bg-bottom': { 'background-position': 'bottom' },
|
|
821
|
-
'bg-center': { 'background-position': 'center' },
|
|
822
|
-
'bg-left': { 'background-position': 'left' },
|
|
823
|
-
'bg-left-bottom': { 'background-position': 'left bottom' },
|
|
824
|
-
'bg-left-top': { 'background-position': 'left top' },
|
|
825
|
-
'bg-right': { 'background-position': 'right' },
|
|
826
|
-
'bg-right-bottom': { 'background-position': 'right bottom' },
|
|
827
|
-
'bg-right-top': { 'background-position': 'right top' },
|
|
828
|
-
'bg-top': { 'background-position': 'top' },
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// Background repeat - direct raw class to CSS
|
|
832
|
-
const BG_REPEAT_MAP: Record<string, Record<string, string>> = {
|
|
833
|
-
'bg-repeat': { 'background-repeat': 'repeat' },
|
|
834
|
-
'bg-no-repeat': { 'background-repeat': 'no-repeat' },
|
|
835
|
-
'bg-repeat-x': { 'background-repeat': 'repeat-x' },
|
|
836
|
-
'bg-repeat-y': { 'background-repeat': 'repeat-y' },
|
|
837
|
-
'bg-repeat-round': { 'background-repeat': 'round' },
|
|
838
|
-
'bg-repeat-space': { 'background-repeat': 'space' },
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// Background size - direct raw class to CSS
|
|
842
|
-
const BG_SIZE_MAP: Record<string, Record<string, string>> = {
|
|
843
|
-
'bg-auto': { 'background-size': 'auto' },
|
|
844
|
-
'bg-cover': { 'background-size': 'cover' },
|
|
845
|
-
'bg-contain': { 'background-size': 'contain' },
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
// Gradient direction - direct raw class to CSS
|
|
849
|
-
const GRADIENT_MAP: Record<string, Record<string, string>> = {
|
|
850
|
-
'bg-none': { 'background-image': 'none' },
|
|
851
|
-
'bg-gradient-to-t': { 'background-image': 'linear-gradient(to top, var(--hw-gradient-stops))' },
|
|
852
|
-
'bg-gradient-to-tr': { 'background-image': 'linear-gradient(to top right, var(--hw-gradient-stops))' },
|
|
853
|
-
'bg-gradient-to-r': { 'background-image': 'linear-gradient(to right, var(--hw-gradient-stops))' },
|
|
854
|
-
'bg-gradient-to-br': { 'background-image': 'linear-gradient(to bottom right, var(--hw-gradient-stops))' },
|
|
855
|
-
'bg-gradient-to-b': { 'background-image': 'linear-gradient(to bottom, var(--hw-gradient-stops))' },
|
|
856
|
-
'bg-gradient-to-bl': { 'background-image': 'linear-gradient(to bottom left, var(--hw-gradient-stops))' },
|
|
857
|
-
'bg-gradient-to-l': { 'background-image': 'linear-gradient(to left, var(--hw-gradient-stops))' },
|
|
858
|
-
'bg-gradient-to-tl': { 'background-image': 'linear-gradient(to top left, var(--hw-gradient-stops))' },
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
// =============================================================================
|
|
862
|
-
// INTERACTIVITY UTILITIES - Fast path for cursor/pointer/etc
|
|
863
|
-
// =============================================================================
|
|
864
|
-
|
|
865
|
-
// Cursor - direct raw class to CSS
|
|
866
|
-
const CURSOR_MAP: Record<string, Record<string, string>> = {
|
|
867
|
-
'cursor-auto': { cursor: 'auto' },
|
|
868
|
-
'cursor-default': { cursor: 'default' },
|
|
869
|
-
'cursor-pointer': { cursor: 'pointer' },
|
|
870
|
-
'cursor-wait': { cursor: 'wait' },
|
|
871
|
-
'cursor-text': { cursor: 'text' },
|
|
872
|
-
'cursor-move': { cursor: 'move' },
|
|
873
|
-
'cursor-help': { cursor: 'help' },
|
|
874
|
-
'cursor-not-allowed': { cursor: 'not-allowed' },
|
|
875
|
-
'cursor-none': { cursor: 'none' },
|
|
876
|
-
'cursor-context-menu': { cursor: 'context-menu' },
|
|
877
|
-
'cursor-progress': { cursor: 'progress' },
|
|
878
|
-
'cursor-cell': { cursor: 'cell' },
|
|
879
|
-
'cursor-crosshair': { cursor: 'crosshair' },
|
|
880
|
-
'cursor-vertical-text': { cursor: 'vertical-text' },
|
|
881
|
-
'cursor-alias': { cursor: 'alias' },
|
|
882
|
-
'cursor-copy': { cursor: 'copy' },
|
|
883
|
-
'cursor-no-drop': { cursor: 'no-drop' },
|
|
884
|
-
'cursor-grab': { cursor: 'grab' },
|
|
885
|
-
'cursor-grabbing': { cursor: 'grabbing' },
|
|
886
|
-
'cursor-all-scroll': { cursor: 'all-scroll' },
|
|
887
|
-
'cursor-col-resize': { cursor: 'col-resize' },
|
|
888
|
-
'cursor-row-resize': { cursor: 'row-resize' },
|
|
889
|
-
'cursor-n-resize': { cursor: 'n-resize' },
|
|
890
|
-
'cursor-e-resize': { cursor: 'e-resize' },
|
|
891
|
-
'cursor-s-resize': { cursor: 's-resize' },
|
|
892
|
-
'cursor-w-resize': { cursor: 'w-resize' },
|
|
893
|
-
'cursor-ne-resize': { cursor: 'ne-resize' },
|
|
894
|
-
'cursor-nw-resize': { cursor: 'nw-resize' },
|
|
895
|
-
'cursor-se-resize': { cursor: 'se-resize' },
|
|
896
|
-
'cursor-sw-resize': { cursor: 'sw-resize' },
|
|
897
|
-
'cursor-ew-resize': { cursor: 'ew-resize' },
|
|
898
|
-
'cursor-ns-resize': { cursor: 'ns-resize' },
|
|
899
|
-
'cursor-nesw-resize': { cursor: 'nesw-resize' },
|
|
900
|
-
'cursor-nwse-resize': { cursor: 'nwse-resize' },
|
|
901
|
-
'cursor-zoom-in': { cursor: 'zoom-in' },
|
|
902
|
-
'cursor-zoom-out': { cursor: 'zoom-out' },
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
// Pointer events - direct raw class to CSS
|
|
906
|
-
const POINTER_EVENTS_MAP: Record<string, Record<string, string>> = {
|
|
907
|
-
'pointer-events-none': { 'pointer-events': 'none' },
|
|
908
|
-
'pointer-events-auto': { 'pointer-events': 'auto' },
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// Resize - direct raw class to CSS
|
|
912
|
-
const RESIZE_MAP: Record<string, Record<string, string>> = {
|
|
913
|
-
'resize-none': { resize: 'none' },
|
|
914
|
-
'resize-y': { resize: 'vertical' },
|
|
915
|
-
'resize-x': { resize: 'horizontal' },
|
|
916
|
-
'resize': { resize: 'both' },
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
// User select - direct raw class to CSS
|
|
920
|
-
const USER_SELECT_MAP: Record<string, Record<string, string>> = {
|
|
921
|
-
'select-none': { 'user-select': 'none' },
|
|
922
|
-
'select-text': { 'user-select': 'text' },
|
|
923
|
-
'select-all': { 'user-select': 'all' },
|
|
924
|
-
'select-auto': { 'user-select': 'auto' },
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
// Scroll behavior - direct raw class to CSS
|
|
928
|
-
const SCROLL_BEHAVIOR_MAP: Record<string, Record<string, string>> = {
|
|
929
|
-
'scroll-auto': { 'scroll-behavior': 'auto' },
|
|
930
|
-
'scroll-smooth': { 'scroll-behavior': 'smooth' },
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
// Scroll snap type - direct raw class to CSS
|
|
934
|
-
const SCROLL_SNAP_MAP: Record<string, Record<string, string>> = {
|
|
935
|
-
'snap-none': { 'scroll-snap-type': 'none' },
|
|
936
|
-
'snap-x': { 'scroll-snap-type': 'x var(--hw-scroll-snap-strictness)' },
|
|
937
|
-
'snap-y': { 'scroll-snap-type': 'y var(--hw-scroll-snap-strictness)' },
|
|
938
|
-
'snap-both': { 'scroll-snap-type': 'both var(--hw-scroll-snap-strictness)' },
|
|
939
|
-
'snap-mandatory': { '--hw-scroll-snap-strictness': 'mandatory' },
|
|
940
|
-
'snap-proximity': { '--hw-scroll-snap-strictness': 'proximity' },
|
|
941
|
-
'snap-start': { 'scroll-snap-align': 'start' },
|
|
942
|
-
'snap-end': { 'scroll-snap-align': 'end' },
|
|
943
|
-
'snap-center': { 'scroll-snap-align': 'center' },
|
|
944
|
-
'snap-align-none': { 'scroll-snap-align': 'none' },
|
|
945
|
-
'snap-normal': { 'scroll-snap-stop': 'normal' },
|
|
946
|
-
'snap-always': { 'scroll-snap-stop': 'always' },
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
// Touch action - direct raw class to CSS
|
|
950
|
-
const TOUCH_ACTION_MAP: Record<string, Record<string, string>> = {
|
|
951
|
-
'touch-auto': { 'touch-action': 'auto' },
|
|
952
|
-
'touch-none': { 'touch-action': 'none' },
|
|
953
|
-
'touch-pan-x': { 'touch-action': 'pan-x' },
|
|
954
|
-
'touch-pan-left': { 'touch-action': 'pan-left' },
|
|
955
|
-
'touch-pan-right': { 'touch-action': 'pan-right' },
|
|
956
|
-
'touch-pan-y': { 'touch-action': 'pan-y' },
|
|
957
|
-
'touch-pan-up': { 'touch-action': 'pan-up' },
|
|
958
|
-
'touch-pan-down': { 'touch-action': 'pan-down' },
|
|
959
|
-
'touch-pinch-zoom': { 'touch-action': 'pinch-zoom' },
|
|
960
|
-
'touch-manipulation': { 'touch-action': 'manipulation' },
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
// Will change - direct raw class to CSS
|
|
964
|
-
const WILL_CHANGE_MAP: Record<string, Record<string, string>> = {
|
|
965
|
-
'will-change-auto': { 'will-change': 'auto' },
|
|
966
|
-
'will-change-scroll': { 'will-change': 'scroll-position' },
|
|
967
|
-
'will-change-contents': { 'will-change': 'contents' },
|
|
968
|
-
'will-change-transform': { 'will-change': 'transform' },
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
// Appearance - direct raw class to CSS
|
|
972
|
-
const APPEARANCE_MAP: Record<string, Record<string, string>> = {
|
|
973
|
-
'appearance-none': { appearance: 'none' },
|
|
974
|
-
'appearance-auto': { appearance: 'auto' },
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
// =============================================================================
|
|
978
|
-
// TABLE UTILITIES - Fast path for table styling
|
|
979
|
-
// =============================================================================
|
|
980
|
-
|
|
981
|
-
// Border collapse - direct raw class to CSS
|
|
982
|
-
const BORDER_COLLAPSE_MAP: Record<string, Record<string, string>> = {
|
|
983
|
-
'border-collapse': { 'border-collapse': 'collapse' },
|
|
984
|
-
'border-separate': { 'border-collapse': 'separate' },
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
// Table layout - direct raw class to CSS
|
|
988
|
-
const TABLE_LAYOUT_MAP: Record<string, Record<string, string>> = {
|
|
989
|
-
'table-auto': { 'table-layout': 'auto' },
|
|
990
|
-
'table-fixed': { 'table-layout': 'fixed' },
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// Caption side - direct raw class to CSS
|
|
994
|
-
const CAPTION_SIDE_MAP: Record<string, Record<string, string>> = {
|
|
995
|
-
'caption-top': { 'caption-side': 'top' },
|
|
996
|
-
'caption-bottom': { 'caption-side': 'bottom' },
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
// =============================================================================
|
|
1000
|
-
// ACCESSIBILITY UTILITIES - Fast path for a11y
|
|
1001
|
-
// =============================================================================
|
|
1002
|
-
|
|
1003
|
-
// Screen reader only - direct raw class to CSS
|
|
1004
|
-
const SR_ONLY_MAP: Record<string, Record<string, string>> = {
|
|
1005
|
-
'sr-only': {
|
|
1006
|
-
position: 'absolute',
|
|
1007
|
-
width: '1px',
|
|
1008
|
-
height: '1px',
|
|
1009
|
-
padding: '0',
|
|
1010
|
-
margin: '-1px',
|
|
1011
|
-
overflow: 'hidden',
|
|
1012
|
-
clip: 'rect(0, 0, 0, 0)',
|
|
1013
|
-
'white-space': 'nowrap',
|
|
1014
|
-
'border-width': '0',
|
|
1015
|
-
},
|
|
1016
|
-
'not-sr-only': {
|
|
1017
|
-
position: 'static',
|
|
1018
|
-
width: 'auto',
|
|
1019
|
-
height: 'auto',
|
|
1020
|
-
padding: '0',
|
|
1021
|
-
margin: '0',
|
|
1022
|
-
overflow: 'visible',
|
|
1023
|
-
clip: 'auto',
|
|
1024
|
-
'white-space': 'normal',
|
|
1025
|
-
},
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// Forced color adjust - direct raw class to CSS
|
|
1029
|
-
const FORCED_COLOR_MAP: Record<string, Record<string, string>> = {
|
|
1030
|
-
'forced-color-adjust-auto': { 'forced-color-adjust': 'auto' },
|
|
1031
|
-
'forced-color-adjust-none': { 'forced-color-adjust': 'none' },
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
// =============================================================================
|
|
1035
|
-
// SVG UTILITIES - Fast path for SVG
|
|
1036
|
-
// =============================================================================
|
|
1037
|
-
|
|
1038
|
-
// Fill - direct raw class to CSS
|
|
1039
|
-
const FILL_MAP: Record<string, Record<string, string>> = {
|
|
1040
|
-
'fill-none': { fill: 'none' },
|
|
1041
|
-
'fill-current': { fill: 'currentColor' },
|
|
1042
|
-
'fill-inherit': { fill: 'inherit' },
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
// Stroke - direct raw class to CSS
|
|
1046
|
-
const STROKE_MAP: Record<string, Record<string, string>> = {
|
|
1047
|
-
'stroke-none': { stroke: 'none' },
|
|
1048
|
-
'stroke-current': { stroke: 'currentColor' },
|
|
1049
|
-
'stroke-inherit': { stroke: 'inherit' },
|
|
1050
|
-
'stroke-0': { 'stroke-width': '0' },
|
|
1051
|
-
'stroke-1': { 'stroke-width': '1' },
|
|
1052
|
-
'stroke-2': { 'stroke-width': '2' },
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
// Stroke linecap - direct raw class to CSS
|
|
1056
|
-
const STROKE_LINECAP_MAP: Record<string, Record<string, string>> = {
|
|
1057
|
-
'stroke-linecap-butt': { 'stroke-linecap': 'butt' },
|
|
1058
|
-
'stroke-linecap-round': { 'stroke-linecap': 'round' },
|
|
1059
|
-
'stroke-linecap-square': { 'stroke-linecap': 'square' },
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
// Stroke linejoin - direct raw class to CSS
|
|
1063
|
-
const STROKE_LINEJOIN_MAP: Record<string, Record<string, string>> = {
|
|
1064
|
-
'stroke-linejoin-miter': { 'stroke-linejoin': 'miter' },
|
|
1065
|
-
'stroke-linejoin-round': { 'stroke-linejoin': 'round' },
|
|
1066
|
-
'stroke-linejoin-bevel': { 'stroke-linejoin': 'bevel' },
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
// =============================================================================
|
|
1070
|
-
// FILTER UTILITIES - Fast path for filters
|
|
1071
|
-
// =============================================================================
|
|
1072
|
-
|
|
1073
|
-
// Blur - direct raw class to CSS
|
|
1074
|
-
const BLUR_MAP: Record<string, Record<string, string>> = {
|
|
1075
|
-
'blur-none': { filter: 'blur(0)' },
|
|
1076
|
-
'blur-sm': { filter: 'blur(4px)' },
|
|
1077
|
-
'blur': { filter: 'blur(8px)' },
|
|
1078
|
-
'blur-md': { filter: 'blur(12px)' },
|
|
1079
|
-
'blur-lg': { filter: 'blur(16px)' },
|
|
1080
|
-
'blur-xl': { filter: 'blur(24px)' },
|
|
1081
|
-
'blur-2xl': { filter: 'blur(40px)' },
|
|
1082
|
-
'blur-3xl': { filter: 'blur(64px)' },
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
// Backdrop blur - direct raw class to CSS
|
|
1086
|
-
const BACKDROP_BLUR_MAP: Record<string, Record<string, string>> = {
|
|
1087
|
-
'backdrop-blur-none': { 'backdrop-filter': 'blur(0)' },
|
|
1088
|
-
'backdrop-blur-sm': { 'backdrop-filter': 'blur(4px)' },
|
|
1089
|
-
'backdrop-blur': { 'backdrop-filter': 'blur(8px)' },
|
|
1090
|
-
'backdrop-blur-md': { 'backdrop-filter': 'blur(12px)' },
|
|
1091
|
-
'backdrop-blur-lg': { 'backdrop-filter': 'blur(16px)' },
|
|
1092
|
-
'backdrop-blur-xl': { 'backdrop-filter': 'blur(24px)' },
|
|
1093
|
-
'backdrop-blur-2xl': { 'backdrop-filter': 'blur(40px)' },
|
|
1094
|
-
'backdrop-blur-3xl': { 'backdrop-filter': 'blur(64px)' },
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
// Grayscale/invert/sepia - direct raw class to CSS
|
|
1098
|
-
const FILTER_TOGGLE_MAP: Record<string, Record<string, string>> = {
|
|
1099
|
-
'grayscale-0': { filter: 'grayscale(0)' },
|
|
1100
|
-
'grayscale': { filter: 'grayscale(100%)' },
|
|
1101
|
-
'invert-0': { filter: 'invert(0)' },
|
|
1102
|
-
'invert': { filter: 'invert(100%)' },
|
|
1103
|
-
'sepia-0': { filter: 'sepia(0)' },
|
|
1104
|
-
'sepia': { filter: 'sepia(100%)' },
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
// Backdrop grayscale/invert/sepia - direct raw class to CSS
|
|
1108
|
-
const BACKDROP_FILTER_TOGGLE_MAP: Record<string, Record<string, string>> = {
|
|
1109
|
-
'backdrop-grayscale-0': { 'backdrop-filter': 'grayscale(0)' },
|
|
1110
|
-
'backdrop-grayscale': { 'backdrop-filter': 'grayscale(100%)' },
|
|
1111
|
-
'backdrop-invert-0': { 'backdrop-filter': 'invert(0)' },
|
|
1112
|
-
'backdrop-invert': { 'backdrop-filter': 'invert(100%)' },
|
|
1113
|
-
'backdrop-sepia-0': { 'backdrop-filter': 'sepia(0)' },
|
|
1114
|
-
'backdrop-sepia': { 'backdrop-filter': 'sepia(100%)' },
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
// Drop shadow - direct raw class to CSS
|
|
1118
|
-
const DROP_SHADOW_MAP: Record<string, Record<string, string>> = {
|
|
1119
|
-
'drop-shadow-sm': { filter: 'drop-shadow(0 1px 1px rgb(0 0 0 / 0.05))' },
|
|
1120
|
-
'drop-shadow': { filter: 'drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06))' },
|
|
1121
|
-
'drop-shadow-md': { filter: 'drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06))' },
|
|
1122
|
-
'drop-shadow-lg': { filter: 'drop-shadow(0 10px 8px rgb(0 0 0 / 0.04)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1))' },
|
|
1123
|
-
'drop-shadow-xl': { filter: 'drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08))' },
|
|
1124
|
-
'drop-shadow-2xl': { filter: 'drop-shadow(0 25px 25px rgb(0 0 0 / 0.15))' },
|
|
1125
|
-
'drop-shadow-none': { filter: 'drop-shadow(0 0 #0000)' },
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
// Mix blend mode - direct raw class to CSS
|
|
1129
|
-
const MIX_BLEND_MAP: Record<string, Record<string, string>> = {
|
|
1130
|
-
'mix-blend-normal': { 'mix-blend-mode': 'normal' },
|
|
1131
|
-
'mix-blend-multiply': { 'mix-blend-mode': 'multiply' },
|
|
1132
|
-
'mix-blend-screen': { 'mix-blend-mode': 'screen' },
|
|
1133
|
-
'mix-blend-overlay': { 'mix-blend-mode': 'overlay' },
|
|
1134
|
-
'mix-blend-darken': { 'mix-blend-mode': 'darken' },
|
|
1135
|
-
'mix-blend-lighten': { 'mix-blend-mode': 'lighten' },
|
|
1136
|
-
'mix-blend-color-dodge': { 'mix-blend-mode': 'color-dodge' },
|
|
1137
|
-
'mix-blend-color-burn': { 'mix-blend-mode': 'color-burn' },
|
|
1138
|
-
'mix-blend-hard-light': { 'mix-blend-mode': 'hard-light' },
|
|
1139
|
-
'mix-blend-soft-light': { 'mix-blend-mode': 'soft-light' },
|
|
1140
|
-
'mix-blend-difference': { 'mix-blend-mode': 'difference' },
|
|
1141
|
-
'mix-blend-exclusion': { 'mix-blend-mode': 'exclusion' },
|
|
1142
|
-
'mix-blend-hue': { 'mix-blend-mode': 'hue' },
|
|
1143
|
-
'mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
|
|
1144
|
-
'mix-blend-color': { 'mix-blend-mode': 'color' },
|
|
1145
|
-
'mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
|
|
1146
|
-
'mix-blend-plus-darker': { 'mix-blend-mode': 'plus-darker' },
|
|
1147
|
-
'mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
|
|
1148
|
-
}
|
|
1149
|
-
|
|
1150
|
-
// Background blend mode - direct raw class to CSS
|
|
1151
|
-
const BG_BLEND_MAP: Record<string, Record<string, string>> = {
|
|
1152
|
-
'bg-blend-normal': { 'background-blend-mode': 'normal' },
|
|
1153
|
-
'bg-blend-multiply': { 'background-blend-mode': 'multiply' },
|
|
1154
|
-
'bg-blend-screen': { 'background-blend-mode': 'screen' },
|
|
1155
|
-
'bg-blend-overlay': { 'background-blend-mode': 'overlay' },
|
|
1156
|
-
'bg-blend-darken': { 'background-blend-mode': 'darken' },
|
|
1157
|
-
'bg-blend-lighten': { 'background-blend-mode': 'lighten' },
|
|
1158
|
-
'bg-blend-color-dodge': { 'background-blend-mode': 'color-dodge' },
|
|
1159
|
-
'bg-blend-color-burn': { 'background-blend-mode': 'color-burn' },
|
|
1160
|
-
'bg-blend-hard-light': { 'background-blend-mode': 'hard-light' },
|
|
1161
|
-
'bg-blend-soft-light': { 'background-blend-mode': 'soft-light' },
|
|
1162
|
-
'bg-blend-difference': { 'background-blend-mode': 'difference' },
|
|
1163
|
-
'bg-blend-exclusion': { 'background-blend-mode': 'exclusion' },
|
|
1164
|
-
'bg-blend-hue': { 'background-blend-mode': 'hue' },
|
|
1165
|
-
'bg-blend-saturation': { 'background-blend-mode': 'saturation' },
|
|
1166
|
-
'bg-blend-color': { 'background-blend-mode': 'color' },
|
|
1167
|
-
'bg-blend-luminosity': { 'background-blend-mode': 'luminosity' },
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
// Combined static map for raw class lookups (display, flex, transform, etc.)
|
|
1171
|
-
const STATIC_UTILITY_MAP: Record<string, Record<string, string>> = {
|
|
1172
|
-
...DISPLAY_MAP,
|
|
1173
|
-
...FLEX_DIRECTION_MAP,
|
|
1174
|
-
...FLEX_WRAP_MAP,
|
|
1175
|
-
...FLEX_VALUES_MAP,
|
|
1176
|
-
...GROW_SHRINK_MAP,
|
|
1177
|
-
...BORDER_STYLE_MAP,
|
|
1178
|
-
...TRANSFORM_MAP,
|
|
1179
|
-
...TRANSITION_MAP,
|
|
1180
|
-
...TIMING_MAP,
|
|
1181
|
-
...ANIMATION_MAP,
|
|
1182
|
-
...RING_MAP,
|
|
1183
|
-
...SHADOW_MAP,
|
|
1184
|
-
...BORDER_RADIUS_MAP,
|
|
1185
|
-
...BORDER_WIDTH_MAP,
|
|
1186
|
-
...RING_OFFSET_MAP,
|
|
1187
|
-
...OPACITY_MAP,
|
|
1188
|
-
// Typography
|
|
1189
|
-
...FONT_WEIGHT_MAP,
|
|
1190
|
-
...FONT_STYLE_MAP,
|
|
1191
|
-
...TEXT_TRANSFORM_MAP,
|
|
1192
|
-
...TEXT_DECORATION_MAP,
|
|
1193
|
-
...TEXT_DECORATION_STYLE_MAP,
|
|
1194
|
-
...TEXT_ALIGN_MAP,
|
|
1195
|
-
...TEXT_OVERFLOW_MAP,
|
|
1196
|
-
...TEXT_WRAP_MAP,
|
|
1197
|
-
...WHITESPACE_MAP,
|
|
1198
|
-
...WORD_BREAK_MAP,
|
|
1199
|
-
...VERTICAL_ALIGN_MAP,
|
|
1200
|
-
...LIST_STYLE_MAP,
|
|
1201
|
-
...HYPHENS_MAP,
|
|
1202
|
-
// Layout
|
|
1203
|
-
...POSITION_MAP,
|
|
1204
|
-
...VISIBILITY_MAP,
|
|
1205
|
-
...FLOAT_MAP,
|
|
1206
|
-
...CLEAR_MAP,
|
|
1207
|
-
...ISOLATION_MAP,
|
|
1208
|
-
...OBJECT_FIT_MAP,
|
|
1209
|
-
...OBJECT_POSITION_MAP,
|
|
1210
|
-
...OVERFLOW_MAP,
|
|
1211
|
-
...OVERSCROLL_MAP,
|
|
1212
|
-
...Z_INDEX_MAP,
|
|
1213
|
-
...ASPECT_RATIO_MAP,
|
|
1214
|
-
...BOX_SIZING_MAP,
|
|
1215
|
-
...BOX_DECORATION_MAP,
|
|
1216
|
-
// Background
|
|
1217
|
-
...BG_ATTACHMENT_MAP,
|
|
1218
|
-
...BG_CLIP_MAP,
|
|
1219
|
-
...BG_ORIGIN_MAP,
|
|
1220
|
-
...BG_POSITION_MAP,
|
|
1221
|
-
...BG_REPEAT_MAP,
|
|
1222
|
-
...BG_SIZE_MAP,
|
|
1223
|
-
...GRADIENT_MAP,
|
|
1224
|
-
// Interactivity
|
|
1225
|
-
...CURSOR_MAP,
|
|
1226
|
-
...POINTER_EVENTS_MAP,
|
|
1227
|
-
...RESIZE_MAP,
|
|
1228
|
-
...USER_SELECT_MAP,
|
|
1229
|
-
...SCROLL_BEHAVIOR_MAP,
|
|
1230
|
-
...SCROLL_SNAP_MAP,
|
|
1231
|
-
...TOUCH_ACTION_MAP,
|
|
1232
|
-
...WILL_CHANGE_MAP,
|
|
1233
|
-
...APPEARANCE_MAP,
|
|
1234
|
-
// Table
|
|
1235
|
-
...BORDER_COLLAPSE_MAP,
|
|
1236
|
-
...TABLE_LAYOUT_MAP,
|
|
1237
|
-
...CAPTION_SIDE_MAP,
|
|
1238
|
-
// Accessibility
|
|
1239
|
-
...SR_ONLY_MAP,
|
|
1240
|
-
...FORCED_COLOR_MAP,
|
|
1241
|
-
// SVG
|
|
1242
|
-
...FILL_MAP,
|
|
1243
|
-
...STROKE_MAP,
|
|
1244
|
-
...STROKE_LINECAP_MAP,
|
|
1245
|
-
...STROKE_LINEJOIN_MAP,
|
|
1246
|
-
// Filters
|
|
1247
|
-
...BLUR_MAP,
|
|
1248
|
-
...BACKDROP_BLUR_MAP,
|
|
1249
|
-
...FILTER_TOGGLE_MAP,
|
|
1250
|
-
...BACKDROP_FILTER_TOGGLE_MAP,
|
|
1251
|
-
...DROP_SHADOW_MAP,
|
|
1252
|
-
...MIX_BLEND_MAP,
|
|
1253
|
-
...BG_BLEND_MAP,
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
// Pre-computed variant selector map for O(1) lookup (shared across all instances)
|
|
1257
|
-
const VARIANT_SELECTORS: Record<string, string> = {
|
|
1258
|
-
// Pseudo-class variants
|
|
1259
|
-
'hover': ':hover',
|
|
1260
|
-
'focus': ':focus',
|
|
1261
|
-
'active': ':active',
|
|
1262
|
-
'disabled': ':disabled',
|
|
1263
|
-
'visited': ':visited',
|
|
1264
|
-
'checked': ':checked',
|
|
1265
|
-
'focus-within': ':focus-within',
|
|
1266
|
-
'focus-visible': ':focus-visible',
|
|
1267
|
-
// Positional variants
|
|
1268
|
-
'first': ':first-child',
|
|
1269
|
-
'last': ':last-child',
|
|
1270
|
-
'odd': ':nth-child(odd)',
|
|
1271
|
-
'even': ':nth-child(even)',
|
|
1272
|
-
'first-of-type': ':first-of-type',
|
|
1273
|
-
'last-of-type': ':last-of-type',
|
|
1274
|
-
// Pseudo-elements
|
|
1275
|
-
'before': '::before',
|
|
1276
|
-
'after': '::after',
|
|
1277
|
-
'marker': '::marker',
|
|
1278
|
-
'placeholder': '::placeholder',
|
|
1279
|
-
'selection': '::selection',
|
|
1280
|
-
'file': '::file-selector-button',
|
|
1281
|
-
// Form state pseudo-classes
|
|
1282
|
-
'required': ':required',
|
|
1283
|
-
'valid': ':valid',
|
|
1284
|
-
'invalid': ':invalid',
|
|
1285
|
-
'read-only': ':read-only',
|
|
1286
|
-
'autofill': ':autofill',
|
|
1287
|
-
// Additional state pseudo-classes
|
|
1288
|
-
'open': '[open]',
|
|
1289
|
-
'closed': ':not([open])',
|
|
1290
|
-
'empty': ':empty',
|
|
1291
|
-
'enabled': ':enabled',
|
|
1292
|
-
'only': ':only-child',
|
|
1293
|
-
'target': ':target',
|
|
1294
|
-
'indeterminate': ':indeterminate',
|
|
1295
|
-
'default': ':default',
|
|
1296
|
-
'optional': ':optional',
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
// Pre-computed prefix variants (these modify the selector prefix, not suffix)
|
|
1300
|
-
const PREFIX_VARIANTS: Record<string, string> = {
|
|
1301
|
-
'dark': '.dark ',
|
|
1302
|
-
'rtl': '[dir="rtl"] ',
|
|
1303
|
-
'ltr': '[dir="ltr"] ',
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
/**
|
|
1307
|
-
* Generates CSS rules from parsed utility classes
|
|
1308
|
-
*/
|
|
1309
|
-
export class CSSGenerator {
|
|
1310
|
-
private rules: Map<string, CSSRule[]> = new Map()
|
|
1311
|
-
private classCache: Set<string> = new Set()
|
|
1312
|
-
private blocklistRegexCache: RegExp[] = []
|
|
1313
|
-
private blocklistExact: Set<string> = new Set()
|
|
1314
|
-
private selectorCache: Map<string, string> = new Map()
|
|
1315
|
-
private mediaQueryCache: Map<string, string | undefined> = new Map()
|
|
1316
|
-
private ruleCache: Map<string, UtilityRule[]> = new Map()
|
|
1317
|
-
private variantEnabled: Record<string, boolean>
|
|
1318
|
-
private screenBreakpoints: Map<string, string>
|
|
1319
|
-
// Cache for utility+value combinations that don't match any rule (negative cache)
|
|
1320
|
-
private noMatchCache: Set<string> = new Set()
|
|
1321
|
-
// Preserve extend colors for CSS variable generation (only custom colors, not defaults)
|
|
1322
|
-
private extendColors: Record<string, string | Record<string, string>> | null = null
|
|
1323
|
-
|
|
1324
|
-
constructor(private config: CrosswindConfig) {
|
|
1325
|
-
// Merge preset themes into the main config theme
|
|
1326
|
-
if (config.presets && config.presets.length > 0) {
|
|
1327
|
-
for (const preset of config.presets) {
|
|
1328
|
-
if (preset.theme) {
|
|
1329
|
-
this.config.theme = deepMerge(this.config.theme, preset.theme)
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
// Save extend colors before merging (for CSS variable generation)
|
|
1335
|
-
if (config.theme.extend?.colors) {
|
|
1336
|
-
this.extendColors = config.theme.extend.colors as Record<string, string | Record<string, string>>
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// Merge theme.extend into theme (allows users to add custom values without replacing defaults)
|
|
1340
|
-
if (config.theme.extend) {
|
|
1341
|
-
const { extend, ...baseTheme } = this.config.theme
|
|
1342
|
-
if (extend) {
|
|
1343
|
-
this.config.theme = deepMerge(baseTheme, extend) as typeof this.config.theme
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
// Pre-compile blocklist patterns for performance
|
|
1348
|
-
for (const pattern of this.config.blocklist) {
|
|
1349
|
-
if (pattern.includes('*')) {
|
|
1350
|
-
const regexPattern = pattern.replace(/\*/g, '.*')
|
|
1351
|
-
this.blocklistRegexCache.push(new RegExp(`^${regexPattern}$`))
|
|
1352
|
-
}
|
|
1353
|
-
else {
|
|
1354
|
-
this.blocklistExact.add(pattern)
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
// Pre-cache variant enabled state for faster lookup
|
|
1359
|
-
this.variantEnabled = this.config.variants as unknown as Record<string, boolean>
|
|
1360
|
-
|
|
1361
|
-
// Pre-cache screen breakpoints as Map for faster lookup
|
|
1362
|
-
this.screenBreakpoints = new Map(Object.entries(this.config.theme.screens))
|
|
1363
|
-
|
|
1364
|
-
// Build rule lookup map for faster matching
|
|
1365
|
-
this.buildRuleLookup()
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
/**
|
|
1369
|
-
* Build a prefix-based lookup map for rules
|
|
1370
|
-
* This allows O(1) lookup instead of O(n) iteration
|
|
1371
|
-
*/
|
|
1372
|
-
private buildRuleLookup(): void {
|
|
1373
|
-
// Pre-processing done in constructor
|
|
1374
|
-
// Rule caching happens during generation
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
/**
|
|
1378
|
-
* Generate CSS for a utility class
|
|
1379
|
-
*/
|
|
1380
|
-
generate(className: string): void {
|
|
1381
|
-
// Check cache for already processed classes
|
|
1382
|
-
if (this.classCache.has(className)) {
|
|
1383
|
-
return
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
// Check shortcuts first (before marking as cached)
|
|
1387
|
-
const shortcut = this.config.shortcuts[className]
|
|
1388
|
-
if (shortcut) {
|
|
1389
|
-
this.classCache.add(className)
|
|
1390
|
-
const classes = Array.isArray(shortcut) ? shortcut : shortcut.split(/\s+/)
|
|
1391
|
-
for (const cls of classes) {
|
|
1392
|
-
this.generate(cls)
|
|
1393
|
-
}
|
|
1394
|
-
return
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
this.classCache.add(className)
|
|
1398
|
-
|
|
1399
|
-
// Check exact match blocklist first (O(1) Set lookup)
|
|
1400
|
-
if (this.blocklistExact.size > 0 && this.blocklistExact.has(className)) {
|
|
1401
|
-
return
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
// Check if class is blocklisted (use pre-compiled regexes)
|
|
1405
|
-
if (this.blocklistRegexCache.length > 0) {
|
|
1406
|
-
for (let i = 0; i < this.blocklistRegexCache.length; i++) {
|
|
1407
|
-
if (this.blocklistRegexCache[i].test(className)) {
|
|
1408
|
-
return
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
const parsed = parseClass(className)
|
|
1414
|
-
|
|
1415
|
-
// ==========================================================================
|
|
1416
|
-
// FAST PATH: Static utility map lookup (O(1))
|
|
1417
|
-
// Handles ~80% of common utilities without any rule iteration
|
|
1418
|
-
// ==========================================================================
|
|
1419
|
-
|
|
1420
|
-
// Check static raw class map first (display, flex-direction, transform, transition, etc.)
|
|
1421
|
-
const staticResult = STATIC_UTILITY_MAP[parsed.raw]
|
|
1422
|
-
if (staticResult) {
|
|
1423
|
-
this.addRule(parsed, staticResult)
|
|
1424
|
-
return
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
// Fast path for utility-based lookups
|
|
1428
|
-
const utility = parsed.utility
|
|
1429
|
-
const value = parsed.value
|
|
1430
|
-
|
|
1431
|
-
// ==========================================================================
|
|
1432
|
-
// SPACING UTILITIES - Most common, use pre-computed values
|
|
1433
|
-
// ==========================================================================
|
|
1434
|
-
|
|
1435
|
-
// Width: w-{size}
|
|
1436
|
-
if (utility === 'w' && value) {
|
|
1437
|
-
const sizeVal = SIZE_VALUES[value]
|
|
1438
|
-
if (sizeVal) {
|
|
1439
|
-
this.addRule(parsed, { width: sizeVal })
|
|
1440
|
-
return
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
// Height: h-{size}
|
|
1445
|
-
if (utility === 'h' && value) {
|
|
1446
|
-
const sizeVal = SIZE_VALUES[value]
|
|
1447
|
-
if (sizeVal) {
|
|
1448
|
-
this.addRule(parsed, { height: value === 'screen' ? '100vh' : sizeVal })
|
|
1449
|
-
return
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
// Padding: p-{size}
|
|
1454
|
-
if (utility === 'p' && value) {
|
|
1455
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1456
|
-
if (spacingVal) {
|
|
1457
|
-
this.addRule(parsed, { padding: spacingVal })
|
|
1458
|
-
return
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
// Padding X: px-{size}
|
|
1463
|
-
if (utility === 'px' && value) {
|
|
1464
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1465
|
-
if (spacingVal) {
|
|
1466
|
-
this.addRule(parsed, { 'padding-left': spacingVal, 'padding-right': spacingVal })
|
|
1467
|
-
return
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
// Padding Y: py-{size}
|
|
1472
|
-
if (utility === 'py' && value) {
|
|
1473
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1474
|
-
if (spacingVal) {
|
|
1475
|
-
this.addRule(parsed, { 'padding-top': spacingVal, 'padding-bottom': spacingVal })
|
|
1476
|
-
return
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
|
|
1480
|
-
// Padding sides: pt, pr, pb, pl
|
|
1481
|
-
if ((utility === 'pt' || utility === 'pr' || utility === 'pb' || utility === 'pl') && value) {
|
|
1482
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1483
|
-
if (spacingVal) {
|
|
1484
|
-
const propMap: Record<string, string> = { pt: 'padding-top', pr: 'padding-right', pb: 'padding-bottom', pl: 'padding-left' }
|
|
1485
|
-
this.addRule(parsed, { [propMap[utility]]: spacingVal })
|
|
1486
|
-
return
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
// Margin: m-{size}
|
|
1491
|
-
if (utility === 'm' && value) {
|
|
1492
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1493
|
-
if (spacingVal) {
|
|
1494
|
-
this.addRule(parsed, { margin: spacingVal })
|
|
1495
|
-
return
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
// Margin X: mx-{size}
|
|
1500
|
-
if (utility === 'mx' && value) {
|
|
1501
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1502
|
-
if (spacingVal) {
|
|
1503
|
-
this.addRule(parsed, { 'margin-left': spacingVal, 'margin-right': spacingVal })
|
|
1504
|
-
return
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
// Margin Y: my-{size}
|
|
1509
|
-
if (utility === 'my' && value) {
|
|
1510
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1511
|
-
if (spacingVal) {
|
|
1512
|
-
this.addRule(parsed, { 'margin-top': spacingVal, 'margin-bottom': spacingVal })
|
|
1513
|
-
return
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1517
|
-
// Margin sides: mt, mr, mb, ml
|
|
1518
|
-
if ((utility === 'mt' || utility === 'mr' || utility === 'mb' || utility === 'ml') && value) {
|
|
1519
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1520
|
-
if (spacingVal) {
|
|
1521
|
-
const propMap: Record<string, string> = { mt: 'margin-top', mr: 'margin-right', mb: 'margin-bottom', ml: 'margin-left' }
|
|
1522
|
-
this.addRule(parsed, { [propMap[utility]]: spacingVal })
|
|
1523
|
-
return
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
// Position: top, right, bottom, left
|
|
1528
|
-
if ((utility === 'top' || utility === 'right' || utility === 'bottom' || utility === 'left') && value) {
|
|
1529
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1530
|
-
if (spacingVal) {
|
|
1531
|
-
this.addRule(parsed, { [utility]: spacingVal })
|
|
1532
|
-
return
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
// Inset: inset-{size}
|
|
1537
|
-
if (utility === 'inset' && value) {
|
|
1538
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1539
|
-
if (spacingVal) {
|
|
1540
|
-
this.addRule(parsed, { top: spacingVal, right: spacingVal, bottom: spacingVal, left: spacingVal })
|
|
1541
|
-
return
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
// Inset X/Y: inset-x-{size}, inset-y-{size}
|
|
1546
|
-
if (utility === 'inset-x' && value) {
|
|
1547
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1548
|
-
if (spacingVal) {
|
|
1549
|
-
this.addRule(parsed, { left: spacingVal, right: spacingVal })
|
|
1550
|
-
return
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
if (utility === 'inset-y' && value) {
|
|
1554
|
-
const spacingVal = SPACING_VALUES[value]
|
|
1555
|
-
if (spacingVal) {
|
|
1556
|
-
this.addRule(parsed, { top: spacingVal, bottom: spacingVal })
|
|
1557
|
-
return
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
// ==========================================================================
|
|
1562
|
-
// COLOR UTILITIES - Fast path using pre-computed color map
|
|
1563
|
-
// ==========================================================================
|
|
1564
|
-
|
|
1565
|
-
// Background color: bg-{color}-{shade}
|
|
1566
|
-
if (utility === 'bg' && value) {
|
|
1567
|
-
const colorVal = COMMON_COLORS[value]
|
|
1568
|
-
if (colorVal) {
|
|
1569
|
-
this.addRule(parsed, { 'background-color': colorVal })
|
|
1570
|
-
return
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
// Text color: text-{color}-{shade}
|
|
1575
|
-
if (utility === 'text' && value) {
|
|
1576
|
-
const colorVal = COMMON_COLORS[value]
|
|
1577
|
-
if (colorVal) {
|
|
1578
|
-
this.addRule(parsed, { color: colorVal })
|
|
1579
|
-
return
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
// Border color: border-{color}-{shade}
|
|
1584
|
-
if (utility === 'border' && value) {
|
|
1585
|
-
const colorVal = COMMON_COLORS[value]
|
|
1586
|
-
if (colorVal) {
|
|
1587
|
-
this.addRule(parsed, { 'border-color': colorVal })
|
|
1588
|
-
return
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
// Justify content: justify-{start|end|center|between|around|evenly}
|
|
1593
|
-
if (utility === 'justify' && value) {
|
|
1594
|
-
const justifyValue = JUSTIFY_CONTENT_VALUES[value]
|
|
1595
|
-
if (justifyValue) {
|
|
1596
|
-
this.addRule(parsed, { 'justify-content': justifyValue })
|
|
1597
|
-
return
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
// Align items: items-{start|end|center|baseline|stretch}
|
|
1602
|
-
if (utility === 'items' && value) {
|
|
1603
|
-
const itemsValue = ALIGN_ITEMS_VALUES[value]
|
|
1604
|
-
if (itemsValue) {
|
|
1605
|
-
this.addRule(parsed, { 'align-items': itemsValue })
|
|
1606
|
-
return
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
// Align content: content-{normal|center|start|end|between|around|evenly|baseline|stretch}
|
|
1611
|
-
if (utility === 'content' && value) {
|
|
1612
|
-
const contentValue = ALIGN_CONTENT_VALUES[value]
|
|
1613
|
-
if (contentValue) {
|
|
1614
|
-
this.addRule(parsed, { 'align-content': contentValue })
|
|
1615
|
-
return
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
// Align self: self-{auto|start|end|center|stretch|baseline}
|
|
1620
|
-
if (utility === 'self' && value) {
|
|
1621
|
-
const selfValue = ALIGN_SELF_VALUES[value]
|
|
1622
|
-
if (selfValue) {
|
|
1623
|
-
this.addRule(parsed, { 'align-self': selfValue })
|
|
1624
|
-
return
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
|
|
1628
|
-
// Grid columns: grid-cols-{1-12|none|subgrid}
|
|
1629
|
-
if (utility === 'grid-cols' && value) {
|
|
1630
|
-
const colsValue = GRID_COLS_VALUES[value]
|
|
1631
|
-
if (colsValue) {
|
|
1632
|
-
this.addRule(parsed, { 'grid-template-columns': colsValue })
|
|
1633
|
-
return
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
// Grid rows: grid-rows-{1-6|none|subgrid}
|
|
1638
|
-
if (utility === 'grid-rows' && value) {
|
|
1639
|
-
const rowsValue = GRID_ROWS_VALUES[value]
|
|
1640
|
-
if (rowsValue) {
|
|
1641
|
-
this.addRule(parsed, { 'grid-template-rows': rowsValue })
|
|
1642
|
-
return
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
// Grid column span: col-{auto|span-1..12|span-full}
|
|
1647
|
-
if (utility === 'col' && value) {
|
|
1648
|
-
const colValue = GRID_COL_VALUES[value]
|
|
1649
|
-
if (colValue) {
|
|
1650
|
-
this.addRule(parsed, { 'grid-column': colValue })
|
|
1651
|
-
return
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
// Grid row span: row-{auto|span-1..6|span-full}
|
|
1656
|
-
if (utility === 'row' && value) {
|
|
1657
|
-
const rowValue = GRID_ROW_VALUES[value]
|
|
1658
|
-
if (rowValue) {
|
|
1659
|
-
this.addRule(parsed, { 'grid-row': rowValue })
|
|
1660
|
-
return
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
|
-
// Grid auto flow: grid-flow-{row|col|dense|row-dense|col-dense}
|
|
1665
|
-
if (utility === 'grid-flow' && value) {
|
|
1666
|
-
const flowValue = GRID_FLOW_VALUES[value]
|
|
1667
|
-
if (flowValue) {
|
|
1668
|
-
this.addRule(parsed, { 'grid-auto-flow': flowValue })
|
|
1669
|
-
return
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
// Auto cols: auto-cols-{auto|min|max|fr}
|
|
1674
|
-
if (utility === 'auto-cols' && value) {
|
|
1675
|
-
const autoColsValue = AUTO_COLS_ROWS_VALUES[value]
|
|
1676
|
-
if (autoColsValue) {
|
|
1677
|
-
this.addRule(parsed, { 'grid-auto-columns': autoColsValue })
|
|
1678
|
-
return
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
// Auto rows: auto-rows-{auto|min|max|fr}
|
|
1683
|
-
if (utility === 'auto-rows' && value) {
|
|
1684
|
-
const autoRowsValue = AUTO_COLS_ROWS_VALUES[value]
|
|
1685
|
-
if (autoRowsValue) {
|
|
1686
|
-
this.addRule(parsed, { 'grid-auto-rows': autoRowsValue })
|
|
1687
|
-
return
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
// Transform origin: origin-{center|top|top-right|...}
|
|
1692
|
-
if (utility === 'origin' && value) {
|
|
1693
|
-
const originValue = TRANSFORM_ORIGIN_VALUES[value]
|
|
1694
|
-
if (originValue) {
|
|
1695
|
-
this.addRule(parsed, { 'transform-origin': originValue })
|
|
1696
|
-
return
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
// Scale: scale-{0-150} -> transform: scale(value/100)
|
|
1701
|
-
if (utility === 'scale' && value && !parsed.arbitrary) {
|
|
1702
|
-
const scaleNum = Number(value) / 100
|
|
1703
|
-
if (!Number.isNaN(scaleNum)) {
|
|
1704
|
-
this.addRule(parsed, { transform: `scale(${scaleNum})` })
|
|
1705
|
-
return
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
if (utility === 'scale-x' && value && !parsed.arbitrary) {
|
|
1709
|
-
const scaleNum = Number(value) / 100
|
|
1710
|
-
if (!Number.isNaN(scaleNum)) {
|
|
1711
|
-
this.addRule(parsed, { transform: `scaleX(${scaleNum})` })
|
|
1712
|
-
return
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
if (utility === 'scale-y' && value && !parsed.arbitrary) {
|
|
1716
|
-
const scaleNum = Number(value) / 100
|
|
1717
|
-
if (!Number.isNaN(scaleNum)) {
|
|
1718
|
-
this.addRule(parsed, { transform: `scaleY(${scaleNum})` })
|
|
1719
|
-
return
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
// Rotate: rotate-{0-180} -> transform: rotate(Ndeg)
|
|
1724
|
-
if (utility === 'rotate' && value && !parsed.arbitrary) {
|
|
1725
|
-
this.addRule(parsed, { transform: `rotate(${value}deg)` })
|
|
1726
|
-
return
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
// Duration: duration-{75|100|150|200|300|500|700|1000}
|
|
1730
|
-
if (utility === 'duration' && value) {
|
|
1731
|
-
this.addRule(parsed, { 'transition-duration': `${value}ms` })
|
|
1732
|
-
return
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
// Delay: delay-{75|100|150|200|300|500|700|1000}
|
|
1736
|
-
if (utility === 'delay' && value) {
|
|
1737
|
-
this.addRule(parsed, { 'transition-delay': `${value}ms` })
|
|
1738
|
-
return
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
// Gap: gap-{spacing}
|
|
1742
|
-
if (utility === 'gap' && value) {
|
|
1743
|
-
const gapValue = this.config.theme.spacing[value] || value
|
|
1744
|
-
this.addRule(parsed, { gap: gapValue })
|
|
1745
|
-
return
|
|
1746
|
-
}
|
|
1747
|
-
if (utility === 'gap-x' && value) {
|
|
1748
|
-
const gapValue = this.config.theme.spacing[value] || value
|
|
1749
|
-
this.addRule(parsed, { 'column-gap': gapValue })
|
|
1750
|
-
return
|
|
1751
|
-
}
|
|
1752
|
-
if (utility === 'gap-y' && value) {
|
|
1753
|
-
const gapValue = this.config.theme.spacing[value] || value
|
|
1754
|
-
this.addRule(parsed, { 'row-gap': gapValue })
|
|
1755
|
-
return
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
// Place content/items/self
|
|
1759
|
-
if (utility === 'place' && value) {
|
|
1760
|
-
if (value.startsWith('content-')) {
|
|
1761
|
-
const placeValue = PLACE_CONTENT_VALUES[value.slice(8)]
|
|
1762
|
-
if (placeValue) {
|
|
1763
|
-
this.addRule(parsed, { 'place-content': placeValue })
|
|
1764
|
-
return
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
if (value.startsWith('items-')) {
|
|
1768
|
-
const placeValue = PLACE_CONTENT_VALUES[value.slice(6)]
|
|
1769
|
-
if (placeValue) {
|
|
1770
|
-
this.addRule(parsed, { 'place-items': placeValue })
|
|
1771
|
-
return
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
if (value.startsWith('self-')) {
|
|
1775
|
-
const placeValue = PLACE_CONTENT_VALUES[value.slice(5)]
|
|
1776
|
-
if (placeValue) {
|
|
1777
|
-
this.addRule(parsed, { 'place-self': placeValue })
|
|
1778
|
-
return
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
// ==========================================================================
|
|
1784
|
-
// SLOW PATH: Rule iteration (only if fast path didn't match)
|
|
1785
|
-
// ==========================================================================
|
|
1786
|
-
|
|
1787
|
-
// Check no-match cache - if this utility+value combo was already determined to not match
|
|
1788
|
-
// any rule, skip the expensive rule iteration (especially helpful for variant classes)
|
|
1789
|
-
const utilityKey = `${parsed.utility}:${parsed.value || ''}`
|
|
1790
|
-
if (this.noMatchCache.has(utilityKey)) {
|
|
1791
|
-
return
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
// Try custom rules from config first (allows overriding built-in rules)
|
|
1795
|
-
if (this.config.rules.length > 0) {
|
|
1796
|
-
for (const [pattern, handler] of this.config.rules) {
|
|
1797
|
-
const match = className.match(pattern)
|
|
1798
|
-
if (match) {
|
|
1799
|
-
const properties = handler(match)
|
|
1800
|
-
if (properties) {
|
|
1801
|
-
this.addRule(parsed, properties)
|
|
1802
|
-
return
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1808
|
-
// Try built-in rules with optimized iteration
|
|
1809
|
-
const rulesLength = builtInRules.length
|
|
1810
|
-
for (let i = 0; i < rulesLength; i++) {
|
|
1811
|
-
const result = builtInRules[i](parsed, this.config)
|
|
1812
|
-
if (result) {
|
|
1813
|
-
// Handle both old format (just properties) and new format (object with properties and childSelector/pseudoElement)
|
|
1814
|
-
if ('properties' in result && typeof result.properties === 'object') {
|
|
1815
|
-
this.addRule(parsed, result.properties, result.childSelector, result.pseudoElement)
|
|
1816
|
-
}
|
|
1817
|
-
else {
|
|
1818
|
-
this.addRule(parsed, result as Record<string, string>)
|
|
1819
|
-
}
|
|
1820
|
-
return
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
// No rule matched - cache this utility+value combo to skip future iterations
|
|
1825
|
-
this.noMatchCache.add(utilityKey)
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
/**
|
|
1829
|
-
* Add a CSS rule with variants applied
|
|
1830
|
-
*/
|
|
1831
|
-
private addRule(parsed: ParsedClass, properties: Record<string, string>, childSelector?: string, pseudoElement?: string): void {
|
|
1832
|
-
// Use cached selector if available
|
|
1833
|
-
const cacheKey = `${parsed.raw}${childSelector || ''}${pseudoElement || ''}`
|
|
1834
|
-
let selector = this.selectorCache.get(cacheKey)
|
|
1835
|
-
if (!selector) {
|
|
1836
|
-
selector = this.buildSelector(parsed)
|
|
1837
|
-
// Append pseudo-element directly (no space)
|
|
1838
|
-
if (pseudoElement) {
|
|
1839
|
-
selector += pseudoElement
|
|
1840
|
-
}
|
|
1841
|
-
// Append child selector if provided
|
|
1842
|
-
if (childSelector) {
|
|
1843
|
-
selector += ` ${childSelector}`
|
|
1844
|
-
}
|
|
1845
|
-
this.selectorCache.set(cacheKey, selector)
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
const mediaQuery = this.getMediaQuery(parsed)
|
|
1849
|
-
|
|
1850
|
-
// Apply !important modifier
|
|
1851
|
-
if (parsed.important) {
|
|
1852
|
-
for (const key in properties) {
|
|
1853
|
-
properties[key] += ' !important'
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
const key = mediaQuery || 'base'
|
|
1858
|
-
if (!this.rules.has(key)) {
|
|
1859
|
-
this.rules.set(key, [])
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
|
-
this.rules.get(key)!.push({
|
|
1863
|
-
selector,
|
|
1864
|
-
properties,
|
|
1865
|
-
mediaQuery,
|
|
1866
|
-
childSelector,
|
|
1867
|
-
})
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
/**
|
|
1871
|
-
* Build CSS selector with pseudo-classes and variants
|
|
1872
|
-
* Optimized with pre-computed lookup maps for O(1) variant resolution
|
|
1873
|
-
*/
|
|
1874
|
-
private buildSelector(parsed: ParsedClass): string {
|
|
1875
|
-
let selector = `.${this.escapeSelector(parsed.raw)}`
|
|
1876
|
-
let prefix = ''
|
|
1877
|
-
|
|
1878
|
-
const variants = parsed.variants
|
|
1879
|
-
const variantsLen = variants.length
|
|
1880
|
-
|
|
1881
|
-
// Fast path: no variants
|
|
1882
|
-
if (variantsLen === 0) {
|
|
1883
|
-
return selector
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
|
-
// Apply variants using pre-computed maps
|
|
1887
|
-
for (let i = 0; i < variantsLen; i++) {
|
|
1888
|
-
const variant = variants[i]
|
|
1889
|
-
|
|
1890
|
-
// Try suffix selector lookup first (most common case)
|
|
1891
|
-
const suffixSelector = VARIANT_SELECTORS[variant]
|
|
1892
|
-
if (suffixSelector !== undefined) {
|
|
1893
|
-
// Check if variant is enabled
|
|
1894
|
-
if (this.variantEnabled[variant]) {
|
|
1895
|
-
selector += suffixSelector
|
|
1896
|
-
}
|
|
1897
|
-
continue
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
// Try prefix selector lookup (dark, rtl, ltr)
|
|
1901
|
-
const prefixSelector = PREFIX_VARIANTS[variant]
|
|
1902
|
-
if (prefixSelector !== undefined) {
|
|
1903
|
-
if (this.variantEnabled[variant]) {
|
|
1904
|
-
prefix = prefixSelector
|
|
1905
|
-
}
|
|
1906
|
-
continue
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
// Handle group-* variants
|
|
1910
|
-
if (variant.charCodeAt(0) === 103 && variant.startsWith('group-')) { // 'g' = 103
|
|
1911
|
-
if (this.variantEnabled.group) {
|
|
1912
|
-
const groupVariant = variant.slice(6)
|
|
1913
|
-
prefix = `.group:${groupVariant} `
|
|
1914
|
-
}
|
|
1915
|
-
continue
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
// Handle peer-* variants
|
|
1919
|
-
if (variant.charCodeAt(0) === 112 && variant.startsWith('peer-')) { // 'p' = 112
|
|
1920
|
-
if (this.variantEnabled.peer) {
|
|
1921
|
-
const peerVariant = variant.slice(5)
|
|
1922
|
-
prefix = `.peer:${peerVariant} ~ `
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
return prefix + selector
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
|
-
/**
|
|
1931
|
-
* Get media query for responsive and media variants
|
|
1932
|
-
* Optimized with pre-cached lookups and early returns
|
|
1933
|
-
*/
|
|
1934
|
-
private getMediaQuery(parsed: ParsedClass): string | undefined {
|
|
1935
|
-
const variants = parsed.variants
|
|
1936
|
-
const variantsLen = variants.length
|
|
1937
|
-
|
|
1938
|
-
// Fast path: no variants
|
|
1939
|
-
if (variantsLen === 0) {
|
|
1940
|
-
return undefined
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
// Use cached media query if available
|
|
1944
|
-
const cacheKey = variants.join(':')
|
|
1945
|
-
const cached = this.mediaQueryCache.get(cacheKey)
|
|
1946
|
-
if (cached !== undefined) {
|
|
1947
|
-
return cached || undefined // Convert empty string to undefined
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
let result: string | undefined
|
|
1951
|
-
|
|
1952
|
-
for (let i = 0; i < variantsLen; i++) {
|
|
1953
|
-
const variant = variants[i]
|
|
1954
|
-
const firstChar = variant.charCodeAt(0)
|
|
1955
|
-
|
|
1956
|
-
// Container queries (@sm, @md, @lg, etc.) - '@' = 64
|
|
1957
|
-
if (firstChar === 64) {
|
|
1958
|
-
const breakpointKey = variant.slice(1)
|
|
1959
|
-
const breakpoint = this.screenBreakpoints.get(breakpointKey)
|
|
1960
|
-
if (breakpoint) {
|
|
1961
|
-
result = `@container (min-width: ${breakpoint})`
|
|
1962
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
1963
|
-
return result
|
|
1964
|
-
}
|
|
1965
|
-
continue
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
// Responsive breakpoints - check if variant is a screen breakpoint
|
|
1969
|
-
if (this.variantEnabled.responsive) {
|
|
1970
|
-
const breakpoint = this.screenBreakpoints.get(variant)
|
|
1971
|
-
if (breakpoint) {
|
|
1972
|
-
result = `@media (min-width: ${breakpoint})`
|
|
1973
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
1974
|
-
return result
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
|
-
// Media preference variants - use switch for common cases
|
|
1979
|
-
switch (variant) {
|
|
1980
|
-
case 'print':
|
|
1981
|
-
if (this.variantEnabled.print) {
|
|
1982
|
-
result = '@media print'
|
|
1983
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
1984
|
-
return result
|
|
1985
|
-
}
|
|
1986
|
-
break
|
|
1987
|
-
case 'motion-safe':
|
|
1988
|
-
if (this.variantEnabled['motion-safe']) {
|
|
1989
|
-
result = '@media (prefers-reduced-motion: no-preference)'
|
|
1990
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
1991
|
-
return result
|
|
1992
|
-
}
|
|
1993
|
-
break
|
|
1994
|
-
case 'motion-reduce':
|
|
1995
|
-
if (this.variantEnabled['motion-reduce']) {
|
|
1996
|
-
result = '@media (prefers-reduced-motion: reduce)'
|
|
1997
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
1998
|
-
return result
|
|
1999
|
-
}
|
|
2000
|
-
break
|
|
2001
|
-
case 'contrast-more':
|
|
2002
|
-
if (this.variantEnabled['contrast-more']) {
|
|
2003
|
-
result = '@media (prefers-contrast: more)'
|
|
2004
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
2005
|
-
return result
|
|
2006
|
-
}
|
|
2007
|
-
break
|
|
2008
|
-
case 'contrast-less':
|
|
2009
|
-
if (this.variantEnabled['contrast-less']) {
|
|
2010
|
-
result = '@media (prefers-contrast: less)'
|
|
2011
|
-
this.mediaQueryCache.set(cacheKey, result)
|
|
2012
|
-
return result
|
|
2013
|
-
}
|
|
2014
|
-
break
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
this.mediaQueryCache.set(cacheKey, '') // Use empty string as "no result" marker
|
|
2019
|
-
return undefined
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
/**
|
|
2023
|
-
* Escape special characters in class names for CSS selectors
|
|
2024
|
-
* Optimized with charCode checks for common fast path
|
|
2025
|
-
*/
|
|
2026
|
-
private escapeSelector(className: string): string {
|
|
2027
|
-
// Fast path: check if string needs escaping at all
|
|
2028
|
-
let needsEscape = false
|
|
2029
|
-
for (let i = 0; i < className.length; i++) {
|
|
2030
|
-
const c = className.charCodeAt(i)
|
|
2031
|
-
// Check for : (58), . (46), / (47), @ (64), space (32), [ (91), ] (93)
|
|
2032
|
-
if (c === 58 || c === 46 || c === 47 || c === 64 || c === 32 || c === 91 || c === 93) {
|
|
2033
|
-
needsEscape = true
|
|
2034
|
-
break
|
|
2035
|
-
}
|
|
2036
|
-
}
|
|
2037
|
-
if (!needsEscape) {
|
|
2038
|
-
return className
|
|
2039
|
-
}
|
|
2040
|
-
return className.replace(/[:./@ \[\]]/g, '\\$&')
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
/**
|
|
2044
|
-
* Generate final CSS output
|
|
2045
|
-
*/
|
|
2046
|
-
toCSS(includePreflight = true, minify = false): string {
|
|
2047
|
-
const parts: string[] = []
|
|
2048
|
-
|
|
2049
|
-
// Add preflight CSS first (if requested)
|
|
2050
|
-
if (includePreflight) {
|
|
2051
|
-
for (const preflight of this.config.preflights) {
|
|
2052
|
-
let preflightCSS = preflight.getCSS()
|
|
2053
|
-
// Replace hardcoded font-family in preflight with theme's sans font
|
|
2054
|
-
const sansFonts = this.config.theme?.fontFamily?.sans
|
|
2055
|
-
if (sansFonts && Array.isArray(sansFonts)) {
|
|
2056
|
-
const fontFamilyValue = sansFonts.join(', ')
|
|
2057
|
-
// Replace the default ui-sans-serif stack in html/:host selector
|
|
2058
|
-
preflightCSS = preflightCSS.replace(
|
|
2059
|
-
/font-family:\s*ui-sans-serif[^;]+;/g,
|
|
2060
|
-
`font-family: ${fontFamilyValue};`,
|
|
2061
|
-
)
|
|
2062
|
-
}
|
|
2063
|
-
parts.push(minify ? preflightCSS.replace(/\s+/g, ' ').trim() : preflightCSS)
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
|
|
2067
|
-
// Generate CSS variables from theme colors if enabled
|
|
2068
|
-
if (this.config.cssVariables) {
|
|
2069
|
-
const vars = this.generateCSSVariables()
|
|
2070
|
-
if (vars) {
|
|
2071
|
-
parts.push(minify ? vars.replace(/\s+/g, ' ').trim() : vars)
|
|
2072
|
-
}
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
// Base rules (no media query)
|
|
2076
|
-
const baseRules = this.rules.get('base') || []
|
|
2077
|
-
if (baseRules.length > 0) {
|
|
2078
|
-
parts.push(this.rulesToCSS(baseRules, minify))
|
|
2079
|
-
}
|
|
2080
|
-
|
|
2081
|
-
// Media query rules
|
|
2082
|
-
for (const [key, rules] of this.rules.entries()) {
|
|
2083
|
-
if (key !== 'base' && rules.length > 0) {
|
|
2084
|
-
const mediaQuery = rules[0].mediaQuery!
|
|
2085
|
-
const css = this.rulesToCSS(rules, minify)
|
|
2086
|
-
parts.push(minify ? `${mediaQuery}{${css}}` : `${mediaQuery} {\n${css}\n}`)
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
|
|
2090
|
-
return minify ? parts.join('') : parts.join('\n\n')
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
/**
|
|
2094
|
-
* Convert rules to CSS string
|
|
2095
|
-
*/
|
|
2096
|
-
private rulesToCSS(rules: CSSRule[], minify: boolean): string {
|
|
2097
|
-
const grouped = this.groupRulesBySelector(rules)
|
|
2098
|
-
const parts: string[] = []
|
|
2099
|
-
|
|
2100
|
-
for (const [selector, properties] of grouped.entries()) {
|
|
2101
|
-
const props = Array.from(properties.entries())
|
|
2102
|
-
.map(([prop, value]) => minify ? `${prop}:${value}` : ` ${prop}: ${value};`)
|
|
2103
|
-
.join(minify ? ';' : '\n')
|
|
2104
|
-
|
|
2105
|
-
if (minify) {
|
|
2106
|
-
parts.push(`${selector}{${props}}`)
|
|
2107
|
-
}
|
|
2108
|
-
else {
|
|
2109
|
-
parts.push(`${selector} {\n${props}\n}`)
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
|
|
2113
|
-
return minify ? parts.join('') : parts.join('\n\n')
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
/**
|
|
2117
|
-
* Group rules by selector and merge properties
|
|
2118
|
-
*/
|
|
2119
|
-
private groupRulesBySelector(rules: CSSRule[]): Map<string, Map<string, string>> {
|
|
2120
|
-
const grouped = new Map<string, Map<string, string>>()
|
|
2121
|
-
|
|
2122
|
-
for (const rule of rules) {
|
|
2123
|
-
if (!grouped.has(rule.selector)) {
|
|
2124
|
-
grouped.set(rule.selector, new Map())
|
|
2125
|
-
}
|
|
2126
|
-
const props = grouped.get(rule.selector)!
|
|
2127
|
-
for (const [prop, value] of Object.entries(rule.properties)) {
|
|
2128
|
-
props.set(prop, value)
|
|
2129
|
-
}
|
|
2130
|
-
}
|
|
2131
|
-
|
|
2132
|
-
return grouped
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
|
-
/**
|
|
2136
|
-
* Generate :root CSS variables from theme colors
|
|
2137
|
-
* Uses only extend colors (custom) if available, to avoid dumping 300+ default Tailwind colors.
|
|
2138
|
-
* Flattens nested color objects: { monokai: { bg: '#2d2a2e' } } -> --monokai-bg: #2d2a2e
|
|
2139
|
-
*/
|
|
2140
|
-
private generateCSSVariables(): string | null {
|
|
2141
|
-
// Prefer extend colors (user's custom colors only), fall back to all theme colors
|
|
2142
|
-
const colors = this.extendColors || this.config.theme.colors
|
|
2143
|
-
if (!colors || Object.keys(colors).length === 0) return null
|
|
2144
|
-
|
|
2145
|
-
const vars: string[] = []
|
|
2146
|
-
for (const [name, value] of Object.entries(colors)) {
|
|
2147
|
-
if (typeof value === 'string') {
|
|
2148
|
-
vars.push(` --${name}: ${value};`)
|
|
2149
|
-
}
|
|
2150
|
-
else if (typeof value === 'object' && value !== null) {
|
|
2151
|
-
for (const [shade, shadeValue] of Object.entries(value)) {
|
|
2152
|
-
if (typeof shadeValue === 'string') {
|
|
2153
|
-
vars.push(` --${name}-${shade}: ${shadeValue};`)
|
|
2154
|
-
}
|
|
2155
|
-
}
|
|
2156
|
-
}
|
|
2157
|
-
}
|
|
2158
|
-
|
|
2159
|
-
if (vars.length === 0) return null
|
|
2160
|
-
return `:root {\n${vars.join('\n')}\n}`
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
|
-
/**
|
|
2164
|
-
* Reset the generator state
|
|
2165
|
-
*/
|
|
2166
|
-
reset(): void {
|
|
2167
|
-
this.rules.clear()
|
|
2168
|
-
this.classCache.clear()
|
|
2169
|
-
this.selectorCache.clear()
|
|
2170
|
-
this.mediaQueryCache.clear()
|
|
2171
|
-
this.noMatchCache.clear()
|
|
2172
|
-
}
|
|
2173
|
-
}
|