Skip to content

Commit 130943e

Browse files
authored
fix(preset-mini): let negate variant negate negative numbers & functions (#3399)
1 parent da3996a commit 130943e

File tree

7 files changed

+41
-12
lines changed

7 files changed

+41
-12
lines changed

packages/preset-mini/src/_utils/mappings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,4 @@ export const globalKeywords = [
114114
'unset',
115115
]
116116

117-
export const cssMathFnRE = /(?:calc|clamp|min|max)\s*\(.*\)/
117+
export const cssMathFnRE = /^(calc|clamp|min|max)\s*\((.+)\)(.*)/

packages/preset-mini/src/_variants/negative.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
import type { Variant } from '@unocss/core'
22
import { getStringComponent } from '@unocss/rule-utils'
3-
import { CONTROL_MINI_NO_NEGATIVE } from '../utils'
3+
import { CONTROL_MINI_NO_NEGATIVE, cssMathFnRE } from '../utils'
44

5-
const numberRE = /[0-9.]+(?:[a-z]+|%)?/
5+
const numberRE = /-?[0-9.]+(?:[a-z]+|%)?/
66

77
const ignoreProps = [
8-
/opacity|color|flex/,
8+
/\b(opacity|color|flex|backdrop-filter|^filter|transform)\b/,
99
]
1010

11-
function negateFunctions(value: string) {
12-
const match = value.match(/^(calc|clamp|max|min)\s*(\(.*)/)
11+
function negateMathFunction(value: string) {
12+
const match = value.match(cssMathFnRE)
1313
if (match) {
14-
const [fnBody, rest] = getStringComponent(match[2], '(', ')', ' ') ?? []
14+
const [fnBody, rest] = getStringComponent(`(${match[2]})${match[3]}`, '(', ')', ' ') ?? []
1515
if (fnBody)
1616
return `calc(${match[1]}${fnBody} * -1)${rest ? ` ${rest}` : ''}`
1717
}
1818
}
1919

20+
const negateFunctionBodyRE = /\b(hue-rotate)\s*(\(.*)/
21+
function negateFunctionBody(value: string) {
22+
const match = value.match(negateFunctionBodyRE)
23+
if (match) {
24+
const [fnBody, rest] = getStringComponent(match[2], '(', ')', ' ') ?? []
25+
if (fnBody) {
26+
const body = numberRE.test(fnBody)
27+
? fnBody.replace(numberRE, i => i.startsWith('-') ? i.slice(1) : `-${i}`)
28+
: `(calc(${fnBody} * -1))`
29+
return `${match[1]}${body}${rest ? ` ${rest}` : ''}`
30+
}
31+
}
32+
}
33+
2034
export const variantNegative: Variant = {
2135
name: 'negative',
2236
match(matcher) {
@@ -35,13 +49,20 @@ export const variantNegative: Variant = {
3549
return
3650
if (ignoreProps.some(i => i.test(v[0])))
3751
return
38-
const negated = negateFunctions(value)
39-
if (negated) {
40-
v[1] = negated
52+
const negatedFn = negateMathFunction(value)
53+
if (negatedFn) {
54+
v[1] = negatedFn
4155
changed = true
56+
return
57+
}
58+
const negatedBody = negateFunctionBody(value)
59+
if (negatedBody) {
60+
v[1] = negatedBody
61+
changed = true
62+
return
4263
}
43-
else if (numberRE.test(value)) {
44-
v[1] = value.replace(numberRE, i => `-${i}`)
64+
if (numberRE.test(value)) {
65+
v[1] = value.replace(numberRE, i => i.startsWith('-') ? i.slice(1) : `-${i}`)
4566
changed = true
4667
}
4768
})

test/__snapshots__/postcss.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ exports[`postcss > @unocss 1`] = `
348348
.grayscale-\\$variable{--un-grayscale:grayscale(var(--variable));filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
349349
.grayscale-90{--un-grayscale:grayscale(0.9);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
350350
.-backdrop-hue-rotate-90{--un-backdrop-hue-rotate:hue-rotate(-90deg);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);}
351+
.-hue-rotate--90{--un-hue-rotate:hue-rotate(90deg);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
352+
.-hue-rotate-\\[var\\(--for-hue\\,0\\.5turn\\)\\]{--un-hue-rotate:hue-rotate(var(--for-hue,-0.5turn));filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
351353
.-hue-rotate-90{--un-hue-rotate:hue-rotate(-90deg);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}
352354
.backdrop-hue-rotate-0{--un-backdrop-hue-rotate:hue-rotate(0);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);}
353355
.backdrop-hue-rotate-360{--un-backdrop-hue-rotate:hue-rotate(360deg);-webkit-backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);backdrop-filter:var(--un-backdrop-blur) var(--un-backdrop-brightness) var(--un-backdrop-contrast) var(--un-backdrop-grayscale) var(--un-backdrop-hue-rotate) var(--un-backdrop-invert) var(--un-backdrop-opacity) var(--un-backdrop-saturate) var(--un-backdrop-sepia);}

test/assets/output/preset-mini-targets.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
.my-revert-layer{margin-top:revert-layer;margin-bottom:revert-layer;}
103103
.-\!mb-safe{margin-bottom:calc(max(env(safe-area-inset-left), env(safe-area-inset-right)) * -1) !important;}
104104
.-mb-px{margin-bottom:-1px;}
105+
.-mt--5cm{margin-top:5cm;}
105106
.-mt-safe{margin-top:calc(max(env(safe-area-inset-left), env(safe-area-inset-right)) * -1);}
106107
.\!-ms-safe{margin-inline-start:calc(max(env(safe-area-inset-left), env(safe-area-inset-right)) * -1) !important;}
107108
.me-8{margin-inline-end:2rem;}

test/assets/output/preset-wind-targets.css

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/assets/preset-mini-targets.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ export const presetMiniTargets: string[] = [
10361036
'!p-5px',
10371037
'-gap-y-5',
10381038
'-mb-px',
1039+
'-mt--5cm',
10391040
'-p-px',
10401041
'-z-1',
10411042

test/assets/preset-wind-targets.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ export const presetWindTargets: string[] = [
385385
'!animate-ping',
386386
'-backdrop-hue-rotate-90',
387387
'-hue-rotate-90',
388+
'-hue-rotate--90',
389+
'-hue-rotate-[var(--for-hue,0.5turn)]',
388390
'hover:animate-bounce',
389391

390392
'-scroll-mb-px',

0 commit comments

Comments
 (0)