@@ -3,129 +3,60 @@ import * as path from 'path'
3
3
import postcss from 'postcss'
4
4
import createUtilityPlugin from './util/createUtilityPlugin'
5
5
import buildMediaQuery from './util/buildMediaQuery'
6
- import prefixSelector from './util/prefixSelector'
7
6
import parseAnimationValue from './util/parseAnimationValue'
8
7
import flattenColorPalette from './util/flattenColorPalette'
9
8
import withAlphaVariable , { withAlphaValue } from './util/withAlphaVariable'
10
9
import toColorValue from './util/toColorValue'
11
10
import isPlainObject from './util/isPlainObject'
12
11
import transformThemeValue from './util/transformThemeValue'
13
- import {
14
- applyStateToMarker ,
15
- updateLastClasses ,
16
- updateAllClasses ,
17
- transformAllSelectors ,
18
- transformAllClasses ,
19
- transformLastClasses ,
20
- } from './util/pluginUtils'
21
12
import { version as tailwindVersion } from '../package.json'
22
13
import log from './util/log'
23
14
24
15
export let variantPlugins = {
25
- pseudoElementVariants : ( { config, addVariant } ) => {
26
- addVariant (
27
- 'first-letter' ,
28
- transformAllSelectors ( ( selector ) => {
29
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
30
- return withPseudo ( `first-letter${ config ( 'separator' ) } ${ className } ` , '::first-letter' )
31
- } )
32
- } )
33
- )
16
+ pseudoElementVariants : ( { addVariant } ) => {
17
+ addVariant ( 'first-letter' , '&::first-letter' )
18
+ addVariant ( 'first-line' , '&::first-line' )
34
19
35
- addVariant (
36
- 'first-line' ,
37
- transformAllSelectors ( ( selector ) => {
38
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
39
- return withPseudo ( `first-line${ config ( 'separator' ) } ${ className } ` , '::first-line' )
40
- } )
41
- } )
42
- )
20
+ addVariant ( 'marker' , [ '& *::marker' , '&::marker' ] )
21
+ addVariant ( 'selection' , [ '& *::selection' , '&::selection' ] )
43
22
44
- addVariant ( 'marker' , [
45
- transformAllSelectors ( ( selector ) => {
46
- let variantSelector = updateAllClasses ( selector , ( className ) => {
47
- return `marker${ config ( 'separator' ) } ${ className } `
48
- } )
23
+ addVariant ( 'file' , '&::file-selector-button' )
49
24
50
- return `${ variantSelector } *::marker`
51
- } ) ,
52
- transformAllSelectors ( ( selector ) => {
53
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
54
- return withPseudo ( `marker${ config ( 'separator' ) } ${ className } ` , '::marker' )
55
- } )
56
- } ) ,
57
- ] )
25
+ // TODO: Use `addVariant('before', '*::before')` instead, once `content`
26
+ // fix is implemented.
27
+ addVariant ( 'before' , ( { format, withRule } ) => {
28
+ format ( '&::before' )
58
29
59
- addVariant ( 'selection' , [
60
- transformAllSelectors ( ( selector ) => {
61
- let variantSelector = updateAllClasses ( selector , ( className ) => {
62
- return `selection ${ config ( 'separator' ) } ${ className } `
30
+ withRule ( ( rule ) => {
31
+ let foundContent = false
32
+ rule . walkDecls ( 'content' , ( ) => {
33
+ foundContent = true
63
34
} )
35
+ if ( ! foundContent ) {
36
+ rule . prepend ( postcss . decl ( { prop : 'content' , value : '""' } ) )
37
+ }
38
+ } )
39
+ } )
64
40
65
- return `${ variantSelector } *::selection`
66
- } ) ,
67
- transformAllSelectors ( ( selector ) => {
68
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
69
- return withPseudo ( `selection${ config ( 'separator' ) } ${ className } ` , '::selection' )
70
- } )
71
- } ) ,
72
- ] )
41
+ // TODO: Use `addVariant('after', '*::after')` instead, once `content`
42
+ // fix is implemented.
43
+ addVariant ( 'after' , ( { format, withRule } ) => {
44
+ format ( '&::after' )
73
45
74
- addVariant (
75
- 'file' ,
76
- transformAllSelectors ( ( selector ) => {
77
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
78
- return withPseudo ( `file${ config ( 'separator' ) } ${ className } ` , '::file-selector-button' )
46
+ withRule ( ( rule ) => {
47
+ let foundContent = false
48
+ rule . walkDecls ( 'content' , ( ) => {
49
+ foundContent = true
79
50
} )
80
- } )
81
- )
82
51
83
- addVariant (
84
- 'before' ,
85
- transformAllSelectors (
86
- ( selector ) => {
87
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
88
- return withPseudo ( `before${ config ( 'separator' ) } ${ className } ` , '::before' )
89
- } )
90
- } ,
91
- {
92
- withRule : ( rule ) => {
93
- let foundContent = false
94
- rule . walkDecls ( 'content' , ( ) => {
95
- foundContent = true
96
- } )
97
- if ( ! foundContent ) {
98
- rule . prepend ( postcss . decl ( { prop : 'content' , value : '""' } ) )
99
- }
100
- } ,
101
- }
102
- )
103
- )
104
-
105
- addVariant (
106
- 'after' ,
107
- transformAllSelectors (
108
- ( selector ) => {
109
- return updateAllClasses ( selector , ( className , { withPseudo } ) => {
110
- return withPseudo ( `after${ config ( 'separator' ) } ${ className } ` , '::after' )
111
- } )
112
- } ,
113
- {
114
- withRule : ( rule ) => {
115
- let foundContent = false
116
- rule . walkDecls ( 'content' , ( ) => {
117
- foundContent = true
118
- } )
119
- if ( ! foundContent ) {
120
- rule . prepend ( postcss . decl ( { prop : 'content' , value : '""' } ) )
121
- }
122
- } ,
52
+ if ( ! foundContent ) {
53
+ rule . prepend ( postcss . decl ( { prop : 'content' , value : '""' } ) )
123
54
}
124
- )
125
- )
55
+ } )
56
+ } )
126
57
} ,
127
58
128
- pseudoClassVariants : ( { config , addVariant } ) => {
59
+ pseudoClassVariants : ( { addVariant } ) => {
129
60
let pseudoVariants = [
130
61
// Positional
131
62
[ 'first' , ':first-child' ] ,
@@ -165,137 +96,44 @@ export let variantPlugins = {
165
96
'focus-visible' ,
166
97
'active' ,
167
98
'disabled' ,
168
- ]
169
-
170
- for ( let variant of pseudoVariants ) {
171
- let [ variantName , state ] = Array . isArray ( variant ) ? variant : [ variant , `:${ variant } ` ]
172
-
173
- addVariant (
174
- variantName ,
175
- transformAllClasses ( ( className , { withAttr, withPseudo } ) => {
176
- if ( state . startsWith ( ':' ) ) {
177
- return withPseudo ( `${ variantName } ${ config ( 'separator' ) } ${ className } ` , state )
178
- } else if ( state . startsWith ( '[' ) ) {
179
- return withAttr ( `${ variantName } ${ config ( 'separator' ) } ${ className } ` , state )
180
- }
181
- } )
182
- )
183
- }
184
-
185
- let groupMarker = prefixSelector ( config ( 'prefix' ) , '.group' )
186
- for ( let variant of pseudoVariants ) {
187
- let [ variantName , state ] = Array . isArray ( variant ) ? variant : [ variant , `:${ variant } ` ]
188
- let groupVariantName = `group-${ variantName } `
189
-
190
- addVariant (
191
- groupVariantName ,
192
- transformAllSelectors ( ( selector ) => {
193
- let variantSelector = updateAllClasses ( selector , ( className ) => {
194
- if ( `.${ className } ` === groupMarker ) return className
195
- return `${ groupVariantName } ${ config ( 'separator' ) } ${ className } `
196
- } )
197
-
198
- if ( variantSelector === selector ) {
199
- return null
200
- }
99
+ ] . map ( ( variant ) => ( Array . isArray ( variant ) ? variant : [ variant , `:${ variant } ` ] ) )
201
100
202
- return applyStateToMarker (
203
- variantSelector ,
204
- groupMarker ,
205
- state ,
206
- ( marker , selector ) => `${ marker } ${ selector } `
207
- )
208
- } )
209
- )
101
+ for ( let [ variantName , state ] of pseudoVariants ) {
102
+ addVariant ( variantName , `&${ state } ` )
210
103
}
211
104
212
- let peerMarker = prefixSelector ( config ( 'prefix' ) , '.peer' )
213
- for ( let variant of pseudoVariants ) {
214
- let [ variantName , state ] = Array . isArray ( variant ) ? variant : [ variant , `:${ variant } ` ]
215
- let peerVariantName = `peer-${ variantName } `
216
-
217
- addVariant (
218
- peerVariantName ,
219
- transformAllSelectors ( ( selector ) => {
220
- let variantSelector = updateAllClasses ( selector , ( className ) => {
221
- if ( `.${ className } ` === peerMarker ) return className
222
- return `${ peerVariantName } ${ config ( 'separator' ) } ${ className } `
223
- } )
224
-
225
- if ( variantSelector === selector ) {
226
- return null
227
- }
105
+ for ( let [ variantName , state ] of pseudoVariants ) {
106
+ addVariant ( `group-${ variantName } ` , `:merge(.group)${ state } &` )
107
+ }
228
108
229
- return applyStateToMarker ( variantSelector , peerMarker , state , ( marker , selector ) =>
230
- selector . trim ( ) . startsWith ( '~' ) ? `${ marker } ${ selector } ` : `${ marker } ~ ${ selector } `
231
- )
232
- } )
233
- )
109
+ for ( let [ variantName , state ] of pseudoVariants ) {
110
+ addVariant ( `peer-${ variantName } ` , `:merge(.peer)${ state } ~ &` )
234
111
}
235
112
} ,
236
113
237
- directionVariants : ( { config, addVariant } ) => {
238
- addVariant (
239
- 'ltr' ,
240
- transformAllSelectors ( ( selector ) => {
241
- log . warn ( 'rtl-experimental' , [
242
- 'The RTL features in Tailwind CSS are currently in preview.' ,
243
- 'Preview features are not covered by semver, and may be improved in breaking ways at any time.' ,
244
- ] )
245
- return `[dir="ltr"] ${ updateAllClasses (
246
- selector ,
247
- ( className ) => `ltr${ config ( 'separator' ) } ${ className } `
248
- ) } `
249
- } )
250
- )
114
+ directionVariants : ( { addVariant } ) => {
115
+ addVariant ( 'ltr' , ( { format } ) => {
116
+ log . warn ( 'rtl-experimental' , [
117
+ 'The RTL features in Tailwind CSS are currently in preview.' ,
118
+ 'Preview features are not covered by semver, and may be improved in breaking ways at any time.' ,
119
+ ] )
251
120
252
- addVariant (
253
- 'rtl' ,
254
- transformAllSelectors ( ( selector ) => {
255
- log . warn ( 'rtl-experimental' , [
256
- 'The RTL features in Tailwind CSS are currently in preview.' ,
257
- 'Preview features are not covered by semver, and may be improved in breaking ways at any time.' ,
258
- ] )
259
- return `[dir="rtl"] ${ updateAllClasses (
260
- selector ,
261
- ( className ) => `rtl${ config ( 'separator' ) } ${ className } `
262
- ) } `
263
- } )
264
- )
265
- } ,
121
+ format ( '[dir="ltr"] &' )
122
+ } )
266
123
267
- reducedMotionVariants : ( { config, addVariant } ) => {
268
- addVariant (
269
- 'motion-safe' ,
270
- transformLastClasses (
271
- ( className ) => {
272
- return `motion-safe${ config ( 'separator' ) } ${ className } `
273
- } ,
274
- {
275
- wrap : ( ) =>
276
- postcss . atRule ( {
277
- name : 'media' ,
278
- params : '(prefers-reduced-motion: no-preference)' ,
279
- } ) ,
280
- }
281
- )
282
- )
124
+ addVariant ( 'rtl' , ( { format } ) => {
125
+ log . warn ( 'rtl-experimental' , [
126
+ 'The RTL features in Tailwind CSS are currently in preview.' ,
127
+ 'Preview features are not covered by semver, and may be improved in breaking ways at any time.' ,
128
+ ] )
283
129
284
- addVariant (
285
- 'motion-reduce' ,
286
- transformLastClasses (
287
- ( className ) => {
288
- return `motion-reduce${ config ( 'separator' ) } ${ className } `
289
- } ,
290
- {
291
- wrap : ( ) =>
292
- postcss . atRule ( {
293
- name : 'media' ,
294
- params : '(prefers-reduced-motion: reduce)' ,
295
- } ) ,
296
- }
297
- )
298
- )
130
+ format ( '[dir="rtl"] &' )
131
+ } )
132
+ } ,
133
+
134
+ reducedMotionVariants : ( { addVariant } ) => {
135
+ addVariant ( 'motion-safe' , '@media (prefers-reduced-motion: no-preference)' )
136
+ addVariant ( 'motion-reduce' , '@media (prefers-reduced-motion: reduce)' )
299
137
} ,
300
138
301
139
darkVariants : ( { config, addVariant } ) => {
@@ -309,55 +147,18 @@ export let variantPlugins = {
309
147
}
310
148
311
149
if ( mode === 'class' ) {
312
- addVariant (
313
- 'dark' ,
314
- transformAllSelectors ( ( selector ) => {
315
- let variantSelector = updateLastClasses ( selector , ( className ) => {
316
- return `dark${ config ( 'separator' ) } ${ className } `
317
- } )
318
-
319
- if ( variantSelector === selector ) {
320
- return null
321
- }
322
-
323
- let darkSelector = prefixSelector ( config ( 'prefix' ) , `.dark` )
324
-
325
- return `${ darkSelector } ${ variantSelector } `
326
- } )
327
- )
150
+ addVariant ( 'dark' , '.dark &' )
328
151
} else if ( mode === 'media' ) {
329
- addVariant (
330
- 'dark' ,
331
- transformLastClasses (
332
- ( className ) => {
333
- return `dark${ config ( 'separator' ) } ${ className } `
334
- } ,
335
- {
336
- wrap : ( ) =>
337
- postcss . atRule ( {
338
- name : 'media' ,
339
- params : '(prefers-color-scheme: dark)' ,
340
- } ) ,
341
- }
342
- )
343
- )
152
+ addVariant ( 'dark' , '@media (prefers-color-scheme: dark)' )
344
153
}
345
154
} ,
346
155
347
- screenVariants : ( { config , theme, addVariant } ) => {
156
+ screenVariants : ( { theme, addVariant } ) => {
348
157
for ( let screen in theme ( 'screens' ) ) {
349
158
let size = theme ( 'screens' ) [ screen ]
350
159
let query = buildMediaQuery ( size )
351
160
352
- addVariant (
353
- screen ,
354
- transformLastClasses (
355
- ( className ) => {
356
- return `${ screen } ${ config ( 'separator' ) } ${ className } `
357
- } ,
358
- { wrap : ( ) => postcss . atRule ( { name : 'media' , params : query } ) }
359
- )
360
- )
161
+ addVariant ( screen , `@media ${ query } ` )
361
162
}
362
163
} ,
363
164
}
0 commit comments