Properly resolve theme('someKey.DEFAULT') when only --some-key-* keys exist (#14354)
This PR fixes an issue where theme function calls like
`theme('transitionTimingFunction.DEFAULT')` would incorrectly resolve to
an object when the set of defined CSS theme values looked like this:
```css
@theme {
--transition-timing-function-in: ease-in;
--transition-timing-function-out: ease-out;
--transition-timing-function-in-out: ease-out;
}
```
We were mistakenly retrieving the entire
`--transition-timing-function-*` namespace in this case and returning an
object, even though the user is explicitly asking for a single value by
including `.DEFAULT` in their call.
This ensures it resolves to null instead. Fixes an issue I ran into on
this live stream earlier today:
https://x.com/adamwathan/status/1831740214051799281
---------
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
This commit is contained in:
parent
f028eae75e
commit
7b59aac274
3 changed files with 43 additions and 14 deletions
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
|
||||
- Ensure there is always CLI feedback on save even when no new classes were found ([#14351](https://github.com/tailwindlabs/tailwindcss/pull/14351))
|
||||
- Properly resolve `theme('someKey.DEFAULT')` when all `--some-key-*` keys have a suffix ([#14354](https://github.com/tailwindlabs/tailwindcss/pull/14354))
|
||||
|
||||
## [4.0.0-alpha.23] - 2024-09-05
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ function readFromCss(theme: Theme, path: string[]) {
|
|||
}
|
||||
|
||||
// We have to turn the map into object-like structure for v3 compatibility
|
||||
let obj = {}
|
||||
let obj: Record<string, unknown> = {}
|
||||
let useNestedObjects = false // paths.some((path) => nestedKeys.has(path))
|
||||
|
||||
for (let [key, value] of map) {
|
||||
|
|
@ -134,20 +134,19 @@ function readFromCss(theme: Theme, path: string[]) {
|
|||
set(obj, path, value)
|
||||
}
|
||||
|
||||
if ('DEFAULT' in obj) {
|
||||
// The request looked like `theme('animation.DEFAULT')` and was turned into
|
||||
// a lookup for `--animation-*` and we should extract the value for the
|
||||
// `DEFAULT` key from the list of possible values
|
||||
if (path[path.length - 1] === 'DEFAULT') {
|
||||
return obj.DEFAULT
|
||||
}
|
||||
// If the request looked like `theme('animation.DEFAULT')` it would have been
|
||||
// turned into a lookup for `--animation-*` so we should extract the value for
|
||||
// the `DEFAULT` key from the list of possible values. If there is no
|
||||
// `DEFAULT` in the list, there is no match so return `null`.
|
||||
if (path[path.length - 1] === 'DEFAULT') {
|
||||
return obj?.DEFAULT ?? null
|
||||
}
|
||||
|
||||
// The request looked like `theme('animation.spin')` and was turned into a
|
||||
// lookup for `--animation-spin-*` which had only one entry which means it
|
||||
// should be returned directly
|
||||
if (Object.keys(obj).length === 1) {
|
||||
return obj.DEFAULT
|
||||
}
|
||||
// The request looked like `theme('animation.spin')` and was turned into a
|
||||
// lookup for `--animation-spin-*` which had only one entry which means it
|
||||
// should be returned directly.
|
||||
if ('DEFAULT' in obj && Object.keys(obj).length === 1) {
|
||||
return obj.DEFAULT
|
||||
}
|
||||
|
||||
return obj
|
||||
|
|
|
|||
|
|
@ -804,6 +804,35 @@ describe('theme', async () => {
|
|||
expect(fn).toHaveBeenCalledWith('blue')
|
||||
})
|
||||
|
||||
test("`theme('*.DEFAULT')` resolves to `undefined` when all theme keys in that namespace have a suffix", async ({
|
||||
expect,
|
||||
}) => {
|
||||
let input = css`
|
||||
@tailwind utilities;
|
||||
@plugin "my-plugin";
|
||||
@theme {
|
||||
--transition-timing-function-in: ease-in;
|
||||
--transition-timing-function-out: ease-out;
|
||||
}
|
||||
`
|
||||
|
||||
let fn = vi.fn()
|
||||
|
||||
await compile(input, {
|
||||
loadPlugin: async () => {
|
||||
return plugin(({ theme }) => {
|
||||
fn(theme('transitionTimingFunction.DEFAULT'))
|
||||
fn(theme('transitionTimingFunction.in'))
|
||||
fn(theme('transitionTimingFunction.out'))
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
expect(fn).toHaveBeenNthCalledWith(1, undefined)
|
||||
expect(fn).toHaveBeenNthCalledWith(2, 'ease-in')
|
||||
expect(fn).toHaveBeenNthCalledWith(3, 'ease-out')
|
||||
})
|
||||
|
||||
test('nested theme key lookups work even for flattened keys', async ({ expect }) => {
|
||||
let input = css`
|
||||
@tailwind utilities;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue