Skip to content

Commit b56b4c0

Browse files
authored
[JIT] Support animation lists (#5252)
* Support animation lists * Update tests
1 parent ca1a167 commit b56b4c0

6 files changed

+247
-79
lines changed

src/plugins/animation.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@ export default function () {
1919
matchUtilities(
2020
{
2121
animate: (value, { includeRules }) => {
22-
let { name: animationName } = parseAnimationValue(value)
22+
let animations = parseAnimationValue(value)
2323

24-
if (keyframes[animationName] !== undefined) {
25-
includeRules(keyframes[animationName], { respectImportant: false })
26-
}
27-
28-
if (animationName === undefined || keyframes[animationName] === undefined) {
29-
return { animation: value }
24+
for (let { name } of animations) {
25+
if (keyframes[name] !== undefined) {
26+
includeRules(keyframes[name], { respectImportant: false })
27+
}
3028
}
3129

3230
return {
33-
animation: value.replace(animationName, prefixName(animationName)),
31+
animation: animations
32+
.map(({ name, value }) => {
33+
if (name === undefined || keyframes[name] === undefined) {
34+
return value
35+
}
36+
return value.replace(name, prefixName(name))
37+
})
38+
.join(', '),
3439
}
3540
},
3641
},

src/util/parseAnimationValue.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ const DIGIT = /^(\d+)$/
2020

2121
export default function parseAnimationValue(input) {
2222
let animations = input.split(COMMA)
23-
let result = animations.map((animation) => {
24-
let result = {}
25-
let parts = animation.trim().split(SPACE)
23+
return animations.map((animation) => {
24+
let value = animation.trim()
25+
let result = { value }
26+
let parts = value.split(SPACE)
2627
let seen = new Set()
2728

2829
for (let part of parts) {
@@ -58,6 +59,4 @@ export default function parseAnimationValue(input) {
5859

5960
return result
6061
})
61-
62-
return animations.length > 1 ? result : result[0]
6362
}

tests/jit/animations.test.css

-32
This file was deleted.

tests/jit/animations.test.html

-3
This file was deleted.

tests/jit/animations.test.js

+186-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import postcss from 'postcss'
2-
import fs from 'fs'
32
import path from 'path'
43
import tailwind from '../../src/jit/index.js'
54

@@ -9,22 +8,199 @@ function run(input, config = {}) {
98
})
109
}
1110

12-
test('animations', () => {
11+
test('basic', () => {
1312
let config = {
14-
darkMode: 'class',
1513
mode: 'jit',
16-
purge: [path.resolve(__dirname, './animations.test.html')],
17-
corePlugins: {},
18-
theme: {},
19-
plugins: [],
14+
purge: [
15+
{
16+
raw: `
17+
<div class="animate-spin"></div>
18+
<div class="hover:animate-ping"></div>
19+
<div class="group-hover:animate-bounce"></div>
20+
`,
21+
},
22+
],
2023
}
2124

2225
let css = `@tailwind utilities`
2326

2427
return run(css, config).then((result) => {
25-
let expectedPath = path.resolve(__dirname, './animations.test.css')
26-
let expected = fs.readFileSync(expectedPath, 'utf8')
28+
expect(result.css).toMatchFormattedCss(`
29+
@keyframes spin {
30+
to {
31+
transform: rotate(360deg);
32+
}
33+
}
34+
.animate-spin {
35+
animation: spin 1s linear infinite;
36+
}
37+
@keyframes ping {
38+
75%,
39+
100% {
40+
transform: scale(2);
41+
opacity: 0;
42+
}
43+
}
44+
.hover\\:animate-ping:hover {
45+
animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
46+
}
47+
@keyframes bounce {
48+
0%,
49+
100% {
50+
transform: translateY(-25%);
51+
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
52+
}
53+
50% {
54+
transform: none;
55+
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
56+
}
57+
}
58+
.group:hover .group-hover\\:animate-bounce {
59+
animation: bounce 1s infinite;
60+
}
61+
`)
62+
})
63+
})
64+
65+
test('custom', () => {
66+
let config = {
67+
mode: 'jit',
68+
purge: [{ raw: `<div class="animate-one"></div>` }],
69+
theme: {
70+
extend: {
71+
keyframes: {
72+
one: { to: { transform: 'rotate(360deg)' } },
73+
},
74+
animation: {
75+
one: 'one 2s',
76+
},
77+
},
78+
},
79+
}
80+
81+
let css = `@tailwind utilities`
82+
83+
return run(css, config).then((result) => {
84+
expect(result.css).toMatchFormattedCss(`
85+
@keyframes one {
86+
to {
87+
transform: rotate(360deg);
88+
}
89+
}
90+
.animate-one {
91+
animation: one 2s;
92+
}
93+
`)
94+
})
95+
})
96+
97+
test('custom prefixed', () => {
98+
let config = {
99+
mode: 'jit',
100+
prefix: 'tw-',
101+
purge: [{ raw: `<div class="tw-animate-one"></div>` }],
102+
theme: {
103+
extend: {
104+
keyframes: {
105+
one: { to: { transform: 'rotate(360deg)' } },
106+
},
107+
animation: {
108+
one: 'one 2s',
109+
},
110+
},
111+
},
112+
}
113+
114+
let css = `@tailwind utilities`
27115

28-
expect(result.css).toMatchFormattedCss(expected)
116+
return run(css, config).then((result) => {
117+
expect(result.css).toMatchFormattedCss(`
118+
@keyframes tw-one {
119+
to {
120+
transform: rotate(360deg);
121+
}
122+
}
123+
.tw-animate-one {
124+
animation: tw-one 2s;
125+
}
126+
`)
127+
})
128+
})
129+
130+
test('multiple', () => {
131+
let config = {
132+
mode: 'jit',
133+
purge: [{ raw: `<div class="animate-multiple"></div>` }],
134+
theme: {
135+
extend: {
136+
animation: {
137+
multiple: 'bounce 2s linear, pulse 3s ease-in',
138+
},
139+
},
140+
},
141+
}
142+
143+
let css = `@tailwind utilities`
144+
145+
return run(css, config).then((result) => {
146+
expect(result.css).toMatchFormattedCss(`
147+
@keyframes bounce {
148+
0%,
149+
100% {
150+
transform: translateY(-25%);
151+
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
152+
}
153+
50% {
154+
transform: none;
155+
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
156+
}
157+
}
158+
@keyframes pulse {
159+
50% {
160+
opacity: 0.5;
161+
}
162+
}
163+
.animate-multiple {
164+
animation: bounce 2s linear, pulse 3s ease-in;
165+
}
166+
`)
167+
})
168+
})
169+
170+
test('multiple custom', () => {
171+
let config = {
172+
mode: 'jit',
173+
purge: [{ raw: `<div class="animate-multiple"></div>` }],
174+
theme: {
175+
extend: {
176+
keyframes: {
177+
one: { to: { transform: 'rotate(360deg)' } },
178+
two: { to: { transform: 'scale(1.23)' } },
179+
},
180+
animation: {
181+
multiple: 'one 2s, two 3s',
182+
},
183+
},
184+
},
185+
}
186+
187+
let css = `@tailwind utilities`
188+
189+
return run(css, config).then((result) => {
190+
expect(result.css).toMatchFormattedCss(`
191+
@keyframes one {
192+
to {
193+
transform: rotate(360deg);
194+
}
195+
}
196+
@keyframes two {
197+
to {
198+
transform: scale(1.23);
199+
}
200+
}
201+
.animate-multiple {
202+
animation: one 2s, two 3s;
203+
}
204+
`)
29205
})
30206
})

0 commit comments

Comments
 (0)