Compare commits

...
Sign in to create a new pull request.

4 commits

Author SHA1 Message Date
Jordan Pittman
a9015fc14c Change match variant wrap modifier in an object
Needed for compat w/ some group and peer plugins
2022-10-12 17:18:37 -04:00
Jordan Pittman
2049989184 Fix CS
wip
2022-10-12 17:11:50 -04:00
Jordan Pittman
285b02c9de Change matchVariant API to use positional arguments 2022-10-12 10:43:43 -04:00
Jordan Pittman
651e3dd4c3 Fix plugin types 2022-10-12 09:27:17 -04:00
4 changed files with 49 additions and 45 deletions

View file

@ -144,28 +144,27 @@ export let variantPlugins = {
} }
let variants = { let variants = {
group: ({ modifier }) => group: (_, { modifier }) =>
modifier ? [`:merge(.group\\/${modifier})`, ' &'] : [`:merge(.group)`, ' &'], modifier ? [`:merge(.group\\/${modifier})`, ' &'] : [`:merge(.group)`, ' &'],
peer: ({ modifier }) => peer: (_, { modifier }) =>
modifier ? [`:merge(.peer\\/${modifier})`, ' ~ &'] : [`:merge(.peer)`, ' ~ &'], modifier ? [`:merge(.peer\\/${modifier})`, ' ~ &'] : [`:merge(.peer)`, ' ~ &'],
} }
for (let [name, fn] of Object.entries(variants)) { for (let [name, fn] of Object.entries(variants)) {
matchVariant( matchVariant(
name, name,
(ctx = {}) => { (value = '', extra) => {
let { modifier, value = '' } = ctx if (extra.modifier) {
if (modifier) {
log.warn(`modifier-${name}-experimental`, [ log.warn(`modifier-${name}-experimental`, [
`The ${name} variant modifier feature in Tailwind CSS is currently in preview.`, `The ${name} variant modifier feature in Tailwind CSS is currently in preview.`,
'Preview features are not covered by semver, and may be improved in breaking ways at any time.', 'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
]) ])
} }
let result = normalize(typeof value === 'function' ? value(ctx) : value) let result = normalize(typeof value === 'function' ? value(extra) : value)
if (!result.includes('&')) result = '&' + result if (!result.includes('&')) result = '&' + result
let [a, b] = fn({ modifier }) let [a, b] = fn('', extra)
return result.replace(/&(\S+)?/g, (_, pseudo = '') => a + pseudo + b) return result.replace(/&(\S+)?/g, (_, pseudo = '') => a + pseudo + b)
}, },
{ values: Object.fromEntries(pseudoVariants) } { values: Object.fromEntries(pseudoVariants) }
@ -232,7 +231,7 @@ export let variantPlugins = {
supportsVariants: ({ matchVariant, theme }) => { supportsVariants: ({ matchVariant, theme }) => {
matchVariant( matchVariant(
'supports', 'supports',
({ value = '' }) => { (value = '') => {
let check = normalize(value) let check = normalize(value)
let isRaw = /^\w*\s*\(/.test(check) let isRaw = /^\w*\s*\(/.test(check)

View file

@ -525,18 +525,24 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
for (let [key, value] of Object.entries(options?.values ?? {})) { for (let [key, value] of Object.entries(options?.values ?? {})) {
api.addVariant( api.addVariant(
isSpecial ? `${variant}${key}` : `${variant}-${key}`, isSpecial ? `${variant}${key}` : `${variant}-${key}`,
Object.assign(({ args, container }) => variantFn({ ...args, container, value }), { Object.assign(
[MATCH_VARIANT]: true, ({ args, container }) => variantFn(value, { modifier: args.modifier, container }),
}), {
[MATCH_VARIANT]: true,
}
),
{ ...options, value, id } { ...options, value, id }
) )
} }
api.addVariant( api.addVariant(
variant, variant,
Object.assign(({ args, container }) => variantFn({ ...args, container }), { Object.assign(
[MATCH_VARIANT]: true, ({ args, container }) => variantFn(args.value, { modifier: args.modifier, container }),
}), {
[MATCH_VARIANT]: true,
}
),
{ ...options, id } { ...options, id }
) )
}, },

View file

@ -10,7 +10,7 @@ test('partial arbitrary variants', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('potato', ({ value: flavor }) => `.potato-${flavor} &`) matchVariant('potato', (flavor) => `.potato-${flavor} &`)
}, },
], ],
} }
@ -43,7 +43,7 @@ test('partial arbitrary variants with at-rules', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('potato', ({ value: flavor }) => `@media (potato: ${flavor})`) matchVariant('potato', (flavor) => `@media (potato: ${flavor})`)
}, },
], ],
} }
@ -79,7 +79,7 @@ test('partial arbitrary variants with at-rules and placeholder', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('potato', ({ value: flavor }) => `@media (potato: ${flavor}) { &:potato }`) matchVariant('potato', (flavor) => `@media (potato: ${flavor}) { &:potato }`)
}, },
], ],
} }
@ -115,7 +115,7 @@ test('partial arbitrary variants with default values', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('tooltip', ({ value: side }) => `&${side}`, { matchVariant('tooltip', (side) => `&${side}`, {
values: { values: {
bottom: '[data-location="bottom"]', bottom: '[data-location="bottom"]',
top: '[data-location="top"]', top: '[data-location="top"]',
@ -154,7 +154,7 @@ test('matched variant values maintain the sort order they are registered in', ()
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('alphabet', ({ value: side }) => `&${side}`, { matchVariant('alphabet', (side) => `&${side}`, {
values: { values: {
a: '[data-value="a"]', a: '[data-value="a"]',
b: '[data-value="b"]', b: '[data-value="b"]',
@ -201,7 +201,7 @@ test('matchVariant can return an array of format strings from the function', ()
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('test', ({ value: selector }) => matchVariant('test', (selector) =>
selector.split(',').map((selector) => `&.${selector} > *`) selector.split(',').map((selector) => `&.${selector} > *`)
) )
}, },
@ -243,7 +243,7 @@ it('should be possible to sort variants', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(a.value) - parseInt(z.value) return parseInt(a.value) - parseInt(z.value)
}, },
@ -287,7 +287,7 @@ it('should be possible to compare arbitrary variants and hardcoded variants', ()
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
values: { values: {
example: '600px', example: '600px',
}, },
@ -347,13 +347,13 @@ it('should be possible to sort stacked arbitrary variants correctly', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(a.value) - parseInt(z.value) return parseInt(a.value) - parseInt(z.value)
}, },
}) })
matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { matchVariant('max', (value) => `@media (max-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(z.value) - parseInt(a.value) return parseInt(z.value) - parseInt(a.value)
}, },
@ -412,13 +412,13 @@ it('should maintain sort from other variants, if sort functions of arbitrary var
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(a.value) - parseInt(z.value) return parseInt(a.value) - parseInt(z.value)
}, },
}) })
matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { matchVariant('max', (value) => `@media (max-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(z.value) - parseInt(a.value) return parseInt(z.value) - parseInt(a.value)
}, },
@ -464,12 +464,12 @@ it('should sort arbitrary variants left to right (1)', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(a.value) - parseInt(z.value) return parseInt(a.value) - parseInt(z.value)
}, },
}) })
matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { matchVariant('max', (value) => `@media (max-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(z.value) - parseInt(a.value) return parseInt(z.value) - parseInt(a.value)
}, },
@ -532,12 +532,12 @@ it('should sort arbitrary variants left to right (2)', () => {
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(a.value) - parseInt(z.value) return parseInt(a.value) - parseInt(z.value)
}, },
}) })
matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { matchVariant('max', (value) => `@media (max-width: ${value})`, {
sort(a, z) { sort(a, z) {
return parseInt(z.value) - parseInt(a.value) return parseInt(z.value) - parseInt(a.value)
}, },
@ -598,7 +598,7 @@ it('should guarantee that we are not passing values from other variants to the w
corePlugins: { preflight: false }, corePlugins: { preflight: false },
plugins: [ plugins: [
({ matchVariant }) => { ({ matchVariant }) => {
matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { matchVariant('min', (value) => `@media (min-width: ${value})`, {
sort(a, z) { sort(a, z) {
let lookup = ['100px', '200px'] let lookup = ['100px', '200px']
if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) { if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) {
@ -607,7 +607,7 @@ it('should guarantee that we are not passing values from other variants to the w
return lookup.indexOf(a.value) - lookup.indexOf(z.value) return lookup.indexOf(a.value) - lookup.indexOf(z.value)
}, },
}) })
matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { matchVariant('max', (value) => `@media (max-width: ${value})`, {
sort(a, z) { sort(a, z) {
let lookup = ['300px', '400px'] let lookup = ['300px', '400px']
if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) { if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) {

25
types/config.d.ts vendored
View file

@ -296,18 +296,14 @@ export interface PluginAPI {
addBase(base: CSSRuleObject | CSSRuleObject[]): void addBase(base: CSSRuleObject | CSSRuleObject[]): void
// for registering custom variants // for registering custom variants
addVariant(name: string, definition: string | string[] | (() => string) | (() => string)[]): void addVariant(name: string, definition: string | string[] | (() => string) | (() => string)[]): void
matchVariant( matchVariant<T = string>(
name: string, name: string,
cb: (options: { value: string; modifier: string | null }) => string | string[] cb: (value: T | string, extra: { modifier: string | null }) => string | string[],
): void options?: {
matchVariant<Values extends {}>( values?: KeyValuePair<string, T>
name: string, sort?(
cb: (options: { value: string; modifier: string | null }) => string | string[], a: { value: T | string; modifier: string | null },
options: { b: { value: T | string; modifier: string | null }
values: Values
sort(
a: { value: keyof Values | string; modifier: string | null },
b: { value: keyof Values | string; modifier: string | null }
): number ): number
} }
): void ): void
@ -326,8 +322,11 @@ export interface PluginAPI {
export type PluginCreator = (api: PluginAPI) => void export type PluginCreator = (api: PluginAPI) => void
export type PluginsConfig = ( export type PluginsConfig = (
| PluginCreator | PluginCreator
| { handler: PluginCreator; config?: Config } | { handler: PluginCreator; config?: Partial<Config> }
| { (options: any): { handler: PluginCreator; config?: Config }; __isOptionsFunction: true } | {
(options: any): { handler: PluginCreator; config?: Partial<Config> }
__isOptionsFunction: true
}
)[] )[]
// Top level config related // Top level config related