diff --git a/docs/README.md b/docs/README.md index 8c8a822d..48c351f6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,8 +16,8 @@ twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]') // → 'hover:bg-dark-red p-3 bg-[#B91C1C]' ``` -- Supports Tailwind v3.0 up to v3.3 (if you use Tailwind v2, use [tailwind-merge v0.9.0](https://github.com/dcastil/tailwind-merge/tree/v0.9.0)) -- Works in all modern browsers and Node >=12 +- Supports Tailwind v3.0 up to v3.4 (if you use Tailwind v2, use [tailwind-merge v0.9.0](https://github.com/dcastil/tailwind-merge/tree/v0.9.0)) +- Works in all modern browsers and maintained Node versions - Fully typed - [Check bundle size on Bundlephobia](https://bundlephobia.com/package/tailwind-merge) diff --git a/src/lib/default-config.ts b/src/lib/default-config.ts index a29892df..c0ccbe2e 100644 --- a/src/lib/default-config.ts +++ b/src/lib/default-config.ts @@ -193,12 +193,12 @@ export function getDefaultConfig() { * Floats * @see https://tailwindcss.com/docs/float */ - float: [{ float: ['right', 'left', 'none'] }], + float: [{ float: ['right', 'left', 'none', 'start', 'end'] }], /** * Clear * @see https://tailwindcss.com/docs/clear */ - clear: [{ clear: ['left', 'right', 'both', 'none'] }], + clear: [{ clear: ['left', 'right', 'both', 'none', 'start', 'end'] }], /** * Isolation * @see https://tailwindcss.com/docs/isolation @@ -581,12 +581,26 @@ export function getDefaultConfig() { * Width * @see https://tailwindcss.com/docs/width */ - w: [{ w: ['auto', 'min', 'max', 'fit', isArbitraryValue, spacing] }], + w: [ + { + w: [ + 'auto', + 'min', + 'max', + 'fit', + 'svw', + 'lvw', + 'dvw', + isArbitraryValue, + spacing, + ], + }, + ], /** * Min-Width * @see https://tailwindcss.com/docs/min-width */ - 'min-w': [{ 'min-w': ['min', 'max', 'fit', isArbitraryValue, isLength] }], + 'min-w': [{ 'min-w': [isArbitraryValue, spacing, 'min', 'max', 'fit'] }], /** * Max-Width * @see https://tailwindcss.com/docs/max-width @@ -594,7 +608,8 @@ export function getDefaultConfig() { 'max-w': [ { 'max-w': [ - '0', + isArbitraryValue, + spacing, 'none', 'full', 'min', @@ -603,7 +618,6 @@ export function getDefaultConfig() { 'prose', { screen: [isTshirtSize] }, isTshirtSize, - isArbitraryValue, ], }, ], @@ -611,17 +625,40 @@ export function getDefaultConfig() { * Height * @see https://tailwindcss.com/docs/height */ - h: [{ h: [isArbitraryValue, spacing, 'auto', 'min', 'max', 'fit'] }], + h: [ + { + h: [ + isArbitraryValue, + spacing, + 'auto', + 'min', + 'max', + 'fit', + 'svh', + 'lvh', + 'dvh', + ], + }, + ], /** * Min-Height * @see https://tailwindcss.com/docs/min-height */ - 'min-h': [{ 'min-h': ['min', 'max', 'fit', isLength, isArbitraryValue] }], + 'min-h': [ + { 'min-h': [isArbitraryValue, spacing, 'min', 'max', 'fit', 'svh', 'lvh', 'dvh'] }, + ], /** * Max-Height * @see https://tailwindcss.com/docs/max-height */ - 'max-h': [{ 'max-h': [isArbitraryValue, spacing, 'min', 'max', 'fit'] }], + 'max-h': [ + { 'max-h': [isArbitraryValue, spacing, 'min', 'max', 'fit', 'svh', 'lvh', 'dvh'] }, + ], + /** + * Size + * @see https://tailwindcss.com/docs/size + */ + size: [{ size: [isArbitraryValue, spacing, 'auto', 'min', 'max', 'fit'] }], // Typography /** * Font Size @@ -811,6 +848,11 @@ export function getDefaultConfig() { * @see https://tailwindcss.com/docs/text-overflow */ 'text-overflow': ['truncate', 'text-ellipsis', 'text-clip'], + /** + * Text Wrap + * @see https://tailwindcss.com/docs/text-wrap + */ + 'text-wrap': [{ text: ['wrap', 'nowrap', 'balance', 'pretty'] }], /** * Text Indent * @see https://tailwindcss.com/docs/text-indent @@ -1468,7 +1510,7 @@ export function getDefaultConfig() { * Appearance * @see https://tailwindcss.com/docs/appearance */ - appearance: ['appearance-none'], + appearance: [{ appearance: ['none', 'auto'] }], /** * Cursor * @see https://tailwindcss.com/docs/cursor @@ -1712,6 +1754,11 @@ export function getDefaultConfig() { * @see https://tailwindcss.com/docs/screen-readers */ sr: ['sr-only', 'not-sr-only'], + /** + * Forced Color Adjust + * @see https://tailwindcss.com/docs/forced-color-adjust + */ + 'forced-color-adjust': [{ 'forced-color-adjust': ['auto', 'none'] }], }, conflictingClassGroups: { overflow: ['overflow-x', 'overflow-y'], @@ -1727,6 +1774,7 @@ export function getDefaultConfig() { m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'], mx: ['mr', 'ml'], my: ['mt', 'mb'], + size: ['w', 'h'], 'font-size': ['leading'], 'fvn-normal': [ 'fvn-ordinal', diff --git a/src/lib/types.ts b/src/lib/types.ts index 25eabaf5..54ed0876 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -223,6 +223,7 @@ export type DefaultClassGroupIds = | 'font-smoothing' | 'font-style' | 'font-weight' + | 'forced-color-adjust' | 'fvn-figure' | 'fvn-fraction' | 'fvn-normal' @@ -360,6 +361,7 @@ export type DefaultClassGroupIds = | 'shadow-color' | 'shadow' | 'shrink' + | 'size' | 'skew-x' | 'skew-y' | 'snap-align' @@ -384,11 +386,12 @@ export type DefaultClassGroupIds = | 'text-opacity' | 'text-overflow' | 'text-transform' + | 'text-wrap' | 'top' - | 'touch' + | 'touch-pz' | 'touch-x' | 'touch-y' - | 'touch-pz' + | 'touch' | 'tracking' | 'transform-origin' | 'transform' diff --git a/tests/class-map.test.ts b/tests/class-map.test.ts index b3340743..0dd5eb82 100644 --- a/tests/class-map.test.ts +++ b/tests/class-map.test.ts @@ -112,6 +112,7 @@ test('class map has correct class groups at first part', () => { float: ['float'], flow: ['display'], font: ['font-family', 'font-weight'], + forced: ['forced-color-adjust'], from: ['gradient-from', 'gradient-from-pos'], gap: ['gap', 'gap-x', 'gap-y'], grayscale: ['grayscale'], @@ -233,6 +234,7 @@ test('class map has correct class groups at first part', () => { sepia: ['sepia'], shadow: ['shadow', 'shadow-color'], shrink: ['shrink'], + size: ['size'], skew: ['skew-x', 'skew-y'], slashed: ['fvn-slashed-zero'], snap: ['snap-align', 'snap-stop', 'snap-strictness', 'snap-type'], @@ -246,7 +248,14 @@ test('class map has correct class groups at first part', () => { subpixel: ['font-smoothing'], table: ['display', 'table-layout'], tabular: ['fvn-spacing'], - text: ['font-size', 'text-alignment', 'text-color', 'text-opacity', 'text-overflow'], + text: [ + 'font-size', + 'text-alignment', + 'text-color', + 'text-opacity', + 'text-overflow', + 'text-wrap', + ], to: ['gradient-to', 'gradient-to-pos'], top: ['top'], touch: ['touch', 'touch-pz', 'touch-x', 'touch-y'], diff --git a/tests/tailwind-css-versions.test.ts b/tests/tailwind-css-versions.test.ts index c4e7c697..3c08b607 100644 --- a/tests/tailwind-css-versions.test.ts +++ b/tests/tailwind-css-versions.test.ts @@ -34,3 +34,24 @@ test('supports Tailwind CSS v3.3 features', () => { expect(twMerge('content-normal content-center content-stretch')).toBe('content-stretch') expect(twMerge('whitespace-nowrap whitespace-break-spaces')).toBe('whitespace-break-spaces') }) + +test('supports Tailwind CSS v3.4 features', () => { + expect(twMerge('h-svh h-dvh w-svw w-dvw')).toBe('h-dvh w-dvw') + expect( + twMerge( + 'has-[[data-potato]]:p-1 has-[[data-potato]]:p-2 group-has-[:checked]:grid group-has-[:checked]:flex', + ), + ).toBe('has-[[data-potato]]:p-2 group-has-[:checked]:flex') + expect(twMerge('text-wrap text-pretty')).toBe('text-pretty') + expect(twMerge('w-5 h-3 size-10 w-12')).toBe('size-10 w-12') + expect(twMerge('grid-cols-2 grid-cols-subgrid grid-rows-5 grid-rows-subgrid')).toBe( + 'grid-cols-subgrid grid-rows-subgrid', + ) + expect(twMerge('min-w-0 min-w-50 min-w-px max-w-0 max-w-50 max-w-px')).toBe('min-w-px max-w-px') + expect(twMerge('forced-color-adjust-none forced-color-adjust-auto')).toBe( + 'forced-color-adjust-auto', + ) + expect(twMerge('appearance-none appearance-auto')).toBe('appearance-auto') + expect(twMerge('float-start float-end clear-start clear-end')).toBe('float-end clear-end') + expect(twMerge('*:p-10 *:p-20 hover:*:p-10 hover:*:p-20')).toBe('*:p-20 hover:*:p-20') +})