Skip to content

Commit 4cb8137

Browse files
committed
implement core variants with new API
1 parent c5ec238 commit 4cb8137

File tree

1 file changed

+64
-263
lines changed

1 file changed

+64
-263
lines changed

src/corePlugins.js

Lines changed: 64 additions & 263 deletions
Original file line numberDiff line numberDiff line change
@@ -3,129 +3,60 @@ import * as path from 'path'
33
import postcss from 'postcss'
44
import createUtilityPlugin from './util/createUtilityPlugin'
55
import buildMediaQuery from './util/buildMediaQuery'
6-
import prefixSelector from './util/prefixSelector'
76
import parseAnimationValue from './util/parseAnimationValue'
87
import flattenColorPalette from './util/flattenColorPalette'
98
import withAlphaVariable, { withAlphaValue } from './util/withAlphaVariable'
109
import toColorValue from './util/toColorValue'
1110
import isPlainObject from './util/isPlainObject'
1211
import transformThemeValue from './util/transformThemeValue'
13-
import {
14-
applyStateToMarker,
15-
updateLastClasses,
16-
updateAllClasses,
17-
transformAllSelectors,
18-
transformAllClasses,
19-
transformLastClasses,
20-
} from './util/pluginUtils'
2112
import { version as tailwindVersion } from '../package.json'
2213
import log from './util/log'
2314

2415
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')
3419

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'])
4322

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')
4924

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')
5829

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
6334
})
35+
if (!foundContent) {
36+
rule.prepend(postcss.decl({ prop: 'content', value: '""' }))
37+
}
38+
})
39+
})
6440

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')
7345

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
7950
})
80-
})
81-
)
8251

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: '""' }))
12354
}
124-
)
125-
)
55+
})
56+
})
12657
},
12758

128-
pseudoClassVariants: ({ config, addVariant }) => {
59+
pseudoClassVariants: ({ addVariant }) => {
12960
let pseudoVariants = [
13061
// Positional
13162
['first', ':first-child'],
@@ -165,137 +96,44 @@ export let variantPlugins = {
16596
'focus-visible',
16697
'active',
16798
'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}`]))
201100

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}`)
210103
}
211104

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+
}
228108

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} ~ &`)
234111
}
235112
},
236113

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+
])
251120

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+
})
266123

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+
])
283129

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)')
299137
},
300138

301139
darkVariants: ({ config, addVariant }) => {
@@ -309,55 +147,18 @@ export let variantPlugins = {
309147
}
310148

311149
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 &')
328151
} 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)')
344153
}
345154
},
346155

347-
screenVariants: ({ config, theme, addVariant }) => {
156+
screenVariants: ({ theme, addVariant }) => {
348157
for (let screen in theme('screens')) {
349158
let size = theme('screens')[screen]
350159
let query = buildMediaQuery(size)
351160

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}`)
361162
}
362163
},
363164
}

0 commit comments

Comments
 (0)