Skip to content

Commit 46b97c2

Browse files
chore: wip
1 parent e15e163 commit 46b97c2

6 files changed

Lines changed: 322 additions & 0 deletions

File tree

packages/headwind/src/parser.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,16 @@ function parseClassImpl(className: string): ParsedClass {
11531153
'rounded-ee',
11541154
'border-opacity',
11551155
'ring-opacity',
1156+
'stroke-dasharray',
1157+
'stroke-dashoffset',
1158+
'animate-iteration',
1159+
'animate-duration',
1160+
'animate-delay',
1161+
'text-emphasis',
1162+
'text-emphasis-color',
1163+
'word-spacing',
1164+
'column-gap',
1165+
'column-rule',
11561166
]
11571167

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

packages/headwind/src/rules-grid.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const gridTemplateColumnsRule: UtilityRule = (parsed) => {
1818
11: 'repeat(11, minmax(0, 1fr))',
1919
12: 'repeat(12, minmax(0, 1fr))',
2020
none: 'none',
21+
subgrid: 'subgrid',
2122
}
2223
return parsed.value ? { 'grid-template-columns': cols[parsed.value] || parsed.value } : undefined
2324
}
@@ -84,6 +85,7 @@ export const gridTemplateRowsRule: UtilityRule = (parsed) => {
8485
5: 'repeat(5, minmax(0, 1fr))',
8586
6: 'repeat(6, minmax(0, 1fr))',
8687
none: 'none',
88+
subgrid: 'subgrid',
8789
}
8890
return parsed.value ? { 'grid-template-rows': rows[parsed.value] || parsed.value } : undefined
8991
}

packages/headwind/src/rules-interactivity.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,40 @@ export const strokeWidthRule: UtilityRule = (parsed) => {
419419
}
420420
}
421421

422+
// SVG stroke-dasharray
423+
export const strokeDasharrayRule: UtilityRule = (parsed) => {
424+
if (parsed.utility === 'stroke-dasharray' && parsed.value) {
425+
return { 'stroke-dasharray': parsed.value === 'none' ? 'none' : parsed.value }
426+
}
427+
}
428+
429+
// SVG stroke-dashoffset
430+
export const strokeDashoffsetRule: UtilityRule = (parsed) => {
431+
if (parsed.utility === 'stroke-dashoffset' && parsed.value) {
432+
return { 'stroke-dashoffset': parsed.value }
433+
}
434+
}
435+
436+
// SVG stroke-linecap
437+
export const strokeLinecapRule: UtilityRule = (parsed) => {
438+
const values: Record<string, string> = {
439+
'stroke-linecap-butt': 'butt',
440+
'stroke-linecap-round': 'round',
441+
'stroke-linecap-square': 'square',
442+
}
443+
return values[parsed.raw] ? { 'stroke-linecap': values[parsed.raw] } : undefined
444+
}
445+
446+
// SVG stroke-linejoin
447+
export const strokeLinejoinRule: UtilityRule = (parsed) => {
448+
const values: Record<string, string> = {
449+
'stroke-linejoin-miter': 'miter',
450+
'stroke-linejoin-round': 'round',
451+
'stroke-linejoin-bevel': 'bevel',
452+
}
453+
return values[parsed.raw] ? { 'stroke-linejoin': values[parsed.raw] } : undefined
454+
}
455+
422456
// Accessibility
423457
export const screenReaderRule: UtilityRule = (parsed) => {
424458
if (parsed.raw === 'sr-only') {
@@ -482,6 +516,10 @@ export const interactivityRules: UtilityRule[] = [
482516
fillRule,
483517
strokeRule,
484518
strokeWidthRule,
519+
strokeDasharrayRule,
520+
strokeDashoffsetRule,
521+
strokeLinecapRule,
522+
strokeLinejoinRule,
485523
screenReaderRule,
486524
forcedColorAdjustRule,
487525
]

packages/headwind/src/rules-layout.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,78 @@ export const columnsRule: UtilityRule = (parsed, config) => {
6969
}
7070
}
7171

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] }
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] }
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 }
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] }
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+
72144
export const breakRule: UtilityRule = (parsed) => {
73145
const breaks: Record<string, Record<string, string>> = {
74146
'break-before-auto': { 'break-before': 'auto' },
@@ -289,6 +361,10 @@ export const zIndexRule: UtilityRule = (parsed) => {
289361
export const layoutRules: UtilityRule[] = [
290362
aspectRatioRule,
291363
columnsRule,
364+
columnFillRule,
365+
columnGapRule,
366+
columnRuleRule,
367+
columnSpanRule,
292368
breakRule,
293369
boxDecorationRule,
294370
boxSizingRule,

packages/headwind/src/rules-transforms.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,77 @@ export const animationRule: UtilityRule = (parsed) => {
314314
return undefined
315315
}
316316

317+
// Animation play state
318+
export const animationPlayStateRule: UtilityRule = (parsed) => {
319+
const values: Record<string, string> = {
320+
'animate-running': 'running',
321+
'animate-paused': 'paused',
322+
}
323+
return values[parsed.raw] ? { 'animation-play-state': values[parsed.raw] } : undefined
324+
}
325+
326+
// Animation direction
327+
export const animationDirectionRule: UtilityRule = (parsed) => {
328+
const values: Record<string, string> = {
329+
'animate-normal': 'normal',
330+
'animate-reverse': 'reverse',
331+
'animate-alternate': 'alternate',
332+
'animate-alternate-reverse': 'alternate-reverse',
333+
}
334+
return values[parsed.raw] ? { 'animation-direction': values[parsed.raw] } : undefined
335+
}
336+
337+
// Animation fill mode
338+
export const animationFillModeRule: UtilityRule = (parsed) => {
339+
const values: Record<string, string> = {
340+
'animate-fill-none': 'none',
341+
'animate-fill-forwards': 'forwards',
342+
'animate-fill-backwards': 'backwards',
343+
'animate-fill-both': 'both',
344+
}
345+
return values[parsed.raw] ? { 'animation-fill-mode': values[parsed.raw] } : undefined
346+
}
347+
348+
// Animation iteration count
349+
export const animationIterationRule: UtilityRule = (parsed) => {
350+
if (parsed.utility === 'animate-iteration' && parsed.value) {
351+
return { 'animation-iteration-count': parsed.value === 'infinite' ? 'infinite' : parsed.value }
352+
}
353+
}
354+
355+
// Animation duration
356+
export const animationDurationRule: UtilityRule = (parsed) => {
357+
if (parsed.utility === 'animate-duration' && parsed.value) {
358+
const durations: Record<string, string> = {
359+
'75': '75ms', '100': '100ms', '150': '150ms', '200': '200ms',
360+
'300': '300ms', '500': '500ms', '700': '700ms', '1000': '1000ms',
361+
}
362+
return { 'animation-duration': durations[parsed.value] || `${parsed.value}ms` }
363+
}
364+
}
365+
366+
// Animation delay
367+
export const animationDelayRule: UtilityRule = (parsed) => {
368+
if (parsed.utility === 'animate-delay' && parsed.value) {
369+
const delays: Record<string, string> = {
370+
'75': '75ms', '100': '100ms', '150': '150ms', '200': '200ms',
371+
'300': '300ms', '500': '500ms', '700': '700ms', '1000': '1000ms',
372+
}
373+
return { 'animation-delay': delays[parsed.value] || `${parsed.value}ms` }
374+
}
375+
}
376+
377+
// Animation timing function
378+
export const animationTimingRule: UtilityRule = (parsed) => {
379+
const values: Record<string, string> = {
380+
'animate-ease-linear': 'linear',
381+
'animate-ease-in': 'cubic-bezier(0.4, 0, 1, 1)',
382+
'animate-ease-out': 'cubic-bezier(0, 0, 0.2, 1)',
383+
'animate-ease-in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
384+
}
385+
return values[parsed.raw] ? { 'animation-timing-function': values[parsed.raw] } : undefined
386+
}
387+
317388
export const transformsRules: UtilityRule[] = [
318389
transformRule,
319390
scaleRule,
@@ -331,4 +402,11 @@ export const transformsRules: UtilityRule[] = [
331402
transitionTimingRule,
332403
transitionDelayRule,
333404
animationRule,
405+
animationPlayStateRule,
406+
animationDirectionRule,
407+
animationFillModeRule,
408+
animationIterationRule,
409+
animationDurationRule,
410+
animationDelayRule,
411+
animationTimingRule,
334412
]

0 commit comments

Comments
 (0)