Skip to content

Commit 462be98

Browse files
committed
chore: wip
1 parent 751b30f commit 462be98

File tree

3 files changed

+84
-22
lines changed

3 files changed

+84
-22
lines changed

packages/headwind/src/generator.ts

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,73 @@ import type { CSSRule, HeadwindConfig, ParsedClass } from './types'
22
import { builtInRules } from './rules'
33
import { parseClass } from './parser'
44

5+
/**
6+
* Deep merge objects
7+
*/
8+
function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {
9+
const result = { ...target }
10+
for (const key in source) {
11+
const sourceValue = source[key]
12+
const targetValue = result[key]
13+
if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue) && targetValue && typeof targetValue === 'object' && !Array.isArray(targetValue)) {
14+
result[key] = deepMerge(targetValue, sourceValue)
15+
}
16+
else if (sourceValue !== undefined) {
17+
result[key] = sourceValue as any
18+
}
19+
}
20+
return result
21+
}
22+
523
/**
624
* Generates CSS rules from parsed utility classes
725
*/
826
export class CSSGenerator {
927
private rules: Map<string, CSSRule[]> = new Map()
1028

11-
constructor(private config: HeadwindConfig) {}
29+
constructor(private config: HeadwindConfig) {
30+
// Merge preset themes into the main config theme
31+
if (config.presets && config.presets.length > 0) {
32+
for (const preset of config.presets) {
33+
if (preset.theme) {
34+
this.config.theme = deepMerge(this.config.theme, preset.theme)
35+
}
36+
}
37+
}
38+
}
1239

1340
/**
1441
* Generate CSS for a utility class
1542
*/
1643
generate(className: string): void {
1744
const parsed = parseClass(className)
1845

19-
// Check if class is blocklisted
20-
if (this.config.blocklist.includes(className)) {
21-
return
46+
// Check if class is blocklisted (supports wildcards)
47+
for (const pattern of this.config.blocklist) {
48+
if (pattern.includes('*')) {
49+
// Convert wildcard pattern to regex
50+
const regexPattern = pattern.replace(/\*/g, '.*')
51+
const regex = new RegExp(`^${regexPattern}$`)
52+
if (regex.test(className)) {
53+
return
54+
}
55+
}
56+
else if (pattern === className) {
57+
// Exact match
58+
return
59+
}
60+
}
61+
62+
// Try custom rules from config first (allows overriding built-in rules)
63+
for (const [pattern, handler] of this.config.rules) {
64+
const match = className.match(pattern)
65+
if (match) {
66+
const properties = handler(match)
67+
if (properties) {
68+
this.addRule(parsed, properties)
69+
return
70+
}
71+
}
2272
}
2373

2474
// Try built-in rules
@@ -36,18 +86,6 @@ export class CSSGenerator {
3686
}
3787
}
3888

39-
// Try custom rules from config
40-
for (const [pattern, handler] of this.config.rules) {
41-
const match = className.match(pattern)
42-
if (match) {
43-
const properties = handler(match)
44-
if (properties) {
45-
this.addRule(parsed, properties)
46-
return
47-
}
48-
}
49-
}
50-
5189
// Check shortcuts
5290
const shortcut = this.config.shortcuts[className]
5391
if (shortcut) {

packages/headwind/src/rules-interactivity.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import type { UtilityRule } from './rules'
44

55
// Filter utilities
66
export const filterRule: UtilityRule = (parsed) => {
7+
// Handle filter-none
8+
if (parsed.raw === 'filter-none') {
9+
return { filter: 'none' }
10+
}
711
if (parsed.utility === 'blur' && parsed.value) {
812
const blurMap: Record<string, string> = {
913
none: '0',
@@ -53,6 +57,10 @@ export const filterRule: UtilityRule = (parsed) => {
5357
}
5458

5559
export const backdropFilterRule: UtilityRule = (parsed) => {
60+
// Handle backdrop-filter-none
61+
if (parsed.raw === 'backdrop-filter-none') {
62+
return { 'backdrop-filter': 'none' }
63+
}
5664
if (parsed.utility === 'backdrop-blur' && parsed.value) {
5765
return { 'backdrop-filter': `blur(${parsed.value}px)` }
5866
}

packages/headwind/src/rules-transforms.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,30 @@ export const transitionBehaviorRule: UtilityRule = (parsed) => {
258258
}
259259

260260
export const animationRule: UtilityRule = (parsed) => {
261+
if (parsed.utility !== 'animate') {
262+
return undefined
263+
}
264+
261265
const animations: Record<string, string> = {
262-
'animate-none': 'none',
263-
'animate-spin': 'spin 1s linear infinite',
264-
'animate-ping': 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
265-
'animate-pulse': 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
266-
'animate-bounce': 'bounce 1s infinite',
266+
'none': 'none',
267+
'spin': 'spin 1s linear infinite',
268+
'ping': 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
269+
'pulse': 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
270+
'bounce': 'bounce 1s infinite',
271+
}
272+
273+
// Support arbitrary animation values
274+
if (parsed.arbitrary && parsed.value) {
275+
// Replace underscores with spaces for arbitrary animation values
276+
return { animation: parsed.value.replace(/_/g, ' ') }
267277
}
268-
return animations[parsed.raw] ? { animation: animations[parsed.raw] } : undefined
278+
279+
// Support predefined animations
280+
if (parsed.value && animations[parsed.value]) {
281+
return { animation: animations[parsed.value] }
282+
}
283+
284+
return undefined
269285
}
270286

271287
export const transformsRules: UtilityRule[] = [

0 commit comments

Comments
 (0)