From fa8253e42a232ae3efa6dff0e12074ac8cd3fc4b Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 27 Aug 2024 06:18:53 -0400 Subject: [PATCH] Fix support for declaration fallbacks in plugins (#14265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes support for "fallback" values for declarations in plugins. A plugin using `addUtilities`, `matchUtilities`, `addComponents`, etc… should be able to specify "fallback" values for declarations by passing an array as the value of a declaration however this does not currently work in v4 (but it does in v3): ```js export default { plugins: [ function ({ addUtilities }) { addUtilities({ '.outlined': { outline: ['1px solid ButtonText', '1px auto -webkit-focus-ring-color'], }, }) }, ], }; ``` After this PR the candidate `outlined` will now produce the following CSS — like it does in v3: ```css .outlined { outline: 1px solid ButtonText; outline: 1px auto -webkit-focus-ring-color; } ``` --- CHANGELOG.md | 1 + packages/tailwindcss/src/plugin-api.test.ts | 29 +++++++++++++++++++++ packages/tailwindcss/src/plugin-api.ts | 10 ++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c59534f..a30cd6914 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Correctly merge tuple values when using the plugin API ([#14260](https://github.com/tailwindlabs/tailwindcss/pull/14260)) - Handle arrays in the CSS `theme()` function when using plugins ([#14262](https://github.com/tailwindlabs/tailwindcss/pull/14262)) - Fix fallback values when using the CSS `theme()` function ([#14262](https://github.com/tailwindlabs/tailwindcss/pull/14262)) +- Fix support for declaration fallbacks in plugins ([#14265](https://github.com/tailwindlabs/tailwindcss/pull/14265)) ## [4.0.0-alpha.20] - 2024-08-23 diff --git a/packages/tailwindcss/src/plugin-api.test.ts b/packages/tailwindcss/src/plugin-api.test.ts index aa0f485a4..7e74572b0 100644 --- a/packages/tailwindcss/src/plugin-api.test.ts +++ b/packages/tailwindcss/src/plugin-api.test.ts @@ -976,6 +976,35 @@ describe('addUtilities()', () => { `) }) + test('utilities can use arrays for fallback declaration values', async () => { + let compiled = await compile( + css` + @plugin "my-plugin"; + @tailwind utilities; + `, + { + async loadPlugin() { + return ({ addUtilities }: PluginAPI) => { + addUtilities([ + { + '.outlined': { + outline: ['1px solid ButtonText', '1px auto -webkit-focus-ring-color'], + }, + }, + ]) + } + }, + }, + ) + + expect(optimizeCss(compiled.build(['outlined'])).trim()).toMatchInlineSnapshot(` + ".outlined { + outline: 1px solid buttontext; + outline: 1px auto -webkit-focus-ring-color; + }" + `) + }) + test('camel case properties are converted to kebab-case', async () => { let compiled = await compile( css` diff --git a/packages/tailwindcss/src/plugin-api.ts b/packages/tailwindcss/src/plugin-api.ts index eb366b7be..9cb2aece3 100644 --- a/packages/tailwindcss/src/plugin-api.ts +++ b/packages/tailwindcss/src/plugin-api.ts @@ -290,7 +290,7 @@ function buildPluginApi( return api } -export type CssInJs = { [key: string]: string | CssInJs | CssInJs[] } +export type CssInJs = { [key: string]: string | string[] | CssInJs | CssInJs[] } function objectToAst(rules: CssInJs | CssInJs[]): AstNode[] { let ast: AstNode[] = [] @@ -310,6 +310,14 @@ function objectToAst(rules: CssInJs | CssInJs[]): AstNode[] { ast.push(decl(name, String(value))) } + } else if (Array.isArray(value)) { + for (let item of value) { + if (typeof item === 'string') { + ast.push(decl(name, item)) + } else { + ast.push(rule(name, objectToAst(item))) + } + } } else if (value !== null) { ast.push(rule(name, objectToAst(value))) }