Skip to content

Commit a036bd9

Browse files
committed
chore: wip
1 parent 9453e16 commit a036bd9

File tree

8 files changed

+742
-12
lines changed

8 files changed

+742
-12
lines changed

packages/headwind/src/config.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ export const defaultConfig: HeadwindConfig = {
2323
800: '#1f2937',
2424
900: '#111827',
2525
},
26+
red: {
27+
500: '#ef4444',
28+
700: '#b91c1c',
29+
},
30+
blue: {
31+
500: '#3b82f6',
32+
},
33+
green: {
34+
500: '#22c55e',
35+
},
36+
yellow: {
37+
100: '#fef9c3',
38+
},
2639
},
2740
spacing: {
2841
0: '0',

packages/headwind/src/parser.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,13 @@ export function parseClass(className: string): ParsedClass {
6060
'row-end',
6161
'translate-x',
6262
'translate-y',
63+
'translate-z',
6364
'scale-x',
6465
'scale-y',
66+
'scale-z',
67+
'rotate-x',
68+
'rotate-y',
69+
'rotate-z',
6570
'skew-x',
6671
'skew-y',
6772
'scroll-m',
@@ -89,6 +94,7 @@ export function parseClass(className: string): ParsedClass {
8994
'space-x',
9095
'space-y',
9196
'ring-offset',
97+
'underline-offset',
9298
'backdrop-blur',
9399
'backdrop-brightness',
94100
'backdrop-contrast',
@@ -172,6 +178,20 @@ export function parseClass(className: string): ParsedClass {
172178
}
173179
}
174180

181+
// Check for color opacity modifiers: bg-blue-500/50, text-red-500/75
182+
// Must come before fractional values to avoid conflict
183+
const opacityMatch = utility.match(/^([a-z-]+?)-(.+?)\/(\d+)$/)
184+
if (opacityMatch && ['bg', 'text', 'border', 'ring', 'placeholder', 'divide'].includes(opacityMatch[1])) {
185+
return {
186+
raw: className,
187+
variants,
188+
utility: opacityMatch[1],
189+
value: `${opacityMatch[2]}/${opacityMatch[3]}`,
190+
important,
191+
arbitrary: false,
192+
}
193+
}
194+
175195
// Check for fractional values: w-1/2, h-3/4
176196
const fractionMatch = utility.match(/^([a-z-]+?)-(\d+)\/(\d+)$/)
177197
if (fractionMatch) {

packages/headwind/src/rules-advanced.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export const minMaxSizingRule: UtilityRule = (parsed) => {
4343
// Ring utilities
4444
export const ringRule: UtilityRule = (parsed, config) => {
4545
if (parsed.utility === 'ring') {
46+
// Handle ring-inset
47+
if (parsed.value === 'inset') {
48+
return { '--tw-ring-inset': 'inset' }
49+
}
50+
4651
const widths: Record<string, string> = {
4752
0: '0',
4853
1: '1px',
@@ -132,8 +137,44 @@ export const spaceRule: UtilityRule = (parsed, config) => {
132137
}
133138
}
134139

140+
// Border style utilities
141+
export const borderStyleRule: UtilityRule = (parsed) => {
142+
if (parsed.utility === 'border' && parsed.value) {
143+
const styles: Record<string, string> = {
144+
solid: 'solid',
145+
dashed: 'dashed',
146+
dotted: 'dotted',
147+
double: 'double',
148+
hidden: 'hidden',
149+
none: 'none',
150+
}
151+
if (styles[parsed.value]) {
152+
return { 'border-style': styles[parsed.value] }
153+
}
154+
}
155+
}
156+
135157
// Divide utilities (borders between children)
136158
export const divideRule: UtilityRule = (parsed, config) => {
159+
// Handle divide styles: divide-solid, divide-dashed, divide-dotted
160+
if (parsed.utility === 'divide' && parsed.value) {
161+
const styles: Record<string, string> = {
162+
solid: 'solid',
163+
dashed: 'dashed',
164+
dotted: 'dotted',
165+
double: 'double',
166+
none: 'none',
167+
}
168+
if (styles[parsed.value]) {
169+
return {
170+
properties: {
171+
'border-style': styles[parsed.value],
172+
},
173+
childSelector: '> :not([hidden]) ~ :not([hidden])',
174+
}
175+
}
176+
}
177+
137178
if (parsed.utility === 'divide-x') {
138179
const widths: Record<string, string> = {
139180
0: '0',
@@ -332,6 +373,7 @@ export const arbitraryPropertyRule: UtilityRule = (parsed) => {
332373
export const advancedRules: UtilityRule[] = [
333374
minMaxSizingRule,
334375
ringRule,
376+
borderStyleRule,
335377
spaceRule,
336378
divideRule,
337379
gradientStopsRule,

packages/headwind/src/rules-transforms.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,25 @@ export const scaleRule: UtilityRule = (parsed) => {
2525
const scale = parsed.value ? Number(parsed.value) / 100 : 1
2626
return { transform: `scaleY(${scale})` }
2727
}
28+
if (parsed.utility === 'scale-z') {
29+
const scale = parsed.value ? Number(parsed.value) / 100 : 1
30+
return { transform: `scaleZ(${scale})` }
31+
}
2832
}
2933

3034
export const rotateRule: UtilityRule = (parsed) => {
3135
if (parsed.utility === 'rotate' && parsed.value) {
3236
return { transform: `rotate(${parsed.value}deg)` }
3337
}
38+
if (parsed.utility === 'rotate-x' && parsed.value) {
39+
return { transform: `rotateX(${parsed.value}deg)` }
40+
}
41+
if (parsed.utility === 'rotate-y' && parsed.value) {
42+
return { transform: `rotateY(${parsed.value}deg)` }
43+
}
44+
if (parsed.utility === 'rotate-z' && parsed.value) {
45+
return { transform: `rotateZ(${parsed.value}deg)` }
46+
}
3447
}
3548

3649
export const translateRule: UtilityRule = (parsed, config) => {
@@ -58,6 +71,18 @@ export const translateRule: UtilityRule = (parsed, config) => {
5871
}
5972
return { transform: `translateY(${value})` }
6073
}
74+
if (parsed.utility === 'translate-z' && parsed.value) {
75+
let value: string
76+
if (parsed.value.startsWith('-')) {
77+
const positiveValue = parsed.value.slice(1)
78+
const spacing = config.theme.spacing[positiveValue]
79+
value = spacing ? `-${spacing}` : parsed.value
80+
}
81+
else {
82+
value = config.theme.spacing[parsed.value] || parsed.value
83+
}
84+
return { transform: `translateZ(${value})` }
85+
}
6186
}
6287

6388
export const skewRule: UtilityRule = (parsed) => {

packages/headwind/src/rules-typography.ts

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const listStyleTypeRule: UtilityRule = (parsed) => {
105105
}
106106
}
107107

108-
export const textDecorationRule: UtilityRule = (parsed) => {
108+
export const textDecorationRule: UtilityRule = (parsed, config) => {
109109
const decorations: Record<string, string> = {
110110
underline: 'underline',
111111
overline: 'overline',
@@ -124,12 +124,63 @@ export const textDecorationRule: UtilityRule = (parsed) => {
124124
dashed: 'dashed',
125125
wavy: 'wavy',
126126
}
127-
return { 'text-decoration-style': styles[parsed.value] || parsed.value }
127+
128+
// Check if it's a style
129+
if (styles[parsed.value]) {
130+
return { 'text-decoration-style': styles[parsed.value] }
131+
}
132+
133+
// Check if it's a thickness
134+
const thicknesses: Record<string, string> = {
135+
auto: 'auto',
136+
from: 'from-font',
137+
0: '0px',
138+
1: '1px',
139+
2: '2px',
140+
4: '4px',
141+
8: '8px',
142+
}
143+
if (thicknesses[parsed.value]) {
144+
return { 'text-decoration-thickness': thicknesses[parsed.value] }
145+
}
146+
147+
// Otherwise treat it as a color: decoration-blue-500
148+
const parts = parsed.value.split('-')
149+
if (parts.length === 2) {
150+
const [colorName, shade] = parts
151+
const colorValue = config.theme.colors[colorName]
152+
if (typeof colorValue === 'object' && colorValue[shade]) {
153+
return { 'text-decoration-color': colorValue[shade] }
154+
}
155+
}
156+
157+
// Direct color
158+
const directColor = config.theme.colors[parsed.value]
159+
if (typeof directColor === 'string') {
160+
return { 'text-decoration-color': directColor }
161+
}
162+
163+
// Fallback
164+
return { 'text-decoration-color': parsed.value }
128165
}
129166

130167
return undefined
131168
}
132169

170+
export const underlineOffsetRule: UtilityRule = (parsed) => {
171+
if (parsed.utility === 'underline-offset' && parsed.value) {
172+
const offsets: Record<string, string> = {
173+
auto: 'auto',
174+
0: '0px',
175+
1: '1px',
176+
2: '2px',
177+
4: '4px',
178+
8: '8px',
179+
}
180+
return { 'text-underline-offset': offsets[parsed.value] || parsed.value }
181+
}
182+
}
183+
133184
export const textTransformRule: UtilityRule = (parsed) => {
134185
const transforms: Record<string, string> = {
135186
uppercase: 'uppercase',
@@ -232,18 +283,47 @@ export const contentRule: UtilityRule = (parsed) => {
232283
}
233284
}
234285

286+
export const lineHeightRule: UtilityRule = (parsed, config) => {
287+
if (parsed.utility === 'leading') {
288+
if (!parsed.value) {
289+
return undefined
290+
}
291+
292+
const lineHeights: Record<string, string> = {
293+
none: '1',
294+
tight: '1.25',
295+
snug: '1.375',
296+
normal: '1.5',
297+
relaxed: '1.625',
298+
loose: '2',
299+
3: '.75rem',
300+
4: '1rem',
301+
5: '1.25rem',
302+
6: '1.5rem',
303+
7: '1.75rem',
304+
8: '2rem',
305+
9: '2.25rem',
306+
10: '2.5rem',
307+
}
308+
309+
return { 'line-height': lineHeights[parsed.value] || parsed.value }
310+
}
311+
}
312+
235313
export const typographyRules: UtilityRule[] = [
236314
fontFamilyRule,
237315
fontSmoothingRule,
238316
fontStyleRule,
239317
fontStretchRule,
240318
fontVariantNumericRule,
241319
letterSpacingRule,
320+
lineHeightRule,
242321
lineClampRule,
243322
listStyleImageRule,
244323
listStylePositionRule,
245324
listStyleTypeRule,
246325
textDecorationRule,
326+
underlineOffsetRule,
247327
textTransformRule,
248328
textOverflowRule,
249329
textWrapRule,

0 commit comments

Comments
 (0)