diff --git a/.changeset/metal-owls-explode.md b/.changeset/metal-owls-explode.md new file mode 100644 index 000000000..a643ade80 --- /dev/null +++ b/.changeset/metal-owls-explode.md @@ -0,0 +1,5 @@ +--- +'@twind/preset-tailwind': minor +--- + +Add `min-*` and `max-*` variants diff --git a/packages/cdn/package.json b/packages/cdn/package.json index d7c9b2113..58e422cc9 100644 --- a/packages/cdn/package.json +++ b/packages/cdn/package.json @@ -27,7 +27,7 @@ "name": "@twind/cdn", "path": "dist/cdn.esnext.js", "brotli": true, - "limit": "16.4kb" + "limit": "16.5kb" } ], "dependencies": { diff --git a/packages/intellisense/src/__snapshots__/enumerate.test.ts.snap b/packages/intellisense/src/__snapshots__/enumerate.test.ts.snap index 604db8d92..689e420f7 100644 --- a/packages/intellisense/src/__snapshots__/enumerate.test.ts.snap +++ b/packages/intellisense/src/__snapshots__/enumerate.test.ts.snap @@ -2,11 +2,18 @@ exports[`enumerate 1`] = ` [ + "max-[:", + "min-[:", + "max-sm:", "sm:", + "max-md:", "md:", "lg:", + "max-lg:", + "max-xl:", "xl:", "2xl:", + "max-2xl:", "active:", "after:", "any-link:", diff --git a/packages/intellisense/src/__snapshots__/suggest-at.test.ts.snap b/packages/intellisense/src/__snapshots__/suggest-at.test.ts.snap index 4bda9baf3..15090c101 100644 --- a/packages/intellisense/src/__snapshots__/suggest-at.test.ts.snap +++ b/packages/intellisense/src/__snapshots__/suggest-at.test.ts.snap @@ -317,10 +317,17 @@ exports[`suggestAt html 4`] = ` "thin", "[", "[", + "min-[:", + "max-[:", + "max-sm:", "sm:", + "max-md:", "md:", + "max-lg:", "lg:", + "max-xl:", "xl:", + "max-2xl:", "2xl:", "visited:", "valid:", @@ -499,11 +506,18 @@ exports[`suggestAt html 5`] = ` "end": 28, "start": 28, "suggestions": [ + "max-[:", + "min-[:", + "max-sm:", "sm:", + "max-md:", "md:", "lg:", + "max-lg:", + "max-xl:", "xl:", "2xl:", + "max-2xl:", "active:", "after:", "any-link:", diff --git a/packages/intellisense/src/__snapshots__/suggest.test.ts.snap b/packages/intellisense/src/__snapshots__/suggest.test.ts.snap index 07032d396..1d66193aa 100644 --- a/packages/intellisense/src/__snapshots__/suggest.test.ts.snap +++ b/packages/intellisense/src/__snapshots__/suggest.test.ts.snap @@ -2847,6 +2847,12 @@ exports[`suggest with single char input 1`] = ` exports[`suggest with two chars 1`] = ` [ + "max-[:", + "max-sm:", + "max-md:", + "max-lg:", + "max-xl:", + "max-2xl:", "marker:", "max-h-0", "max-h-0.5", diff --git a/packages/intellisense/src/suggest.test.ts b/packages/intellisense/src/suggest.test.ts index 6d74983bc..72a474b43 100644 --- a/packages/intellisense/src/suggest.test.ts +++ b/packages/intellisense/src/suggest.test.ts @@ -16,7 +16,7 @@ const $ = (suggestions: Promise) => suggestions.then((suggestions) => suggestions.map(({ value }) => value)) test('suggest with empty input', async () => { - await expect(intellisense.suggest('')).resolves.toHaveLength(14727) + await expect(intellisense.suggest('')).resolves.toHaveLength(14734) }) test('suggest with single char input', async () => { diff --git a/packages/preset-tailwind/src/rules.test.json b/packages/preset-tailwind/src/rules.test.json index 157413893..8bdbbe973 100644 --- a/packages/preset-tailwind/src/rules.test.json +++ b/packages/preset-tailwind/src/rules.test.json @@ -2178,5 +2178,39 @@ "// No value give for the property, defaulting to prop: var(--tw)": "", "supports-[container-type]:underline": "@supports (container-type:var(--tw)){.supports-\\[container-type\\]\\:underline{text-decoration-line:underline}}", "// Named supports usage": "", - "supports-grid:underline": "@supports (display: grid){.supports-grid\\:underline{text-decoration-line:underline}}" + "supports-grid:underline": "@supports (display: grid){.supports-grid\\:underline{text-decoration-line:underline}}", + "px-(max-sm:2 sm:4 5)": [ + "px-5 max-sm:px-2 sm:px-4", + [ + ".px-5{padding-left:1.25rem;padding-right:1.25rem}", + "@media not all and (min-width:640px){.max-sm\\:px-2{padding-left:0.5rem;padding-right:0.5rem}}", + "@media (min-width:640px){.sm\\:px-4{padding-left:1rem;padding-right:1rem}}" + ] + ], + "sm:max-md:px-2": "@media (min-width:640px){@media not all and (min-width:768px){.sm\\:max-md\\:px-2{padding-left:0.5rem;padding-right:0.5rem}}}", + "max-[320px]:px-2 max-sm:px-4 px-5": [ + "px-5 max-[320px]:px-2 max-sm:px-4", + [ + ".px-5{padding-left:1.25rem;padding-right:1.25rem}", + "@media not all and (min-width:320px){.max-\\[320px\\]\\:px-2{padding-left:0.5rem;padding-right:0.5rem}}", + "@media not all and (min-width:640px){.max-sm\\:px-4{padding-left:1rem;padding-right:1rem}}" + ] + ], + "// max-* works only for 'simple' screen values": "", + "max-special": ["max-special", []], + "min-[320px]:px-2 px-5": [ + "px-5 min-[320px]:px-2", + [ + ".px-5{padding-left:1.25rem;padding-right:1.25rem}", + "@media (min-width:320px){.min-\\[320px\\]\\:px-2{padding-left:0.5rem;padding-right:0.5rem}}" + ] + ], + "px-(min-[320px]:2 sm:4 5)": [ + "px-5 min-[320px]:px-2 sm:px-4", + [ + ".px-5{padding-left:1.25rem;padding-right:1.25rem}", + "@media (min-width:320px){.min-\\[320px\\]\\:px-2{padding-left:0.5rem;padding-right:0.5rem}}", + "@media (min-width:640px){.sm\\:px-4{padding-left:1rem;padding-right:1rem}}" + ] + ] } diff --git a/packages/preset-tailwind/src/variants.ts b/packages/preset-tailwind/src/variants.ts index 8ada14561..195ac30fb 100644 --- a/packages/preset-tailwind/src/variants.ts +++ b/packages/preset-tailwind/src/variants.ts @@ -169,6 +169,38 @@ const variants: Variant[] = [ ), ], + [ + 'max-', + withAutocomplete$( + ({ $$ }, context) => { + $$ &&= (context.theme('screens', $$) || arbitrary($$, '', context)) as string + if (typeof $$ == 'string') { + return `@media not all and (min-width:${$$})` + } + }, + DEV && + ((_, { theme }) => + Object.entries(theme('screens') || {}) + .filter(([, value]) => typeof value == 'string') + .map( + ([key, value]): AutocompleteItem => ({ + suffix: key, + label: `@media not all and (min-width:${value})`, + theme: { section: 'screens', key }, + }), + ) + .concat([{ suffix: '[', label: `@media not all and (min-width: …)` }])), + ), + ], + + [ + 'min-', + withAutocomplete$(({ $$ }, context) => { + $$ &&= arbitrary($$, '', context) as string + return $$ && `@media (min-width:${$$})` + }, DEV && (() => [{ suffix: '[', label: `@media (min-width: …)` }])), + ], + // Arbitrary variants [/^\[(.+)]$/, ({ 1: $1 }) => /[&@]/.test($1) && normalize($1).replace(/[}]+$/, '').split('{')], ]