Skip to content

Commit e15e163

Browse files
chore: wip
1 parent b5c003b commit e15e163

File tree

4 files changed

+117
-2
lines changed

4 files changed

+117
-2
lines changed

packages/headwind/src/parser.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,14 @@ function parseClassImpl(className: string): ParsedClass {
11451145
'border-spacing',
11461146
'border-spacing-x',
11471147
'border-spacing-y',
1148+
'rounded-s',
1149+
'rounded-e',
1150+
'rounded-ss',
1151+
'rounded-se',
1152+
'rounded-es',
1153+
'rounded-ee',
1154+
'border-opacity',
1155+
'ring-opacity',
11481156
]
11491157

11501158
// Special case for divide-x and divide-y (without values, they should be treated as compound)

packages/headwind/src/rules-advanced.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,28 @@ export const ringRule: UtilityRule = (parsed, config) => {
116116
return { '--hw-ring-offset-color': directColor } as Record<string, string>
117117
}
118118
}
119+
120+
// Ring opacity
121+
if (parsed.utility === 'ring-opacity' && parsed.value) {
122+
const opacityMap: Record<string, string> = {
123+
0: '0', 5: '0.05', 10: '0.1', 20: '0.2', 25: '0.25',
124+
30: '0.3', 40: '0.4', 50: '0.5', 60: '0.6', 70: '0.7',
125+
75: '0.75', 80: '0.8', 90: '0.9', 95: '0.95', 100: '1',
126+
}
127+
return { '--hw-ring-opacity': opacityMap[parsed.value] || parsed.value } as Record<string, string>
128+
}
129+
}
130+
131+
// Border opacity utility
132+
export const borderOpacityRule: UtilityRule = (parsed) => {
133+
if (parsed.utility === 'border-opacity' && parsed.value) {
134+
const opacityMap: Record<string, string> = {
135+
0: '0', 5: '0.05', 10: '0.1', 20: '0.2', 25: '0.25',
136+
30: '0.3', 40: '0.4', 50: '0.5', 60: '0.6', 70: '0.7',
137+
75: '0.75', 80: '0.8', 90: '0.9', 95: '0.95', 100: '1',
138+
}
139+
return { '--hw-border-opacity': opacityMap[parsed.value] || parsed.value } as Record<string, string>
140+
}
119141
}
120142

121143
// Space utilities (child spacing)
@@ -441,6 +463,7 @@ export const arbitraryPropertyRule: UtilityRule = (parsed) => {
441463
export const advancedRules: UtilityRule[] = [
442464
minMaxSizingRule,
443465
ringRule,
466+
borderOpacityRule,
444467
borderStyleRule,
445468
spaceRule,
446469
divideRule,

packages/headwind/src/rules-transforms.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,19 @@ export const transitionPropertyRule: UtilityRule = (parsed) => {
235235

236236
export const transitionDurationRule: UtilityRule = (parsed) => {
237237
if (parsed.utility === 'duration' && parsed.value) {
238-
return { 'transition-duration': `${parsed.value}ms` }
238+
// Named duration presets (like Tailwind)
239+
const durations: Record<string, string> = {
240+
'0': '0s',
241+
'75': '75ms',
242+
'100': '100ms',
243+
'150': '150ms',
244+
'200': '200ms',
245+
'300': '300ms',
246+
'500': '500ms',
247+
'700': '700ms',
248+
'1000': '1000ms',
249+
}
250+
return { 'transition-duration': durations[parsed.value] || `${parsed.value}ms` }
239251
}
240252
}
241253

@@ -251,7 +263,19 @@ export const transitionTimingRule: UtilityRule = (parsed) => {
251263

252264
export const transitionDelayRule: UtilityRule = (parsed) => {
253265
if (parsed.utility === 'delay' && parsed.value) {
254-
return { 'transition-delay': `${parsed.value}ms` }
266+
// Named delay presets (like Tailwind)
267+
const delays: Record<string, string> = {
268+
'0': '0s',
269+
'75': '75ms',
270+
'100': '100ms',
271+
'150': '150ms',
272+
'200': '200ms',
273+
'300': '300ms',
274+
'500': '500ms',
275+
'700': '700ms',
276+
'1000': '1000ms',
277+
}
278+
return { 'transition-delay': delays[parsed.value] || `${parsed.value}ms` }
255279
}
256280
}
257281

packages/headwind/src/rules.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,28 @@ export const sizingRule: UtilityRule = (parsed, config) => {
272272
return { height: value } as Record<string, string>
273273
}
274274

275+
// Size utility (width + height shorthand)
276+
if (parsed.utility === 'size' && parsed.value) {
277+
const sizeMap: Record<string, string> = {
278+
full: '100%',
279+
auto: 'auto',
280+
min: 'min-content',
281+
max: 'max-content',
282+
fit: 'fit-content',
283+
}
284+
// Handle fractions: 1/2 -> 50%
285+
if (parsed.value.includes('/')) {
286+
const [num, denom] = parsed.value.split('/').map(Number)
287+
if (Number.isNaN(num) || Number.isNaN(denom) || denom === 0) {
288+
return undefined
289+
}
290+
const percent = `${(num / denom) * 100}%`
291+
return { width: percent, height: percent } as Record<string, string>
292+
}
293+
const value = config.theme.spacing[parsed.value] || sizeMap[parsed.value] || parsed.value
294+
return { width: value, height: value } as Record<string, string>
295+
}
296+
275297
return undefined
276298
}
277299

@@ -631,6 +653,44 @@ export const borderRadiusRule: UtilityRule = (parsed, config) => {
631653
const value = parsed.value ? config.theme.borderRadius[parsed.value] : config.theme.borderRadius.DEFAULT
632654
return value ? { 'border-radius': value } : undefined
633655
}
656+
657+
// Logical border-radius utilities (for RTL/LTR support)
658+
// rounded-s-* (start) - applies to start corners
659+
if (parsed.utility === 'rounded-s' && parsed.value) {
660+
const value = config.theme.borderRadius[parsed.value] || parsed.value
661+
return {
662+
'border-start-start-radius': value,
663+
'border-end-start-radius': value,
664+
} as Record<string, string>
665+
}
666+
// rounded-e-* (end) - applies to end corners
667+
if (parsed.utility === 'rounded-e' && parsed.value) {
668+
const value = config.theme.borderRadius[parsed.value] || parsed.value
669+
return {
670+
'border-start-end-radius': value,
671+
'border-end-end-radius': value,
672+
} as Record<string, string>
673+
}
674+
// rounded-ss-* (start-start corner)
675+
if (parsed.utility === 'rounded-ss' && parsed.value) {
676+
const value = config.theme.borderRadius[parsed.value] || parsed.value
677+
return { 'border-start-start-radius': value } as Record<string, string>
678+
}
679+
// rounded-se-* (start-end corner)
680+
if (parsed.utility === 'rounded-se' && parsed.value) {
681+
const value = config.theme.borderRadius[parsed.value] || parsed.value
682+
return { 'border-start-end-radius': value } as Record<string, string>
683+
}
684+
// rounded-es-* (end-start corner)
685+
if (parsed.utility === 'rounded-es' && parsed.value) {
686+
const value = config.theme.borderRadius[parsed.value] || parsed.value
687+
return { 'border-end-start-radius': value } as Record<string, string>
688+
}
689+
// rounded-ee-* (end-end corner)
690+
if (parsed.utility === 'rounded-ee' && parsed.value) {
691+
const value = config.theme.borderRadius[parsed.value] || parsed.value
692+
return { 'border-end-end-radius': value } as Record<string, string>
693+
}
634694
}
635695

636696
// Export all rules (order matters - more specific rules first)

0 commit comments

Comments
 (0)