Skip to content

Commit 611288c

Browse files
committed
fix(preset-wind4): support nested spacing theme functions
1 parent 5a138e4 commit 611288c

4 files changed

Lines changed: 53 additions & 10 deletions

File tree

packages-presets/preset-wind4/src/rules/position.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,19 @@ export const flexGridJustifiesAlignments = [...justifies, ...alignments, ...plac
142142
[`grid-${k}`, v],
143143
])
144144

145-
function handleInsetValue(v: string): string | number | undefined {
145+
function handleInsetValue(v: string, theme: Theme): string | number | undefined {
146146
const _v = numberResolver(v)
147147
if (_v != null) {
148148
themeTracking(`spacing`)
149149
return `calc(var(--spacing) * ${_v})`
150150
}
151151
else {
152-
return h.bracket.cssvar.global.auto.fraction.rem(v)
152+
return h.bracket.cssvar.global.auto.fraction.rem(v, theme)
153153
}
154154
}
155155

156-
function handleInsetValues([, d, v]: string[]): CSSEntries | undefined {
157-
const r = handleInsetValue(v)
156+
function handleInsetValues([, d, v]: string[], { theme }: { theme: Theme }): CSSEntries | undefined {
157+
const r = handleInsetValue(v, theme)
158158
if (r != null && d in insetMap) {
159159
return insetMap[d].map(i => [i.slice(1), r])
160160
}
@@ -163,7 +163,7 @@ function handleInsetValues([, d, v]: string[]): CSSEntries | undefined {
163163
export const insets: Rule<Theme>[] = [
164164
[
165165
/^(?:position-|pos-)?inset-(.+)$/,
166-
([, v]) => ({ inset: handleInsetValue(v) }),
166+
([, v], { theme }) => ({ inset: handleInsetValue(v, theme) }),
167167
{
168168
autocomplete: [
169169
'(position|pos)-inset-<directions>-$spacing',
@@ -178,7 +178,7 @@ export const insets: Rule<Theme>[] = [
178178
[/^(?:position-|pos-)?inset-([rltbse])-(.+)$/, handleInsetValues],
179179
[/^(?:position-|pos-)?inset-(block|inline)-(.+)$/, handleInsetValues],
180180
[/^(?:position-|pos-)?inset-([bi][se])-(.+)$/, handleInsetValues],
181-
[/^(?:position-|pos-)?(top|left|right|bottom)-(.+)$/, ([, d, v]) => ({ [d]: handleInsetValue(v) })],
181+
[/^(?:position-|pos-)?(top|left|right|bottom)-(.+)$/, ([, d, v], { theme }) => ({ [d]: handleInsetValue(v, theme) })],
182182
]
183183

184184
export const floats: Rule<Theme>[] = [

packages-presets/preset-wind4/src/rules/size.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function getSizeValue(theme: Theme, hw: string, prop: string) {
4646
v = `calc(var(--spacing) * ${h.number(prop)})`
4747
}
4848

49-
return v ?? h.bracket.cssvar.global.auto.none.fraction.rem(prop)
49+
return v ?? h.bracket.cssvar.global.auto.none.fraction.rem(prop, theme)
5050
}
5151

5252
export const sizes: Rule<Theme>[] = [
@@ -87,7 +87,7 @@ function handleBreakpoint(context: Readonly<RuleContext<Theme>>, point: string,
8787
return bp.find(i => i.point === point)?.size
8888
}
8989

90-
function getAspectRatio(prop: string) {
90+
function getAspectRatio(prop: string, theme: Theme) {
9191
if (/^\d+\/\d+$/.test(prop))
9292
return prop
9393

@@ -96,9 +96,9 @@ function getAspectRatio(prop: string) {
9696
case 'video': return '16/9'
9797
}
9898

99-
return h.bracket.cssvar.global.auto.number(prop)
99+
return h.bracket.cssvar.global.auto.number(prop, theme)
100100
}
101101

102102
export const aspectRatio: Rule<Theme>[] = [
103-
[/^(?:size-)?aspect-(?:ratio-)?(.+)$/, ([, d]: string[]) => ({ 'aspect-ratio': getAspectRatio(d) }), { autocomplete: ['aspect-(square|video|ratio)', 'aspect-ratio-(square|video)'] }],
103+
[/^(?:size-)?aspect-(?:ratio-)?(.+)$/, ([, d]: string[], { theme }) => ({ 'aspect-ratio': getAspectRatio(d, theme) }), { autocomplete: ['aspect-(square|video|ratio)', 'aspect-ratio-(square|video)'] }],
104104
]

packages-presets/preset-wind4/src/utils/handlers/handlers.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ function processThemeVariable(name: string, key: keyof Theme, paths: string[], t
169169
return { val, varKey }
170170
}
171171

172+
function replaceThemeFunctions(str: string, theme: Theme) {
173+
return str.replace(/--([\w.-]+)\(([^)]+)\)/g, (match, name, factor) => {
174+
const [key, ...paths] = name.split('.') as [keyof Theme, ...string[]]
175+
const { val, varKey } = processThemeVariable(name, key, paths, theme)
176+
177+
if (val == null)
178+
return match
179+
180+
return `calc(var(--${escapeSelector(varKey.replaceAll('.', '-'))}) * ${factor})`
181+
})
182+
}
183+
172184
function bracketWithType(str: string, requiredType?: string, theme?: Theme) {
173185
if (str && str.startsWith('[') && str.endsWith(']')) {
174186
let base: string | undefined
@@ -196,6 +208,9 @@ function bracketWithType(str: string, requiredType?: string, theme?: Theme) {
196208
if (base === '=""')
197209
return
198210

211+
if (theme)
212+
base = replaceThemeFunctions(base, theme)
213+
199214
if (base.startsWith('--')) {
200215
const calcMatch = base.match(/^--([\w.-]+)\(([^)]+)\)$/)
201216
if (calcMatch != null && theme) {

test/preset-wind4.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,34 @@ describe('preset-wind4', () => {
243243
`)
244244
})
245245

246+
it('should handle --spacing() inside calc()', async () => {
247+
const uno = await createGenerator({
248+
envMode: 'dev',
249+
presets: [
250+
presetWind4({
251+
preflights: { reset: false },
252+
}),
253+
],
254+
})
255+
256+
const { css } = await uno.generate([
257+
'w-[calc(var(--sidebar-width-icon)+--spacing(8))]',
258+
'w-[calc(var(--sidebar-width-icon)+--spacing(8)+2px)]',
259+
'start-[calc(--spacing(4)-1px)]',
260+
])
261+
262+
expect(css).toMatchInlineSnapshot(`
263+
"/* layer: theme */
264+
:root, :host {
265+
--spacing: 0.25rem;
266+
}
267+
/* layer: default */
268+
.w-\\[calc\\(var\\(--sidebar-width-icon\\)\\+--spacing\\(8\\)\\)\\]{width:calc(var(--sidebar-width-icon) + calc(var(--spacing) * 8));}
269+
.w-\\[calc\\(var\\(--sidebar-width-icon\\)\\+--spacing\\(8\\)\\+2px\\)\\]{width:calc(var(--sidebar-width-icon) + calc(var(--spacing) * 8) + 2px);}
270+
.start-\\[calc\\(--spacing\\(4\\)-1px\\)\\]{inset-inline-start:calc(calc(var(--spacing) * 4) - 1px);}"
271+
`)
272+
})
273+
246274
it('smarter theme parser', async () => {
247275
const uno = await createGenerator({
248276
envMode: 'dev',

0 commit comments

Comments
 (0)