diff --git a/src/corePlugins.js b/src/corePlugins.js index bd1e43c16..0ae64d9b0 100644 --- a/src/corePlugins.js +++ b/src/corePlugins.js @@ -144,28 +144,27 @@ export let variantPlugins = { } let variants = { - group: ({ modifier }) => + group: (_, { modifier }) => modifier ? [`:merge(.group\\/${modifier})`, ' &'] : [`:merge(.group)`, ' &'], - peer: ({ modifier }) => + peer: (_, { modifier }) => modifier ? [`:merge(.peer\\/${modifier})`, ' ~ &'] : [`:merge(.peer)`, ' ~ &'], } for (let [name, fn] of Object.entries(variants)) { matchVariant( name, - (ctx = {}) => { - let { modifier, value = '' } = ctx - if (modifier) { + (value = '', extra) => { + if (extra.modifier) { log.warn(`modifier-${name}-experimental`, [ `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.', ]) } - let result = normalize(typeof value === 'function' ? value(ctx) : value) + let result = normalize(typeof value === 'function' ? value(extra) : value) if (!result.includes('&')) result = '&' + result - let [a, b] = fn({ modifier }) + let [a, b] = fn('', extra) return result.replace(/&(\S+)?/g, (_, pseudo = '') => a + pseudo + b) }, { values: Object.fromEntries(pseudoVariants) } @@ -232,7 +231,7 @@ export let variantPlugins = { supportsVariants: ({ matchVariant, theme }) => { matchVariant( 'supports', - ({ value = '' }) => { + (value = '') => { let check = normalize(value) let isRaw = /^\w*\s*\(/.test(check) diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index fa0969ffb..bbc2454c4 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -525,18 +525,24 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs for (let [key, value] of Object.entries(options?.values ?? {})) { api.addVariant( isSpecial ? `${variant}${key}` : `${variant}-${key}`, - Object.assign(({ args, container }) => variantFn({ ...args, container, value }), { - [MATCH_VARIANT]: true, - }), + Object.assign( + ({ args, container }) => variantFn(value, { modifier: args.modifier, container }), + { + [MATCH_VARIANT]: true, + } + ), { ...options, value, id } ) } api.addVariant( variant, - Object.assign(({ args, container }) => variantFn({ ...args, container }), { - [MATCH_VARIANT]: true, - }), + Object.assign( + ({ args, container }) => variantFn(args.value, { modifier: args.modifier, container }), + { + [MATCH_VARIANT]: true, + } + ), { ...options, id } ) }, diff --git a/tests/match-variants.test.js b/tests/match-variants.test.js index 7b80a0639..fad171936 100644 --- a/tests/match-variants.test.js +++ b/tests/match-variants.test.js @@ -10,7 +10,7 @@ test('partial arbitrary variants', () => { corePlugins: { preflight: false }, plugins: [ ({ 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 }, plugins: [ ({ 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 }, plugins: [ ({ 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 }, plugins: [ ({ matchVariant }) => { - matchVariant('tooltip', ({ value: side }) => `&${side}`, { + matchVariant('tooltip', (side) => `&${side}`, { values: { bottom: '[data-location="bottom"]', top: '[data-location="top"]', @@ -154,7 +154,7 @@ test('matched variant values maintain the sort order they are registered in', () corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('alphabet', ({ value: side }) => `&${side}`, { + matchVariant('alphabet', (side) => `&${side}`, { values: { a: '[data-value="a"]', b: '[data-value="b"]', @@ -201,7 +201,7 @@ test('matchVariant can return an array of format strings from the function', () corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('test', ({ value: selector }) => + matchVariant('test', (selector) => selector.split(',').map((selector) => `&.${selector} > *`) ) }, @@ -243,7 +243,7 @@ it('should be possible to sort variants', () => { corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { 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 }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { values: { example: '600px', }, @@ -347,13 +347,13 @@ it('should be possible to sort stacked arbitrary variants correctly', () => { corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { return parseInt(a.value) - parseInt(z.value) }, }) - matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { + matchVariant('max', (value) => `@media (max-width: ${value})`, { sort(a, z) { 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 }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { return parseInt(a.value) - parseInt(z.value) }, }) - matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { + matchVariant('max', (value) => `@media (max-width: ${value})`, { sort(a, z) { return parseInt(z.value) - parseInt(a.value) }, @@ -464,12 +464,12 @@ it('should sort arbitrary variants left to right (1)', () => { corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { return parseInt(a.value) - parseInt(z.value) }, }) - matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { + matchVariant('max', (value) => `@media (max-width: ${value})`, { sort(a, z) { return parseInt(z.value) - parseInt(a.value) }, @@ -532,12 +532,12 @@ it('should sort arbitrary variants left to right (2)', () => { corePlugins: { preflight: false }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { return parseInt(a.value) - parseInt(z.value) }, }) - matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { + matchVariant('max', (value) => `@media (max-width: ${value})`, { sort(a, z) { 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 }, plugins: [ ({ matchVariant }) => { - matchVariant('min', ({ value }) => `@media (min-width: ${value})`, { + matchVariant('min', (value) => `@media (min-width: ${value})`, { sort(a, z) { let lookup = ['100px', '200px'] 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) }, }) - matchVariant('max', ({ value }) => `@media (max-width: ${value})`, { + matchVariant('max', (value) => `@media (max-width: ${value})`, { sort(a, z) { let lookup = ['300px', '400px'] if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) { diff --git a/types/config.d.ts b/types/config.d.ts index 4ea61e7da..b08490cd1 100644 --- a/types/config.d.ts +++ b/types/config.d.ts @@ -296,18 +296,14 @@ export interface PluginAPI { addBase(base: CSSRuleObject | CSSRuleObject[]): void // for registering custom variants addVariant(name: string, definition: string | string[] | (() => string) | (() => string)[]): void - matchVariant( + matchVariant( name: string, - cb: (options: { value: string; modifier: string | null }) => string | string[] - ): void - matchVariant( - name: string, - cb: (options: { value: string; modifier: string | null }) => string | string[], - options: { - values: Values - sort( - a: { value: keyof Values | string; modifier: string | null }, - b: { value: keyof Values | string; modifier: string | null } + cb: (value: T | string, extra: { modifier: string | null }) => string | string[], + options?: { + values?: KeyValuePair + sort?( + a: { value: T | string; modifier: string | null }, + b: { value: T | string; modifier: string | null } ): number } ): void @@ -326,8 +322,11 @@ export interface PluginAPI { export type PluginCreator = (api: PluginAPI) => void export type PluginsConfig = ( | PluginCreator - | { handler: PluginCreator; config?: Config } - | { (options: any): { handler: PluginCreator; config?: Config }; __isOptionsFunction: true } + | { handler: PluginCreator; config?: Partial } + | { + (options: any): { handler: PluginCreator; config?: Partial } + __isOptionsFunction: true + } )[] // Top level config related