tailwind-merge 0.6.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -31
- package/dist/index.cjs +358 -283
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +313 -271
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +355 -284
- package/dist/index.module.js.map +1 -1
- package/dist/types/config-utils.d.ts +0 -2
- package/dist/types/create-tailwind-merge.d.ts +8 -0
- package/dist/types/default-config.d.ts +11 -13
- package/dist/types/extend-tailwind-merge.d.ts +4 -0
- package/dist/types/index.d.ts +8 -3
- package/dist/types/merge-configs.d.ts +6 -0
- package/dist/types/types.d.ts +0 -6
- package/dist/types/{config-validators.d.ts → validators.d.ts} +0 -0
- package/package.json +23 -20
- package/src/config-utils.ts +0 -2
- package/src/create-tailwind-merge.ts +63 -0
- package/src/default-config.ts +199 -240
- package/src/extend-tailwind-merge.ts +18 -0
- package/src/index.ts +9 -3
- package/src/merge-classlist.ts +6 -10
- package/src/merge-configs.ts +51 -0
- package/src/types.ts +0 -6
- package/src/{config-validators.ts → validators.ts} +0 -0
- package/dist/types/prefix-utils.d.ts +0 -5
- package/dist/types/tailwind-merge.d.ts +0 -8
- package/src/prefix-utils.ts +0 -34
- package/src/tailwind-merge.ts +0 -43
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<br />
|
|
3
3
|
<a href="https://github.com/dcastil/tailwind-merge">
|
|
4
|
-
<!-- AUTOGENERATED START logo-image --><img src="https://github.com/dcastil/tailwind-merge/raw/v0.
|
|
4
|
+
<!-- AUTOGENERATED START logo-image --><img src="https://github.com/dcastil/tailwind-merge/raw/v0.8.1/assets/logo.svg" alt="tailwind-merge" width="221px" /><!-- AUTOGENERATED END -->
|
|
5
5
|
</a>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
|
|
|
19
19
|
- Supports Tailwind v2.0 up to v2.2, support for newer versions will be added continuously
|
|
20
20
|
- Works in Node >=12 and all modern browsers
|
|
21
21
|
- Fully typed
|
|
22
|
-
- [<!-- AUTOGENERATED START package-gzip-size -->4.8 kB<!-- AUTOGENERATED END --> minified + gzipped](https://bundlephobia.com/package/tailwind-merge) (<!-- AUTOGENERATED START package-composition -->96.
|
|
22
|
+
- [<!-- AUTOGENERATED START package-gzip-size -->4.8 kB<!-- AUTOGENERATED END --> minified + gzipped](https://bundlephobia.com/package/tailwind-merge) (<!-- AUTOGENERATED START package-composition -->96.5% self, 3.5% hashlru<!-- AUTOGENERATED END -->)
|
|
23
23
|
|
|
24
24
|
## Early development
|
|
25
25
|
|
|
@@ -29,7 +29,7 @@ I want to keep the library on v0 until I feel confident enough that there aren't
|
|
|
29
29
|
|
|
30
30
|
## What is it for
|
|
31
31
|
|
|
32
|
-
If you use Tailwind with a component-based UI renderer like [React](https://reactjs.org) or [Vue](https://vuejs.org), you're probably familiar with
|
|
32
|
+
If you use Tailwind with a component-based UI renderer like [React](https://reactjs.org) or [Vue](https://vuejs.org), you're probably familiar with the situation that you want to change some styles of a component, but only in one place.
|
|
33
33
|
|
|
34
34
|
```jsx
|
|
35
35
|
import React from 'react'
|
|
@@ -67,9 +67,9 @@ tailwind-merge makes sure to override conflicting classes and keeps everything e
|
|
|
67
67
|
|
|
68
68
|
### Optimized for speed
|
|
69
69
|
|
|
70
|
-
- Results get cached by default, so you don't need to worry about wasteful
|
|
71
|
-
- Expensive computations happen upfront so that `twMerge
|
|
72
|
-
- These computations are called lazily on the first call to `twMerge
|
|
70
|
+
- Results get cached by default, so you don't need to worry about wasteful re-renders. The library uses a [LRU cache](<https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)>) which stores up to 500 different results. The cache size can be modified or opt-out of by using [`extendTailwindMerge`](#extendtailwindmerge).
|
|
71
|
+
- Expensive computations happen upfront so that `twMerge` calls without a cache hit stay fast.
|
|
72
|
+
- These computations are called lazily on the first call to `twMerge` to prevent it from impacting app startup performance if it isn't used initially.
|
|
73
73
|
|
|
74
74
|
### Last conflicting class wins
|
|
75
75
|
|
|
@@ -126,10 +126,10 @@ twMerge('p-5 p-2 my-non-tailwind-class p-4') // → 'my-non-tailwind-class p-4'
|
|
|
126
126
|
twMerge('text-red text-secret-sauce') // → 'text-secret-sauce'
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
### Ignores `undefined` and `
|
|
129
|
+
### Ignores `undefined`, `null` and `false` values
|
|
130
130
|
|
|
131
131
|
```ts
|
|
132
|
-
twMerge('some-class', undefined, null) // → 'some-class'
|
|
132
|
+
twMerge('some-class', undefined, null, false) // → 'some-class'
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
## API reference
|
|
@@ -139,60 +139,215 @@ Reference to all exports of tailwind-merge.
|
|
|
139
139
|
### `twMerge`
|
|
140
140
|
|
|
141
141
|
```ts
|
|
142
|
-
function twMerge(...classLists: Array<string | undefined | null>): string
|
|
142
|
+
function twMerge(...classLists: Array<string | undefined | null | false>): string
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
Default function to use if you're using the default Tailwind config or are close enough to the default config. You can use this function if all of the following points apply to your Tailwind config:
|
|
146
146
|
|
|
147
|
-
- Only using
|
|
148
|
-
- Only using default color names or color names which don't clash with Tailwind class names
|
|
147
|
+
- Only using color names which don't clash with other Tailwind class names
|
|
149
148
|
- Only deviating by number values from number-based Tailwind classes
|
|
149
|
+
- Only using font-family classes which don't clash with default font-weight classes
|
|
150
|
+
- Sticking to default Tailwind config for everything else
|
|
150
151
|
|
|
151
|
-
If some of these points don't apply to you, it makes sense to test whether `twMerge
|
|
152
|
+
If some of these points don't apply to you, it makes sense to test whether `twMerge` still works as intended with your custom classes. Otherwise, you can create your own custom merge function with [`extendTailwindMerge`](#extendtailwindmerge).
|
|
153
|
+
|
|
154
|
+
### `getDefaultConfig`
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
function getDefaultConfig(): Config
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Function which returns the default config used by tailwind-merge. The tailwind-merge config is different from the Tailwind config. It is optimized for small bundle size and fast runtime performance because it is expected to run in the browser.
|
|
161
|
+
|
|
162
|
+
### `extendTailwindMerge`
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
function extendTailwindMerge(
|
|
166
|
+
configExtension: Partial<Config>,
|
|
167
|
+
...createConfig: Array<(config: Config) => Config>
|
|
168
|
+
): TailwindMerge
|
|
169
|
+
function extendTailwindMerge(...createConfig: Array<(config: Config) => Config>): TailwindMerge
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Function to create merge function with custom config which extends the default config. Use this if you use the default Tailwind config and just extend it in some places.
|
|
173
|
+
|
|
174
|
+
You provide it a `configExtension` object which gets [merged](#mergeconfigs) with the default config.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const customTwMerge = extendTailwindMerge({
|
|
178
|
+
cacheSize: 0, // ← Disabling cache
|
|
179
|
+
prefixes: [
|
|
180
|
+
'my-custom-prefix', // ← Adding custom prefix
|
|
181
|
+
],
|
|
182
|
+
// ↓ Here you define class groups
|
|
183
|
+
classGroups: {
|
|
184
|
+
// ↓ The `foo` key here is the class group ID
|
|
185
|
+
// ↓ Creates group of classes which have conflicting styles
|
|
186
|
+
// Classes here: foo, foo-2, bar-baz, bar-baz-1, bar-baz-2
|
|
187
|
+
foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }],
|
|
188
|
+
// ↓ Functions can also be used to match classes.
|
|
189
|
+
// Classes here: qux-auto, qux-1000, qux-1001, …
|
|
190
|
+
bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }],
|
|
191
|
+
},
|
|
192
|
+
// ↓ Here you can define additional conflicts across different groups
|
|
193
|
+
conflictingClassGroups: {
|
|
194
|
+
// ↓ ID of class group which creates a conflict with …
|
|
195
|
+
// ↓ … classes from groups with these IDs
|
|
196
|
+
foo: ['bar'],
|
|
197
|
+
},
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Additionally you can pass multiple `createConfig` functions (more to that in [`createTailwindMerge`](#createtailwindmerge)) which is convenient if you want to combine your config with third-party plugins.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const customTwMerge = extendTailwindMerge({ … }, withSomePlugin)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
If you only use plugins, you can omit the `configExtension` object as well.
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
const customTwMerge = extendTailwindMerge(withSomePlugin)
|
|
211
|
+
```
|
|
152
212
|
|
|
153
213
|
### `createTailwindMerge`
|
|
154
214
|
|
|
155
215
|
```ts
|
|
156
|
-
function createTailwindMerge(
|
|
216
|
+
function createTailwindMerge(
|
|
217
|
+
...createConfig: [() => Config, ...Array<(config: Config) => Config>]
|
|
218
|
+
): TailwindMerge
|
|
157
219
|
```
|
|
158
220
|
|
|
159
|
-
Function to create merge function with custom config.
|
|
221
|
+
Function to create merge function with custom config. Use this function instead of [`extendTailwindMerge`](#extendtailwindmerge) if you don't need the default config or want more control over the config.
|
|
160
222
|
|
|
161
223
|
You need to provide a function which resolves to the config tailwind-merge should use for the new merge function. You can either extend from the default config or create a new one from scratch.
|
|
162
224
|
|
|
163
225
|
```ts
|
|
164
|
-
// ↓ Callback passed to `createTailwindMerge
|
|
165
|
-
// `customTwMerge
|
|
166
|
-
const customTwMerge = createTailwindMerge((
|
|
226
|
+
// ↓ Callback passed to `createTailwindMerge` is called when
|
|
227
|
+
// `customTwMerge` gets called the first time.
|
|
228
|
+
const customTwMerge = createTailwindMerge(() => {
|
|
167
229
|
const defaultConfig = getDefaultConfig()
|
|
168
230
|
|
|
169
231
|
return {
|
|
170
|
-
cacheSize: 0,
|
|
171
|
-
prefixes: [
|
|
172
|
-
...defaultConfig.prefixes,
|
|
173
|
-
'my-custom-prefix', // ← Adding custom prefix
|
|
174
|
-
],
|
|
175
|
-
// ↓ Here you define class groups
|
|
232
|
+
cacheSize: 0,
|
|
233
|
+
prefixes: [...defaultConfig.prefixes, 'my-custom-prefix'],
|
|
176
234
|
classGroups: {
|
|
177
235
|
...defaultConfig.classGroups,
|
|
178
|
-
// ↓ The `foo` key here is the class group ID
|
|
179
|
-
// ↓ Creates group of classes which have conflicting styles
|
|
180
|
-
// Classes here: foo, foo-2, bar-baz, bar-baz-1, bar-baz-2
|
|
181
236
|
foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }],
|
|
182
|
-
// ↓ Another group with classes qux-auto, qux-1000, qux-1001, …
|
|
183
237
|
bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }],
|
|
184
238
|
},
|
|
185
|
-
// ↓ Here you can define additional conflicts across different groups
|
|
186
239
|
conflictingClassGroups: {
|
|
187
240
|
...defaultConfig.conflictingClassGroups,
|
|
188
|
-
// ↓ ID of class group which creates a conflict with …
|
|
189
|
-
// ↓ … classes from groups with these IDs
|
|
190
241
|
foo: ['bar'],
|
|
191
242
|
},
|
|
192
243
|
}
|
|
193
244
|
})
|
|
194
245
|
```
|
|
195
246
|
|
|
247
|
+
Same as in [`extendTailwindMerge`](#extendtailwindmerge) you can use multiple `createConfig` functions which is convenient if you want to combine your config with third-party plugins. Just keep in mind that the first `createConfig` function does not get passed any arguments, whereas the subsequent functions get each passed the config from the previous function.
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const customTwMerge = createTailwindMerge(getDefaultConfig, withSomePlugin, (config) => ({
|
|
251
|
+
// ↓ Config returned by `withSomePlugin`
|
|
252
|
+
...config,
|
|
253
|
+
classGroups: {
|
|
254
|
+
...config.classGroups,
|
|
255
|
+
mySpecialClassGroup: [{ special: ['1', '2'] }],
|
|
256
|
+
},
|
|
257
|
+
}))
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
But don't merge configs like that. Use [`mergeConfigs`](#mergeconfigs) instead.
|
|
261
|
+
|
|
262
|
+
### `mergeConfigs`
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
function mergeConfigs(baseConfig: Config, configExtension: Partial<Config>): Config
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Helper function to merge multiple config objects. Objects are merged, arrays are concatenated, scalar values are overriden and `undefined` does nothing. The function assumes that both parameters are tailwind-merge config objects and shouldn't be used as a generic merge function.
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
const customTwMerge = createTailwindMerge(getDefaultConfig, (config) =>
|
|
272
|
+
mergeConfigs(config, {
|
|
273
|
+
classGroups: {
|
|
274
|
+
// ↓ Adding new class group
|
|
275
|
+
mySpecialClassGroup: [{ special: ['1', '2'] }],
|
|
276
|
+
// ↓ Adding value to existing class group
|
|
277
|
+
animate: ['animate-magic'],
|
|
278
|
+
},
|
|
279
|
+
})
|
|
280
|
+
)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### `validators`
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
interface Validators {
|
|
287
|
+
isLength(classPart: string): boolean
|
|
288
|
+
isCustomLength(classPart: string): boolean
|
|
289
|
+
isInteger(classPart: string): boolean
|
|
290
|
+
isCustomValue(classPart: string): boolean
|
|
291
|
+
isAny(classPart: string): boolean
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
An object containing all the validators used in tailwind-merge. They are useful if you want to use a custom config with [`extendTailwindMerge`](#extendtailwindmerge) or [`createTailwindMerge`](#createtailwindmerge). E.g. the `classGroup` for padding is defined as
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
const paddingClassGroup = [{ p: [validators.isLength] }]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
A brief summary for each validator:
|
|
302
|
+
|
|
303
|
+
- `isLength` checks whether a class part is a number (`3`, `1.5`), a fraction (`3/4`), a custom length (`[3%]`, `[4px]`, `[length:var(--my-var)]`), or one of the strings `px`, `full` or `screen`.
|
|
304
|
+
- `isCustomLength` checks for custom length values (`[3%]`, `[4px]`, `[length:var(--my-var)]`).
|
|
305
|
+
- `isInteger` checks for integer values (`3`) and custom integer values (`[3]`).
|
|
306
|
+
- `isCustomValue` checks whether the class part is enclosed in brackets (`[something]`)
|
|
307
|
+
- `isAny` always returns true. Be careful with this validator as it might match unwanted classes. I use it primarily to match colors or when I'm ceertain there are no other class groups in a namespace.
|
|
308
|
+
|
|
309
|
+
### `Config`
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
interface Config { … }
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
TypeScript type for config object. Useful if you want to build a `createConfig` function but don't want to define it inline in [`extendTailwindMerge`](#extendtailwindmerge) or [`createTailwindMerge`](#createtailwindmerge).
|
|
316
|
+
|
|
317
|
+
## Writing plugins
|
|
318
|
+
|
|
319
|
+
This library supports classes of the core Tailwind library out of the box, but not classes of any plugins. But it's possible and hopefully easy to write third-party plugins for tailwind-merge. In case you want to write a plugin, I invite you to follow these steps:
|
|
320
|
+
|
|
321
|
+
- Create a package called `tailwind-merge-magic-plugin` with tailwind-merge as peer dependency which exports a function `withMagic` and replace "magic" with your plugin name.
|
|
322
|
+
- This function would be ideally a `createConfig` function which takes a config object as argument and returns the modified config object.
|
|
323
|
+
- If you create new class groups, prepend them with `magic.` (your plugin name with a dot at the end) so they don't collide with class group names from other plugins or even future class groups in tailwind-merge itself.
|
|
324
|
+
- Use the [`validators`](#validators) and [`mergeConfigs`](#mergeconfigs) from tailwind-merge to extend the config with magic.
|
|
325
|
+
|
|
326
|
+
Here is an example of how a plugin could look like:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
import { mergeConfigs, validators, Config } from 'tailwind-merge'
|
|
330
|
+
|
|
331
|
+
export function withMagic(config: Config): Config {
|
|
332
|
+
return mergeConfigs(config, {
|
|
333
|
+
classGroups: {
|
|
334
|
+
'magic.my-group': [{ magic: [validators.isLength, 'wow'] }],
|
|
335
|
+
},
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
This plugin can then be used like this:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
import { extendTailwindMerge } from 'tailwind-merge'
|
|
344
|
+
import { withMagic } from 'tailwind-merge-magic-plugin'
|
|
345
|
+
|
|
346
|
+
const twMerge = extendTailwindMerge(withMagic)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Also feel free to check out [tailwind-merge-rtl-plugin](https://github.com/vltansky/tailwind-merge-rtl-plugin) as a real example of a tailwind-merge plugin.
|
|
350
|
+
|
|
196
351
|
## Versioning
|
|
197
352
|
|
|
198
353
|
This package follows the [SemVer](https://semver.org) versioning rules. More specifically:
|
|
@@ -201,7 +356,7 @@ This package follows the [SemVer](https://semver.org) versioning rules. More spe
|
|
|
201
356
|
|
|
202
357
|
- Minor version gets incremented when additional features are added which don't break any existing API. However, a minor version update might still alter which styles are applied if you use Tailwind features not yet supported by tailwind-merge. E.g. a new Tailwind prefix `magic` gets added to this package which changes the result of `twMerge('magic:px-1 magic:p-3')` from `magic:px-1 magic:p-3` to `magic:p-3`.
|
|
203
358
|
|
|
204
|
-
- Major version gets incremented when breaking changes are introduced to the package API. E.g. the return type of `twMerge
|
|
359
|
+
- Major version gets incremented when breaking changes are introduced to the package API. E.g. the return type of `twMerge` changes.
|
|
205
360
|
|
|
206
361
|
- `alpha` releases might introduce breaking changes on any update. Whereas `beta` releases only introduce new features or bug fixes.
|
|
207
362
|
|