@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/rules-layout.ts
DELETED
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
import type { UtilityRule } from './rules'
|
|
2
|
-
|
|
3
|
-
// Layout utilities
|
|
4
|
-
|
|
5
|
-
export const aspectRatioRule: UtilityRule = (parsed) => {
|
|
6
|
-
if (parsed.utility === 'aspect') {
|
|
7
|
-
const ratios: Record<string, string> = {
|
|
8
|
-
auto: 'auto',
|
|
9
|
-
square: '1 / 1',
|
|
10
|
-
video: '16 / 9',
|
|
11
|
-
}
|
|
12
|
-
return parsed.value ? { 'aspect-ratio': ratios[parsed.value] || parsed.value } : undefined
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const columnsRule: UtilityRule = (parsed, config) => {
|
|
17
|
-
if (parsed.utility === 'columns' && parsed.value) {
|
|
18
|
-
// Named column counts
|
|
19
|
-
const columnCounts: Record<string, string> = {
|
|
20
|
-
'1': '1',
|
|
21
|
-
'2': '2',
|
|
22
|
-
'3': '3',
|
|
23
|
-
'4': '4',
|
|
24
|
-
'5': '5',
|
|
25
|
-
'6': '6',
|
|
26
|
-
'7': '7',
|
|
27
|
-
'8': '8',
|
|
28
|
-
'9': '9',
|
|
29
|
-
'10': '10',
|
|
30
|
-
'11': '11',
|
|
31
|
-
'12': '12',
|
|
32
|
-
'auto': 'auto',
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Named column widths (like Tailwind)
|
|
36
|
-
const columnWidths: Record<string, string> = {
|
|
37
|
-
'3xs': '16rem',
|
|
38
|
-
'2xs': '18rem',
|
|
39
|
-
'xs': '20rem',
|
|
40
|
-
'sm': '24rem',
|
|
41
|
-
'md': '28rem',
|
|
42
|
-
'lg': '32rem',
|
|
43
|
-
'xl': '36rem',
|
|
44
|
-
'2xl': '42rem',
|
|
45
|
-
'3xl': '48rem',
|
|
46
|
-
'4xl': '56rem',
|
|
47
|
-
'5xl': '64rem',
|
|
48
|
-
'6xl': '72rem',
|
|
49
|
-
'7xl': '80rem',
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Check column counts first
|
|
53
|
-
if (columnCounts[parsed.value]) {
|
|
54
|
-
return { columns: columnCounts[parsed.value] }
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Check named widths
|
|
58
|
-
if (columnWidths[parsed.value]) {
|
|
59
|
-
return { columns: columnWidths[parsed.value] }
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Check spacing config
|
|
63
|
-
if (config.theme.spacing[parsed.value]) {
|
|
64
|
-
return { columns: config.theme.spacing[parsed.value] }
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Arbitrary value support
|
|
68
|
-
return { columns: parsed.value }
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Column fill
|
|
73
|
-
export const columnFillRule: UtilityRule = (parsed) => {
|
|
74
|
-
const values: Record<string, string> = {
|
|
75
|
-
'column-fill-auto': 'auto',
|
|
76
|
-
'column-fill-balance': 'balance',
|
|
77
|
-
'column-fill-balance-all': 'balance-all',
|
|
78
|
-
}
|
|
79
|
-
return values[parsed.raw] ? { 'column-fill': values[parsed.raw] } : undefined
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Column gap (different from grid gap)
|
|
83
|
-
export const columnGapRule: UtilityRule = (parsed, config) => {
|
|
84
|
-
if (parsed.utility === 'column-gap' && parsed.value) {
|
|
85
|
-
return { 'column-gap': config.theme.spacing[parsed.value] || parsed.value }
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Column rule (border between columns)
|
|
90
|
-
export const columnRuleRule: UtilityRule = (parsed, config) => {
|
|
91
|
-
// column-rule-width
|
|
92
|
-
if (parsed.utility === 'column-rule' && parsed.value) {
|
|
93
|
-
const widths: Record<string, string> = {
|
|
94
|
-
'0': '0px',
|
|
95
|
-
'1': '1px',
|
|
96
|
-
'2': '2px',
|
|
97
|
-
'4': '4px',
|
|
98
|
-
'8': '8px',
|
|
99
|
-
}
|
|
100
|
-
if (widths[parsed.value]) {
|
|
101
|
-
return { 'column-rule-width': widths[parsed.value] } as Record<string, string>
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Check for colors
|
|
105
|
-
const parts = parsed.value.split('-')
|
|
106
|
-
if (parts.length === 2) {
|
|
107
|
-
const [colorName, shade] = parts
|
|
108
|
-
const colorValue = config.theme.colors[colorName]
|
|
109
|
-
if (typeof colorValue === 'object' && colorValue[shade]) {
|
|
110
|
-
return { 'column-rule-color': colorValue[shade] } as Record<string, string>
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Direct color
|
|
115
|
-
const directColor = config.theme.colors[parsed.value]
|
|
116
|
-
if (typeof directColor === 'string') {
|
|
117
|
-
return { 'column-rule-color': directColor } as Record<string, string>
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Style
|
|
121
|
-
const styles: Record<string, string> = {
|
|
122
|
-
solid: 'solid',
|
|
123
|
-
dashed: 'dashed',
|
|
124
|
-
dotted: 'dotted',
|
|
125
|
-
double: 'double',
|
|
126
|
-
hidden: 'hidden',
|
|
127
|
-
none: 'none',
|
|
128
|
-
}
|
|
129
|
-
if (styles[parsed.value]) {
|
|
130
|
-
return { 'column-rule-style': styles[parsed.value] } as Record<string, string>
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Column span
|
|
136
|
-
export const columnSpanRule: UtilityRule = (parsed) => {
|
|
137
|
-
const values: Record<string, string> = {
|
|
138
|
-
'column-span-all': 'all',
|
|
139
|
-
'column-span-none': 'none',
|
|
140
|
-
}
|
|
141
|
-
return values[parsed.raw] ? { 'column-span': values[parsed.raw] } : undefined
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export const breakRule: UtilityRule = (parsed) => {
|
|
145
|
-
const breaks: Record<string, Record<string, string>> = {
|
|
146
|
-
'break-before-auto': { 'break-before': 'auto' },
|
|
147
|
-
'break-before-avoid': { 'break-before': 'avoid' },
|
|
148
|
-
'break-before-all': { 'break-before': 'all' },
|
|
149
|
-
'break-before-avoid-page': { 'break-before': 'avoid-page' },
|
|
150
|
-
'break-before-page': { 'break-before': 'page' },
|
|
151
|
-
'break-after-auto': { 'break-after': 'auto' },
|
|
152
|
-
'break-after-avoid': { 'break-after': 'avoid' },
|
|
153
|
-
'break-after-all': { 'break-after': 'all' },
|
|
154
|
-
'break-after-avoid-page': { 'break-after': 'avoid-page' },
|
|
155
|
-
'break-after-page': { 'break-after': 'page' },
|
|
156
|
-
'break-inside-auto': { 'break-inside': 'auto' },
|
|
157
|
-
'break-inside-avoid': { 'break-inside': 'avoid' },
|
|
158
|
-
'break-inside-avoid-page': { 'break-inside': 'avoid-page' },
|
|
159
|
-
'break-inside-avoid-column': { 'break-inside': 'avoid-column' },
|
|
160
|
-
}
|
|
161
|
-
return breaks[parsed.raw]
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export const boxDecorationRule: UtilityRule = (parsed) => {
|
|
165
|
-
const values: Record<string, string> = {
|
|
166
|
-
'box-decoration-clone': 'clone',
|
|
167
|
-
'box-decoration-slice': 'slice',
|
|
168
|
-
}
|
|
169
|
-
return values[parsed.raw] ? { 'box-decoration-break': values[parsed.raw] } : undefined
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export const boxSizingRule: UtilityRule = (parsed) => {
|
|
173
|
-
const values: Record<string, string> = {
|
|
174
|
-
'box-border': 'border-box',
|
|
175
|
-
'box-content': 'content-box',
|
|
176
|
-
}
|
|
177
|
-
return values[parsed.raw] ? { 'box-sizing': values[parsed.raw] } : undefined
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export const floatRule: UtilityRule = (parsed) => {
|
|
181
|
-
const floats: Record<string, string> = {
|
|
182
|
-
'float-start': 'inline-start',
|
|
183
|
-
'float-end': 'inline-end',
|
|
184
|
-
'float-right': 'right',
|
|
185
|
-
'float-left': 'left',
|
|
186
|
-
'float-none': 'none',
|
|
187
|
-
}
|
|
188
|
-
return floats[parsed.raw] ? { float: floats[parsed.raw] } : undefined
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export const clearRule: UtilityRule = (parsed) => {
|
|
192
|
-
const clears: Record<string, string> = {
|
|
193
|
-
'clear-start': 'inline-start',
|
|
194
|
-
'clear-end': 'inline-end',
|
|
195
|
-
'clear-left': 'left',
|
|
196
|
-
'clear-right': 'right',
|
|
197
|
-
'clear-both': 'both',
|
|
198
|
-
'clear-none': 'none',
|
|
199
|
-
}
|
|
200
|
-
return clears[parsed.raw] ? { clear: clears[parsed.raw] } : undefined
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export const isolationRule: UtilityRule = (parsed) => {
|
|
204
|
-
const values: Record<string, string> = {
|
|
205
|
-
'isolate': 'isolate',
|
|
206
|
-
'isolation-auto': 'auto',
|
|
207
|
-
}
|
|
208
|
-
return values[parsed.raw] ? { isolation: values[parsed.raw] } : undefined
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export const objectFitRule: UtilityRule = (parsed) => {
|
|
212
|
-
const fits: Record<string, string> = {
|
|
213
|
-
'object-contain': 'contain',
|
|
214
|
-
'object-cover': 'cover',
|
|
215
|
-
'object-fill': 'fill',
|
|
216
|
-
'object-none': 'none',
|
|
217
|
-
'object-scale-down': 'scale-down',
|
|
218
|
-
}
|
|
219
|
-
return fits[parsed.raw] ? { 'object-fit': fits[parsed.raw] } : undefined
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export const objectPositionRule: UtilityRule = (parsed) => {
|
|
223
|
-
const positions: Record<string, string> = {
|
|
224
|
-
'object-bottom': 'bottom',
|
|
225
|
-
'object-center': 'center',
|
|
226
|
-
'object-left': 'left',
|
|
227
|
-
'object-left-bottom': 'left bottom',
|
|
228
|
-
'object-left-top': 'left top',
|
|
229
|
-
'object-right': 'right',
|
|
230
|
-
'object-right-bottom': 'right bottom',
|
|
231
|
-
'object-right-top': 'right top',
|
|
232
|
-
'object-top': 'top',
|
|
233
|
-
}
|
|
234
|
-
return positions[parsed.raw] ? { 'object-position': positions[parsed.raw] } : undefined
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export const overflowRule: UtilityRule = (parsed) => {
|
|
238
|
-
if (parsed.utility === 'overflow') {
|
|
239
|
-
const values = ['auto', 'hidden', 'clip', 'visible', 'scroll']
|
|
240
|
-
if (parsed.value && values.includes(parsed.value)) {
|
|
241
|
-
return { overflow: parsed.value }
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (parsed.utility === 'overflow-x' || parsed.utility === 'overflow-y') {
|
|
245
|
-
const values = ['auto', 'hidden', 'clip', 'visible', 'scroll']
|
|
246
|
-
if (parsed.value && values.includes(parsed.value)) {
|
|
247
|
-
return { [parsed.utility]: parsed.value }
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
export const overscrollRule: UtilityRule = (parsed) => {
|
|
253
|
-
const behaviors: Record<string, string> = {
|
|
254
|
-
'overscroll-auto': 'auto',
|
|
255
|
-
'overscroll-contain': 'contain',
|
|
256
|
-
'overscroll-none': 'none',
|
|
257
|
-
'overscroll-x-auto': 'auto',
|
|
258
|
-
'overscroll-x-contain': 'contain',
|
|
259
|
-
'overscroll-x-none': 'none',
|
|
260
|
-
'overscroll-y-auto': 'auto',
|
|
261
|
-
'overscroll-y-contain': 'contain',
|
|
262
|
-
'overscroll-y-none': 'none',
|
|
263
|
-
}
|
|
264
|
-
const prop = parsed.raw.startsWith('overscroll-x')
|
|
265
|
-
? 'overscroll-behavior-x'
|
|
266
|
-
: parsed.raw.startsWith('overscroll-y')
|
|
267
|
-
? 'overscroll-behavior-y'
|
|
268
|
-
: 'overscroll-behavior'
|
|
269
|
-
return behaviors[parsed.raw] ? { [prop]: behaviors[parsed.raw] } : undefined
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export const positionRule: UtilityRule = (parsed) => {
|
|
273
|
-
const positions = ['static', 'fixed', 'absolute', 'relative', 'sticky']
|
|
274
|
-
if (positions.includes(parsed.utility)) {
|
|
275
|
-
return { position: parsed.utility }
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export const insetRule: UtilityRule = (parsed, config) => {
|
|
280
|
-
const directions: Record<string, string[]> = {
|
|
281
|
-
'inset': ['top', 'right', 'bottom', 'left'],
|
|
282
|
-
'inset-x': ['left', 'right'],
|
|
283
|
-
'inset-y': ['top', 'bottom'],
|
|
284
|
-
'top': ['top'],
|
|
285
|
-
'right': ['right'],
|
|
286
|
-
'bottom': ['bottom'],
|
|
287
|
-
'left': ['left'],
|
|
288
|
-
// Logical inset (for RTL support)
|
|
289
|
-
'start': ['inset-inline-start'],
|
|
290
|
-
'end': ['inset-inline-end'],
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const props = directions[parsed.utility]
|
|
294
|
-
if (!props || !parsed.value)
|
|
295
|
-
return undefined
|
|
296
|
-
|
|
297
|
-
// Helper to resolve inset value (handles fractions, spacing, keywords)
|
|
298
|
-
const resolveInsetValue = (val: string): string => {
|
|
299
|
-
// Handle fractions: 1/2 -> 50%, 1/3 -> 33.333333%, etc.
|
|
300
|
-
if (val.includes('/')) {
|
|
301
|
-
const [num, denom] = val.split('/').map(Number)
|
|
302
|
-
if (!Number.isNaN(num) && !Number.isNaN(denom) && denom !== 0) {
|
|
303
|
-
return `${(num / denom) * 100}%`
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
// Handle special keywords
|
|
307
|
-
if (val === 'full')
|
|
308
|
-
return '100%'
|
|
309
|
-
if (val === 'auto')
|
|
310
|
-
return 'auto'
|
|
311
|
-
// Check spacing config, then fall back to raw value
|
|
312
|
-
return config.theme.spacing[val] || val
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Handle negative values
|
|
316
|
-
let value: string
|
|
317
|
-
if (parsed.value.startsWith('-')) {
|
|
318
|
-
const positiveValue = parsed.value.slice(1)
|
|
319
|
-
const resolved = resolveInsetValue(positiveValue)
|
|
320
|
-
// For percentage values, negate properly
|
|
321
|
-
if (resolved.endsWith('%')) {
|
|
322
|
-
const numericPart = Number.parseFloat(resolved)
|
|
323
|
-
value = `${-numericPart}%`
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
value = resolved.startsWith('-') ? resolved : `-${resolved}`
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
value = resolveInsetValue(parsed.value)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const result: Record<string, string> = {}
|
|
334
|
-
for (const prop of props) {
|
|
335
|
-
result[prop] = value
|
|
336
|
-
}
|
|
337
|
-
return result
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export const visibilityRule: UtilityRule = (parsed) => {
|
|
341
|
-
const values: Record<string, string> = {
|
|
342
|
-
visible: 'visible',
|
|
343
|
-
invisible: 'hidden',
|
|
344
|
-
collapse: 'collapse',
|
|
345
|
-
}
|
|
346
|
-
return values[parsed.utility] ? { visibility: values[parsed.utility] } : undefined
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
export const zIndexRule: UtilityRule = (parsed) => {
|
|
350
|
-
if (parsed.utility === 'z' && parsed.value) {
|
|
351
|
-
const zIndexMap: Record<string, string> = {
|
|
352
|
-
0: '0',
|
|
353
|
-
10: '10',
|
|
354
|
-
20: '20',
|
|
355
|
-
30: '30',
|
|
356
|
-
40: '40',
|
|
357
|
-
50: '50',
|
|
358
|
-
auto: 'auto',
|
|
359
|
-
}
|
|
360
|
-
return { 'z-index': zIndexMap[parsed.value] || parsed.value }
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export const layoutRules: UtilityRule[] = [
|
|
365
|
-
aspectRatioRule,
|
|
366
|
-
columnsRule,
|
|
367
|
-
columnFillRule,
|
|
368
|
-
columnGapRule,
|
|
369
|
-
columnRuleRule,
|
|
370
|
-
columnSpanRule,
|
|
371
|
-
breakRule,
|
|
372
|
-
boxDecorationRule,
|
|
373
|
-
boxSizingRule,
|
|
374
|
-
floatRule,
|
|
375
|
-
clearRule,
|
|
376
|
-
isolationRule,
|
|
377
|
-
objectFitRule,
|
|
378
|
-
objectPositionRule,
|
|
379
|
-
overflowRule,
|
|
380
|
-
overscrollRule,
|
|
381
|
-
positionRule,
|
|
382
|
-
insetRule,
|
|
383
|
-
visibilityRule,
|
|
384
|
-
zIndexRule,
|
|
385
|
-
]
|