tailwind-merge 2.3.0 → 2.4.0-dev.0a332483114bb4ab4ec002262968ced86200ae23
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 +12 -12
- package/dist/bundle-cjs.js +121 -160
- package/dist/bundle-cjs.js.map +1 -1
- package/dist/bundle-mjs.mjs +121 -160
- package/dist/bundle-mjs.mjs.map +1 -1
- package/dist/es5/bundle-cjs.js +152 -154
- package/dist/es5/bundle-cjs.js.map +1 -1
- package/dist/es5/bundle-mjs.mjs +152 -154
- package/dist/es5/bundle-mjs.mjs.map +1 -1
- package/dist/types.d.ts +192 -140
- package/package.json +15 -19
- package/src/index.ts +2 -0
- package/src/lib/{class-utils.ts → class-group-utils.ts} +15 -16
- package/src/lib/config-utils.ts +7 -9
- package/src/lib/default-config.ts +6 -7
- package/src/lib/extend-tailwind-merge.ts +3 -4
- package/src/lib/from-theme.ts +2 -2
- package/src/lib/lru-cache.ts +2 -2
- package/src/lib/merge-classlist.ts +65 -88
- package/src/lib/merge-configs.ts +10 -8
- package/src/lib/{modifier-utils.ts → parse-class-name.ts} +11 -5
- package/src/lib/tw-join.ts +1 -1
- package/src/lib/types.ts +52 -2
- package/src/lib/validators.ts +23 -53
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
<br />
|
|
5
5
|
<a href="https://github.com/dcastil/tailwind-merge">
|
|
6
|
-
<img src="https://github.com/dcastil/tailwind-merge/raw/
|
|
6
|
+
<img src="https://github.com/dcastil/tailwind-merge/raw/0a332483114bb4ab4ec002262968ced86200ae23/assets/logo.svg" alt="tailwind-merge" height="150px" />
|
|
7
7
|
</a>
|
|
8
8
|
</div>
|
|
9
9
|
|
|
@@ -25,14 +25,14 @@ twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
|
|
|
25
25
|
|
|
26
26
|
## Get started
|
|
27
27
|
|
|
28
|
-
- [What is it for](https://github.com/dcastil/tailwind-merge/tree/
|
|
29
|
-
- [When and how to use it](https://github.com/dcastil/tailwind-merge/tree/
|
|
30
|
-
- [Features](https://github.com/dcastil/tailwind-merge/tree/
|
|
31
|
-
- [Limitations](https://github.com/dcastil/tailwind-merge/tree/
|
|
32
|
-
- [Configuration](https://github.com/dcastil/tailwind-merge/tree/
|
|
33
|
-
- [Recipes](https://github.com/dcastil/tailwind-merge/tree/
|
|
34
|
-
- [API reference](https://github.com/dcastil/tailwind-merge/tree/
|
|
35
|
-
- [Writing plugins](https://github.com/dcastil/tailwind-merge/tree/
|
|
36
|
-
- [Versioning](https://github.com/dcastil/tailwind-merge/tree/
|
|
37
|
-
- [Contributing](https://github.com/dcastil/tailwind-merge/tree/
|
|
38
|
-
- [Similar packages](https://github.com/dcastil/tailwind-merge/tree/
|
|
28
|
+
- [What is it for](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/what-is-it-for.md)
|
|
29
|
+
- [When and how to use it](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/when-and-how-to-use-it.md)
|
|
30
|
+
- [Features](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/features.md)
|
|
31
|
+
- [Limitations](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/limitations.md)
|
|
32
|
+
- [Configuration](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/configuration.md)
|
|
33
|
+
- [Recipes](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/recipes.md)
|
|
34
|
+
- [API reference](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/api-reference.md)
|
|
35
|
+
- [Writing plugins](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/writing-plugins.md)
|
|
36
|
+
- [Versioning](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/versioning.md)
|
|
37
|
+
- [Contributing](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/contributing.md)
|
|
38
|
+
- [Similar packages](https://github.com/dcastil/tailwind-merge/tree/0a332483114bb4ab4ec002262968ced86200ae23/docs/similar-packages.md)
|
package/dist/bundle-cjs.js
CHANGED
|
@@ -4,33 +4,33 @@ Object.defineProperty(exports, Symbol.toStringTag, {
|
|
|
4
4
|
value: 'Module'
|
|
5
5
|
});
|
|
6
6
|
const CLASS_PART_SEPARATOR = '-';
|
|
7
|
-
|
|
7
|
+
const createClassGroupUtils = config => {
|
|
8
8
|
const classMap = createClassMap(config);
|
|
9
9
|
const {
|
|
10
10
|
conflictingClassGroups,
|
|
11
11
|
conflictingClassGroupModifiers
|
|
12
12
|
} = config;
|
|
13
|
-
|
|
13
|
+
const getClassGroupId = className => {
|
|
14
14
|
const classParts = className.split(CLASS_PART_SEPARATOR);
|
|
15
15
|
// Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and remove it from classParts.
|
|
16
16
|
if (classParts[0] === '' && classParts.length !== 1) {
|
|
17
17
|
classParts.shift();
|
|
18
18
|
}
|
|
19
19
|
return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className);
|
|
20
|
-
}
|
|
21
|
-
|
|
20
|
+
};
|
|
21
|
+
const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => {
|
|
22
22
|
const conflicts = conflictingClassGroups[classGroupId] || [];
|
|
23
23
|
if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) {
|
|
24
24
|
return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]];
|
|
25
25
|
}
|
|
26
26
|
return conflicts;
|
|
27
|
-
}
|
|
27
|
+
};
|
|
28
28
|
return {
|
|
29
29
|
getClassGroupId,
|
|
30
30
|
getConflictingClassGroupIds
|
|
31
31
|
};
|
|
32
|
-
}
|
|
33
|
-
|
|
32
|
+
};
|
|
33
|
+
const getGroupRecursive = (classParts, classPartObject) => {
|
|
34
34
|
if (classParts.length === 0) {
|
|
35
35
|
return classPartObject.classGroupId;
|
|
36
36
|
}
|
|
@@ -47,9 +47,9 @@ function getGroupRecursive(classParts, classPartObject) {
|
|
|
47
47
|
return classPartObject.validators.find(({
|
|
48
48
|
validator
|
|
49
49
|
}) => validator(classRest))?.classGroupId;
|
|
50
|
-
}
|
|
50
|
+
};
|
|
51
51
|
const arbitraryPropertyRegex = /^\[(.+)\]$/;
|
|
52
|
-
|
|
52
|
+
const getGroupIdForArbitraryProperty = className => {
|
|
53
53
|
if (arbitraryPropertyRegex.test(className)) {
|
|
54
54
|
const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1];
|
|
55
55
|
const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(':'));
|
|
@@ -58,11 +58,11 @@ function getGroupIdForArbitraryProperty(className) {
|
|
|
58
58
|
return 'arbitrary..' + property;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
}
|
|
61
|
+
};
|
|
62
62
|
/**
|
|
63
63
|
* Exported for testing only
|
|
64
64
|
*/
|
|
65
|
-
|
|
65
|
+
const createClassMap = config => {
|
|
66
66
|
const {
|
|
67
67
|
theme,
|
|
68
68
|
prefix
|
|
@@ -76,8 +76,8 @@ function createClassMap(config) {
|
|
|
76
76
|
processClassesRecursively(classGroup, classMap, classGroupId, theme);
|
|
77
77
|
});
|
|
78
78
|
return classMap;
|
|
79
|
-
}
|
|
80
|
-
|
|
79
|
+
};
|
|
80
|
+
const processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => {
|
|
81
81
|
classGroup.forEach(classDefinition => {
|
|
82
82
|
if (typeof classDefinition === 'string') {
|
|
83
83
|
const classPartObjectToEdit = classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition);
|
|
@@ -99,8 +99,8 @@ function processClassesRecursively(classGroup, classPartObject, classGroupId, th
|
|
|
99
99
|
processClassesRecursively(classGroup, getPart(classPartObject, key), classGroupId, theme);
|
|
100
100
|
});
|
|
101
101
|
});
|
|
102
|
-
}
|
|
103
|
-
|
|
102
|
+
};
|
|
103
|
+
const getPart = (classPartObject, path) => {
|
|
104
104
|
let currentClassPartObject = classPartObject;
|
|
105
105
|
path.split(CLASS_PART_SEPARATOR).forEach(pathPart => {
|
|
106
106
|
if (!currentClassPartObject.nextPart.has(pathPart)) {
|
|
@@ -112,11 +112,9 @@ function getPart(classPartObject, path) {
|
|
|
112
112
|
currentClassPartObject = currentClassPartObject.nextPart.get(pathPart);
|
|
113
113
|
});
|
|
114
114
|
return currentClassPartObject;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
function getPrefixedClassGroupEntries(classGroupEntries, prefix) {
|
|
115
|
+
};
|
|
116
|
+
const isThemeGetter = func => func.isThemeGetter;
|
|
117
|
+
const getPrefixedClassGroupEntries = (classGroupEntries, prefix) => {
|
|
120
118
|
if (!prefix) {
|
|
121
119
|
return classGroupEntries;
|
|
122
120
|
}
|
|
@@ -132,10 +130,10 @@ function getPrefixedClassGroupEntries(classGroupEntries, prefix) {
|
|
|
132
130
|
});
|
|
133
131
|
return [classGroupId, prefixedClassGroup];
|
|
134
132
|
});
|
|
135
|
-
}
|
|
133
|
+
};
|
|
136
134
|
|
|
137
135
|
// LRU cache inspired from hashlru (https://github.com/dominictarr/hashlru/blob/v1.0.4/index.js) but object replaced with Map to improve performance
|
|
138
|
-
|
|
136
|
+
const createLruCache = maxCacheSize => {
|
|
139
137
|
if (maxCacheSize < 1) {
|
|
140
138
|
return {
|
|
141
139
|
get: () => undefined,
|
|
@@ -145,7 +143,7 @@ function createLruCache(maxCacheSize) {
|
|
|
145
143
|
let cacheSize = 0;
|
|
146
144
|
let cache = new Map();
|
|
147
145
|
let previousCache = new Map();
|
|
148
|
-
|
|
146
|
+
const update = (key, value) => {
|
|
149
147
|
cache.set(key, value);
|
|
150
148
|
cacheSize++;
|
|
151
149
|
if (cacheSize > maxCacheSize) {
|
|
@@ -153,7 +151,7 @@ function createLruCache(maxCacheSize) {
|
|
|
153
151
|
previousCache = cache;
|
|
154
152
|
cache = new Map();
|
|
155
153
|
}
|
|
156
|
-
}
|
|
154
|
+
};
|
|
157
155
|
return {
|
|
158
156
|
get(key) {
|
|
159
157
|
let value = cache.get(key);
|
|
@@ -173,15 +171,18 @@ function createLruCache(maxCacheSize) {
|
|
|
173
171
|
}
|
|
174
172
|
}
|
|
175
173
|
};
|
|
176
|
-
}
|
|
174
|
+
};
|
|
177
175
|
const IMPORTANT_MODIFIER = '!';
|
|
178
|
-
|
|
179
|
-
const
|
|
176
|
+
const createParseClassName = config => {
|
|
177
|
+
const {
|
|
178
|
+
separator,
|
|
179
|
+
experimentalParseClassName
|
|
180
|
+
} = config;
|
|
180
181
|
const isSeparatorSingleCharacter = separator.length === 1;
|
|
181
182
|
const firstSeparatorCharacter = separator[0];
|
|
182
183
|
const separatorLength = separator.length;
|
|
183
|
-
//
|
|
184
|
-
|
|
184
|
+
// parseClassName inspired by https://github.com/tailwindlabs/tailwindcss/blob/v3.2.2/src/util/splitAtTopLevelOnly.js
|
|
185
|
+
const parseClassName = className => {
|
|
185
186
|
const modifiers = [];
|
|
186
187
|
let bracketDepth = 0;
|
|
187
188
|
let modifierStart = 0;
|
|
@@ -216,13 +217,20 @@ function createSplitModifiers(config) {
|
|
|
216
217
|
maybePostfixModifierPosition
|
|
217
218
|
};
|
|
218
219
|
};
|
|
219
|
-
|
|
220
|
+
if (experimentalParseClassName) {
|
|
221
|
+
return className => experimentalParseClassName({
|
|
222
|
+
className,
|
|
223
|
+
parseClassName
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return parseClassName;
|
|
227
|
+
};
|
|
220
228
|
/**
|
|
221
229
|
* Sorts modifiers according to following schema:
|
|
222
230
|
* - Predefined modifiers are sorted alphabetically
|
|
223
231
|
* - When an arbitrary variant appears, it must be preserved which modifiers are before and after it
|
|
224
232
|
*/
|
|
225
|
-
|
|
233
|
+
const sortModifiers = modifiers => {
|
|
226
234
|
if (modifiers.length <= 1) {
|
|
227
235
|
return modifiers;
|
|
228
236
|
}
|
|
@@ -239,18 +247,15 @@ function sortModifiers(modifiers) {
|
|
|
239
247
|
});
|
|
240
248
|
sortedModifiers.push(...unsortedModifiers.sort());
|
|
241
249
|
return sortedModifiers;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
const SPLIT_CLASSES_REGEX = /\s+/;
|
|
251
|
-
function mergeClassList(classList, configUtils) {
|
|
250
|
+
};
|
|
251
|
+
const createConfigUtils = config => ({
|
|
252
|
+
cache: createLruCache(config.cacheSize),
|
|
253
|
+
parseClassName: createParseClassName(config),
|
|
254
|
+
...createClassGroupUtils(config)
|
|
255
|
+
});
|
|
256
|
+
const mergeClassList = (classList, configUtils) => {
|
|
252
257
|
const {
|
|
253
|
-
|
|
258
|
+
parseClassName,
|
|
254
259
|
getClassGroupId,
|
|
255
260
|
getConflictingClassGroupIds
|
|
256
261
|
} = configUtils;
|
|
@@ -261,61 +266,51 @@ function mergeClassList(classList, configUtils) {
|
|
|
261
266
|
* @example 'hover:focus:bg-color'
|
|
262
267
|
* @example 'md:!pr'
|
|
263
268
|
*/
|
|
264
|
-
const classGroupsInConflict =
|
|
265
|
-
|
|
269
|
+
const classGroupsInConflict = [];
|
|
270
|
+
let result = '';
|
|
271
|
+
for (let i = classList.length - 1; i >= 0;) {
|
|
272
|
+
while (classList[i] === ' ') {
|
|
273
|
+
--i;
|
|
274
|
+
}
|
|
275
|
+
const nextI = classList.lastIndexOf(' ', i);
|
|
276
|
+
const originalClassName = classList.slice(nextI === -1 ? 0 : nextI + 1, i + 1);
|
|
277
|
+
i = nextI;
|
|
266
278
|
const {
|
|
267
279
|
modifiers,
|
|
268
280
|
hasImportantModifier,
|
|
269
281
|
baseClassName,
|
|
270
282
|
maybePostfixModifierPosition
|
|
271
|
-
} =
|
|
272
|
-
let classGroupId = getClassGroupId(maybePostfixModifierPosition ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName);
|
|
283
|
+
} = parseClassName(originalClassName);
|
|
273
284
|
let hasPostfixModifier = Boolean(maybePostfixModifierPosition);
|
|
285
|
+
let classGroupId = getClassGroupId(hasPostfixModifier ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName);
|
|
274
286
|
if (!classGroupId) {
|
|
275
|
-
if (!
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
originalClassName
|
|
279
|
-
};
|
|
287
|
+
if (!hasPostfixModifier) {
|
|
288
|
+
result = originalClassName + (result.length > 0 ? ' ' + result : result);
|
|
289
|
+
continue;
|
|
280
290
|
}
|
|
281
291
|
classGroupId = getClassGroupId(baseClassName);
|
|
282
292
|
if (!classGroupId) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
originalClassName
|
|
286
|
-
};
|
|
293
|
+
result = originalClassName + (result.length > 0 ? ' ' + result : result);
|
|
294
|
+
continue;
|
|
287
295
|
}
|
|
288
296
|
hasPostfixModifier = false;
|
|
289
297
|
}
|
|
290
298
|
const variantModifier = sortModifiers(modifiers).join(':');
|
|
291
299
|
const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier;
|
|
292
|
-
return {
|
|
293
|
-
isTailwindClass: true,
|
|
294
|
-
modifierId,
|
|
295
|
-
classGroupId,
|
|
296
|
-
originalClassName,
|
|
297
|
-
hasPostfixModifier
|
|
298
|
-
};
|
|
299
|
-
}).reverse()
|
|
300
|
-
// Last class in conflict wins, so we need to filter conflicting classes in reverse order.
|
|
301
|
-
.filter(parsed => {
|
|
302
|
-
if (!parsed.isTailwindClass) {
|
|
303
|
-
return true;
|
|
304
|
-
}
|
|
305
|
-
const {
|
|
306
|
-
modifierId,
|
|
307
|
-
classGroupId,
|
|
308
|
-
hasPostfixModifier
|
|
309
|
-
} = parsed;
|
|
310
300
|
const classId = modifierId + classGroupId;
|
|
311
|
-
if (classGroupsInConflict.
|
|
312
|
-
|
|
301
|
+
if (classGroupsInConflict.includes(classId)) {
|
|
302
|
+
continue;
|
|
313
303
|
}
|
|
314
|
-
classGroupsInConflict.
|
|
315
|
-
getConflictingClassGroupIds(classGroupId, hasPostfixModifier)
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
304
|
+
classGroupsInConflict.push(classId);
|
|
305
|
+
const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier);
|
|
306
|
+
for (let i = 0; i < conflictGroups.length; ++i) {
|
|
307
|
+
const group = conflictGroups[i];
|
|
308
|
+
classGroupsInConflict.push(modifierId + group);
|
|
309
|
+
}
|
|
310
|
+
result = originalClassName + (result.length > 0 ? ' ' + result : result);
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
};
|
|
319
314
|
|
|
320
315
|
/**
|
|
321
316
|
* The code in this file is copied from https://github.com/lukeed/clsx and modified to suit the needs of tailwind-merge better.
|
|
@@ -341,7 +336,7 @@ function twJoin() {
|
|
|
341
336
|
}
|
|
342
337
|
return string;
|
|
343
338
|
}
|
|
344
|
-
|
|
339
|
+
const toValue = mix => {
|
|
345
340
|
if (typeof mix === 'string') {
|
|
346
341
|
return mix;
|
|
347
342
|
}
|
|
@@ -356,7 +351,7 @@ function toValue(mix) {
|
|
|
356
351
|
}
|
|
357
352
|
}
|
|
358
353
|
return string;
|
|
359
|
-
}
|
|
354
|
+
};
|
|
360
355
|
function createTailwindMerge(createConfigFirst, ...createConfigRest) {
|
|
361
356
|
let configUtils;
|
|
362
357
|
let cacheGet;
|
|
@@ -383,11 +378,11 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
|
|
|
383
378
|
return functionToCall(twJoin.apply(null, arguments));
|
|
384
379
|
};
|
|
385
380
|
}
|
|
386
|
-
|
|
381
|
+
const fromTheme = key => {
|
|
387
382
|
const themeGetter = theme => theme[key] || [];
|
|
388
383
|
themeGetter.isThemeGetter = true;
|
|
389
384
|
return themeGetter;
|
|
390
|
-
}
|
|
385
|
+
};
|
|
391
386
|
const arbitraryValueRegex = /^\[(?:([a-z-]+):)?(.+)\]$/i;
|
|
392
387
|
const fractionRegex = /^\d+\/\d+$/;
|
|
393
388
|
const stringLengths = /*#__PURE__*/new Set(['px', 'full', 'screen']);
|
|
@@ -397,48 +392,22 @@ const colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/;
|
|
|
397
392
|
// Shadow always begins with x and y offset separated by underscore optionally prepended by inset
|
|
398
393
|
const shadowRegex = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/;
|
|
399
394
|
const imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
function isArbitraryNumber(value) {
|
|
410
|
-
return getIsArbitraryValue(value, 'number', isNumber);
|
|
411
|
-
}
|
|
412
|
-
function isInteger(value) {
|
|
413
|
-
return Boolean(value) && Number.isInteger(Number(value));
|
|
414
|
-
}
|
|
415
|
-
function isPercent(value) {
|
|
416
|
-
return value.endsWith('%') && isNumber(value.slice(0, -1));
|
|
417
|
-
}
|
|
418
|
-
function isArbitraryValue(value) {
|
|
419
|
-
return arbitraryValueRegex.test(value);
|
|
420
|
-
}
|
|
421
|
-
function isTshirtSize(value) {
|
|
422
|
-
return tshirtUnitRegex.test(value);
|
|
423
|
-
}
|
|
395
|
+
const isLength = value => isNumber(value) || stringLengths.has(value) || fractionRegex.test(value);
|
|
396
|
+
const isArbitraryLength = value => getIsArbitraryValue(value, 'length', isLengthOnly);
|
|
397
|
+
const isNumber = value => Boolean(value) && !Number.isNaN(Number(value));
|
|
398
|
+
const isArbitraryNumber = value => getIsArbitraryValue(value, 'number', isNumber);
|
|
399
|
+
const isInteger = value => Boolean(value) && Number.isInteger(Number(value));
|
|
400
|
+
const isPercent = value => value.endsWith('%') && isNumber(value.slice(0, -1));
|
|
401
|
+
const isArbitraryValue = value => arbitraryValueRegex.test(value);
|
|
402
|
+
const isTshirtSize = value => tshirtUnitRegex.test(value);
|
|
424
403
|
const sizeLabels = /*#__PURE__*/new Set(['length', 'size', 'percentage']);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
function isArbitraryPosition(value) {
|
|
429
|
-
return getIsArbitraryValue(value, 'position', isNever);
|
|
430
|
-
}
|
|
404
|
+
const isArbitrarySize = value => getIsArbitraryValue(value, sizeLabels, isNever);
|
|
405
|
+
const isArbitraryPosition = value => getIsArbitraryValue(value, 'position', isNever);
|
|
431
406
|
const imageLabels = /*#__PURE__*/new Set(['image', 'url']);
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return getIsArbitraryValue(value, '', isShadow);
|
|
437
|
-
}
|
|
438
|
-
function isAny() {
|
|
439
|
-
return true;
|
|
440
|
-
}
|
|
441
|
-
function getIsArbitraryValue(value, label, testValue) {
|
|
407
|
+
const isArbitraryImage = value => getIsArbitraryValue(value, imageLabels, isImage);
|
|
408
|
+
const isArbitraryShadow = value => getIsArbitraryValue(value, '', isShadow);
|
|
409
|
+
const isAny = () => true;
|
|
410
|
+
const getIsArbitraryValue = (value, label, testValue) => {
|
|
442
411
|
const result = arbitraryValueRegex.exec(value);
|
|
443
412
|
if (result) {
|
|
444
413
|
if (result[1]) {
|
|
@@ -447,22 +416,15 @@ function getIsArbitraryValue(value, label, testValue) {
|
|
|
447
416
|
return testValue(result[2]);
|
|
448
417
|
}
|
|
449
418
|
return false;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
function isShadow(value) {
|
|
461
|
-
return shadowRegex.test(value);
|
|
462
|
-
}
|
|
463
|
-
function isImage(value) {
|
|
464
|
-
return imageRegex.test(value);
|
|
465
|
-
}
|
|
419
|
+
};
|
|
420
|
+
const isLengthOnly = value =>
|
|
421
|
+
// `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths.
|
|
422
|
+
// For example, `hsl(0 0% 0%)` would be classified as a length without this check.
|
|
423
|
+
// I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough.
|
|
424
|
+
lengthUnitRegex.test(value) && !colorFunctionRegex.test(value);
|
|
425
|
+
const isNever = () => false;
|
|
426
|
+
const isShadow = value => shadowRegex.test(value);
|
|
427
|
+
const isImage = value => imageRegex.test(value);
|
|
466
428
|
const validators = /*#__PURE__*/Object.defineProperty({
|
|
467
429
|
__proto__: null,
|
|
468
430
|
isAny,
|
|
@@ -481,7 +443,7 @@ const validators = /*#__PURE__*/Object.defineProperty({
|
|
|
481
443
|
}, Symbol.toStringTag, {
|
|
482
444
|
value: 'Module'
|
|
483
445
|
});
|
|
484
|
-
|
|
446
|
+
const getDefaultConfig = () => {
|
|
485
447
|
const colors = fromTheme('colors');
|
|
486
448
|
const spacing = fromTheme('spacing');
|
|
487
449
|
const blur = fromTheme('blur');
|
|
@@ -519,7 +481,6 @@ function getDefaultConfig() {
|
|
|
519
481
|
const getAlign = () => ['start', 'end', 'center', 'between', 'around', 'evenly', 'stretch'];
|
|
520
482
|
const getZeroAndEmpty = () => ['', '0', isArbitraryValue];
|
|
521
483
|
const getBreaks = () => ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column'];
|
|
522
|
-
const getNumber = () => [isNumber, isArbitraryNumber];
|
|
523
484
|
const getNumberAndArbitrary = () => [isNumber, isArbitraryValue];
|
|
524
485
|
return {
|
|
525
486
|
cacheSize: 500,
|
|
@@ -528,12 +489,12 @@ function getDefaultConfig() {
|
|
|
528
489
|
colors: [isAny],
|
|
529
490
|
spacing: [isLength, isArbitraryLength],
|
|
530
491
|
blur: ['none', '', isTshirtSize, isArbitraryValue],
|
|
531
|
-
brightness:
|
|
492
|
+
brightness: getNumberAndArbitrary(),
|
|
532
493
|
borderColor: [colors],
|
|
533
494
|
borderRadius: ['none', '', 'full', isTshirtSize, isArbitraryValue],
|
|
534
495
|
borderSpacing: getSpacingWithArbitrary(),
|
|
535
496
|
borderWidth: getLengthWithEmptyAndArbitrary(),
|
|
536
|
-
contrast:
|
|
497
|
+
contrast: getNumberAndArbitrary(),
|
|
537
498
|
grayscale: getZeroAndEmpty(),
|
|
538
499
|
hueRotate: getNumberAndArbitrary(),
|
|
539
500
|
invert: getZeroAndEmpty(),
|
|
@@ -542,10 +503,10 @@ function getDefaultConfig() {
|
|
|
542
503
|
gradientColorStopPositions: [isPercent, isArbitraryLength],
|
|
543
504
|
inset: getSpacingWithAutoAndArbitrary(),
|
|
544
505
|
margin: getSpacingWithAutoAndArbitrary(),
|
|
545
|
-
opacity:
|
|
506
|
+
opacity: getNumberAndArbitrary(),
|
|
546
507
|
padding: getSpacingWithArbitrary(),
|
|
547
|
-
saturate:
|
|
548
|
-
scale:
|
|
508
|
+
saturate: getNumberAndArbitrary(),
|
|
509
|
+
scale: getNumberAndArbitrary(),
|
|
549
510
|
sepia: getZeroAndEmpty(),
|
|
550
511
|
skew: getNumberAndArbitrary(),
|
|
551
512
|
space: getSpacingWithArbitrary(),
|
|
@@ -2534,22 +2495,24 @@ function getDefaultConfig() {
|
|
|
2534
2495
|
'font-size': ['leading']
|
|
2535
2496
|
}
|
|
2536
2497
|
};
|
|
2537
|
-
}
|
|
2498
|
+
};
|
|
2538
2499
|
|
|
2539
2500
|
/**
|
|
2540
2501
|
* @param baseConfig Config where other config will be merged into. This object will be mutated.
|
|
2541
2502
|
* @param configExtension Partial config to merge into the `baseConfig`.
|
|
2542
2503
|
*/
|
|
2543
|
-
|
|
2504
|
+
const mergeConfigs = (baseConfig, {
|
|
2544
2505
|
cacheSize,
|
|
2545
2506
|
prefix,
|
|
2546
2507
|
separator,
|
|
2508
|
+
experimentalParseClassName,
|
|
2547
2509
|
extend = {},
|
|
2548
2510
|
override = {}
|
|
2549
|
-
}) {
|
|
2511
|
+
}) => {
|
|
2550
2512
|
overrideProperty(baseConfig, 'cacheSize', cacheSize);
|
|
2551
2513
|
overrideProperty(baseConfig, 'prefix', prefix);
|
|
2552
2514
|
overrideProperty(baseConfig, 'separator', separator);
|
|
2515
|
+
overrideProperty(baseConfig, 'experimentalParseClassName', experimentalParseClassName);
|
|
2553
2516
|
for (const configKey in override) {
|
|
2554
2517
|
overrideConfigProperties(baseConfig[configKey], override[configKey]);
|
|
2555
2518
|
}
|
|
@@ -2557,20 +2520,20 @@ function mergeConfigs(baseConfig, {
|
|
|
2557
2520
|
mergeConfigProperties(baseConfig[key], extend[key]);
|
|
2558
2521
|
}
|
|
2559
2522
|
return baseConfig;
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2523
|
+
};
|
|
2524
|
+
const overrideProperty = (baseObject, overrideKey, overrideValue) => {
|
|
2562
2525
|
if (overrideValue !== undefined) {
|
|
2563
2526
|
baseObject[overrideKey] = overrideValue;
|
|
2564
2527
|
}
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2528
|
+
};
|
|
2529
|
+
const overrideConfigProperties = (baseObject, overrideObject) => {
|
|
2567
2530
|
if (overrideObject) {
|
|
2568
2531
|
for (const key in overrideObject) {
|
|
2569
2532
|
overrideProperty(baseObject, key, overrideObject[key]);
|
|
2570
2533
|
}
|
|
2571
2534
|
}
|
|
2572
|
-
}
|
|
2573
|
-
|
|
2535
|
+
};
|
|
2536
|
+
const mergeConfigProperties = (baseObject, mergeObject) => {
|
|
2574
2537
|
if (mergeObject) {
|
|
2575
2538
|
for (const key in mergeObject) {
|
|
2576
2539
|
const mergeValue = mergeObject[key];
|
|
@@ -2579,10 +2542,8 @@ function mergeConfigProperties(baseObject, mergeObject) {
|
|
|
2579
2542
|
}
|
|
2580
2543
|
}
|
|
2581
2544
|
}
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
return typeof configExtension === 'function' ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig) : createTailwindMerge(() => mergeConfigs(getDefaultConfig(), configExtension), ...createConfig);
|
|
2585
|
-
}
|
|
2545
|
+
};
|
|
2546
|
+
const extendTailwindMerge = (configExtension, ...createConfig) => typeof configExtension === 'function' ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig) : createTailwindMerge(() => mergeConfigs(getDefaultConfig(), configExtension), ...createConfig);
|
|
2586
2547
|
const twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig);
|
|
2587
2548
|
exports.createTailwindMerge = createTailwindMerge;
|
|
2588
2549
|
exports.extendTailwindMerge = extendTailwindMerge;
|