tailwind-variants 3.2.1 → 3.3.0

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.
@@ -0,0 +1,147 @@
1
+ // src/internal/join-class-value.ts
2
+ var isArray = Array.isArray;
3
+ var joinClassValue = (value) => {
4
+ if (!value && value !== 0 && value !== 0n) return "";
5
+ if (typeof value === "string") return value;
6
+ if (typeof value === "number") {
7
+ if (value !== value) return "";
8
+ return "" + value;
9
+ }
10
+ if (typeof value === "bigint") return "" + value;
11
+ let result = "";
12
+ if (isArray(value)) {
13
+ const length = value.length;
14
+ for (let index = 0; index < length; index++) {
15
+ const item = value[index];
16
+ if (!item && item !== 0 && item !== 0n) continue;
17
+ const resolved = typeof item === "string" ? item : joinClassValue(item);
18
+ if (resolved) {
19
+ if (result) result += " ";
20
+ result += resolved;
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+ if (typeof value === "object") {
26
+ for (const key in value) {
27
+ if (value[key]) {
28
+ if (result) result += " ";
29
+ result += key;
30
+ }
31
+ }
32
+ }
33
+ return result;
34
+ };
35
+
36
+ // src/utils.ts
37
+ var SPACE_REGEX = /\s+/g;
38
+ var isArray2 = Array.isArray;
39
+ var removeExtraSpaces = (str) => {
40
+ if (typeof str !== "string" || !str) return str;
41
+ return str.replace(SPACE_REGEX, " ").trim();
42
+ };
43
+ var stringNeedsNormalize = (str) => {
44
+ const len = str.length;
45
+ if (len === 0) return false;
46
+ const first = str.charCodeAt(0);
47
+ const last = str.charCodeAt(len - 1);
48
+ if (first === 32 || last === 32 || first >= 9 && first <= 13 || first === 160 || last >= 9 && last <= 13 || last === 160) {
49
+ return true;
50
+ }
51
+ for (let i = 0; i < len; i++) {
52
+ const code = str.charCodeAt(i);
53
+ if (code >= 9 && code <= 13 || code === 160) return true;
54
+ if (code === 32 && i + 1 < len && str.charCodeAt(i + 1) === 32) return true;
55
+ }
56
+ return false;
57
+ };
58
+ var cx = (...classnames) => {
59
+ const result = joinClassValue(classnames);
60
+ if (!result) return void 0;
61
+ return stringNeedsNormalize(result) ? removeExtraSpaces(result) : result;
62
+ };
63
+ var falsyToString = (value) => value === false ? "false" : value === true ? "true" : value === 0 ? "0" : value;
64
+ var isEmptyObject = (obj) => {
65
+ if (!obj || typeof obj !== "object") return true;
66
+ for (const _ in obj) return false;
67
+ return true;
68
+ };
69
+ var isEqual = (obj1, obj2) => {
70
+ if (obj1 === obj2) return true;
71
+ if (!obj1 || !obj2) return false;
72
+ const record1 = obj1;
73
+ const record2 = obj2;
74
+ const keys1 = Object.keys(record1);
75
+ const keys2 = Object.keys(record2);
76
+ if (keys1.length !== keys2.length) return false;
77
+ for (let i = 0; i < keys1.length; i++) {
78
+ const key = keys1[i];
79
+ if (!keys2.includes(key)) return false;
80
+ if (record1[key] !== record2[key]) return false;
81
+ }
82
+ return true;
83
+ };
84
+ var isBoolean = (value) => value === true || value === false;
85
+ var joinObjects = (obj1, obj2) => {
86
+ const target = obj1;
87
+ for (const key in obj2) {
88
+ if (Object.hasOwn(obj2, key)) {
89
+ const val2 = obj2[key];
90
+ if (key in target) {
91
+ target[key] = cx(target[key], val2);
92
+ } else {
93
+ target[key] = val2;
94
+ }
95
+ }
96
+ }
97
+ return obj1;
98
+ };
99
+ var flat = (arr, target) => {
100
+ for (let i = 0; i < arr.length; i++) {
101
+ const el = arr[i];
102
+ if (isArray2(el)) flat(el, target);
103
+ else if (el) target.push(el);
104
+ }
105
+ };
106
+ function flatArray(arr) {
107
+ const flattened = [];
108
+ flat(arr, flattened);
109
+ return flattened;
110
+ }
111
+ var flatMergeArrays = (...arrays) => {
112
+ const result = [];
113
+ flat(arrays, result);
114
+ const filtered = [];
115
+ for (let i = 0; i < result.length; i++) {
116
+ if (result[i]) filtered.push(result[i]);
117
+ }
118
+ return filtered;
119
+ };
120
+ var mergeObjects = (obj1, obj2) => {
121
+ const record1 = obj1;
122
+ const record2 = obj2;
123
+ const result = {};
124
+ for (const key in record1) {
125
+ const val1 = record1[key];
126
+ if (key in record2) {
127
+ const val2 = record2[key];
128
+ if (isArray2(val1) || isArray2(val2)) {
129
+ result[key] = flatMergeArrays(val2, val1);
130
+ } else if (typeof val1 === "object" && typeof val2 === "object" && val1 && val2) {
131
+ result[key] = mergeObjects(val1, val2);
132
+ } else {
133
+ result[key] = val2 + " " + val1;
134
+ }
135
+ } else {
136
+ result[key] = val1;
137
+ }
138
+ }
139
+ for (const key in record2) {
140
+ if (!(key in record1)) {
141
+ result[key] = record2[key];
142
+ }
143
+ }
144
+ return result;
145
+ };
146
+
147
+ export { cx, falsyToString, flat, flatArray, flatMergeArrays, isBoolean, isEmptyObject, isEqual, joinClassValue, joinObjects, mergeObjects, removeExtraSpaces };
@@ -0,0 +1,112 @@
1
+ /** Class value accepted by the callable merger (`createMerger()`). */
2
+ type ClassNameValue = ClassNameArray | string | null | undefined | 0 | 0n | false;
3
+ type ClassNameArray = readonly ClassNameValue[];
4
+ /** Built-in merger configuration shape. */
5
+ type Config<ClassGroupIds extends string, ThemeGroupIds extends string> = ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>;
6
+ /**
7
+ * Dynamic merger config groups. When merging configs, use `override` or `extend`.
8
+ */
9
+ interface ConfigGroupsPart<ClassGroupIds extends string, ThemeGroupIds extends string> {
10
+ /**
11
+ * Theme scales used in classGroups.
12
+ *
13
+ * The keys are the same as in the Tailwind config but the values are sometimes defined more broadly.
14
+ */
15
+ theme: NoInfer<ThemeObject<ThemeGroupIds>>;
16
+ /**
17
+ * Object with groups of classes.
18
+ *
19
+ * @example
20
+ * {
21
+ * // Creates group of classes `group`, `of` and `classes`
22
+ * 'group-id': ['group', 'of', 'classes'],
23
+ * // Creates group of classes `look-at-me-other` and `look-at-me-group`.
24
+ * 'other-group': [{ 'look-at-me': ['other', 'group']}]
25
+ * }
26
+ */
27
+ classGroups: NoInfer<Record<ClassGroupIds, ClassGroup<ThemeGroupIds>>>;
28
+ /**
29
+ * Conflicting classes across groups.
30
+ *
31
+ * The key is the ID of a class group which creates a conflict, values are IDs of class groups which receive a conflict. That means if a class from from the key ID is present, all preceding classes from the values are removed.
32
+ *
33
+ * A class group ID is the key of a class group in the classGroups object.
34
+ *
35
+ * @example { gap: ['gap-x', 'gap-y'] }
36
+ */
37
+ conflictingClassGroups: NoInfer<Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>>;
38
+ /**
39
+ * Postfix modifiers conflicting with other class groups.
40
+ *
41
+ * A class group ID is the key of a class group in classGroups object.
42
+ *
43
+ * @example { 'font-size': ['leading'] }
44
+ */
45
+ conflictingClassGroupModifiers: NoInfer<Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>>;
46
+ /**
47
+ * Class group IDs which should be resolved again with their postfix modifier attached.
48
+ *
49
+ * This is needed when a slash can make the full class name belong to a different class group than the part before the slash.
50
+ *
51
+ * @example ['container-type'] // `@container-size/sidebar` should resolve differently from `@container-size`
52
+ */
53
+ postfixLookupClassGroups?: readonly NoInferString<ClassGroupIds>[];
54
+ /**
55
+ * Modifiers whose order among multiple modifiers should be preserved because their order changes which element gets targeted.
56
+ *
57
+ * Classes with these modifiers are not overwritten by peers that only differ in order-sensitive modifier position.
58
+ */
59
+ orderSensitiveModifiers: string[];
60
+ }
61
+ type ThemeObject<ThemeGroupIds extends string> = Record<ThemeGroupIds, ClassGroup<ThemeGroupIds>>;
62
+ type ClassGroup<ThemeGroupIds extends string> = readonly ClassDefinition<ThemeGroupIds>[];
63
+ type ClassDefinition<ThemeGroupIds extends string> = string | ClassValidator | ThemeGetter | ClassObject<ThemeGroupIds>;
64
+ type ClassValidator = (classPart: string) => boolean;
65
+ interface ThemeGetter {
66
+ (theme: ThemeObject<AnyThemeGroupIds>): ClassGroup<AnyClassGroupIds>;
67
+ isThemeGetter: true;
68
+ }
69
+ type ClassObject<ThemeGroupIds extends string> = Record<string, readonly ClassDefinition<ThemeGroupIds>[]>;
70
+ /**
71
+ * Hack from https://stackoverflow.com/questions/56687668/a-way-to-disable-type-argument-inference-in-generics/56688073#56688073
72
+ *
73
+ * Could be replaced with NoInfer utility type from TypeScript (https://www.typescriptlang.org/docs/handbook/utility-types.html#noinfertype), but that is only supported in TypeScript 5.4 or higher, so I should wait some time before using it.
74
+ */
75
+ type NoInfer<T> = [T][T extends unknown ? 0 : never];
76
+ /**
77
+ * Special-purpose NoInfer variant for string unions used in array item positions.
78
+ *
79
+ * The NoInfer helper above doesn't prevent inference from array items in all cases, so this keeps
80
+ * config arrays like `postfixLookupClassGroups` from defining or narrowing class group IDs.
81
+ * Prefer TypeScript's built-in `NoInfer` when the minimum supported version is 5.4+.
82
+ */
83
+ type NoInferString<T extends string> = T extends infer S ? S & string : never;
84
+ type AnyClassGroupIds = string;
85
+ type AnyThemeGroupIds = string;
86
+ /** Merger config with unrestricted class-group and theme-group IDs. */
87
+ type AnyConfig = Config<AnyClassGroupIds, AnyThemeGroupIds>;
88
+ /** Merger config: `override` replaces class groups, `extend` appends to them. */
89
+ interface ConfigExtension {
90
+ override?: Partial<AnyConfig>;
91
+ extend?: Partial<AnyConfig>;
92
+ }
93
+
94
+ /** Merger config for the built-in Tailwind conflict resolver. */
95
+ type TWMergeConfig = ConfigExtension & Partial<AnyConfig> & {
96
+ extend?: Partial<AnyConfig>;
97
+ override?: Partial<AnyConfig>;
98
+ };
99
+ type TWMConfig = {
100
+ /**
101
+ * Whether to merge conflicting Tailwind classes.
102
+ * @default true
103
+ */
104
+ twMerge?: boolean;
105
+ /**
106
+ * Custom merger config (`extend` / `override`, or legacy flat fields).
107
+ */
108
+ twMergeConfig?: TWMergeConfig;
109
+ };
110
+ type TVConfig = TWMConfig;
111
+
112
+ export type { ClassNameValue as C, TWMConfig as T, TVConfig as a, TWMergeConfig as b };
@@ -0,0 +1,112 @@
1
+ /** Class value accepted by the callable merger (`createMerger()`). */
2
+ type ClassNameValue = ClassNameArray | string | null | undefined | 0 | 0n | false;
3
+ type ClassNameArray = readonly ClassNameValue[];
4
+ /** Built-in merger configuration shape. */
5
+ type Config<ClassGroupIds extends string, ThemeGroupIds extends string> = ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>;
6
+ /**
7
+ * Dynamic merger config groups. When merging configs, use `override` or `extend`.
8
+ */
9
+ interface ConfigGroupsPart<ClassGroupIds extends string, ThemeGroupIds extends string> {
10
+ /**
11
+ * Theme scales used in classGroups.
12
+ *
13
+ * The keys are the same as in the Tailwind config but the values are sometimes defined more broadly.
14
+ */
15
+ theme: NoInfer<ThemeObject<ThemeGroupIds>>;
16
+ /**
17
+ * Object with groups of classes.
18
+ *
19
+ * @example
20
+ * {
21
+ * // Creates group of classes `group`, `of` and `classes`
22
+ * 'group-id': ['group', 'of', 'classes'],
23
+ * // Creates group of classes `look-at-me-other` and `look-at-me-group`.
24
+ * 'other-group': [{ 'look-at-me': ['other', 'group']}]
25
+ * }
26
+ */
27
+ classGroups: NoInfer<Record<ClassGroupIds, ClassGroup<ThemeGroupIds>>>;
28
+ /**
29
+ * Conflicting classes across groups.
30
+ *
31
+ * The key is the ID of a class group which creates a conflict, values are IDs of class groups which receive a conflict. That means if a class from from the key ID is present, all preceding classes from the values are removed.
32
+ *
33
+ * A class group ID is the key of a class group in the classGroups object.
34
+ *
35
+ * @example { gap: ['gap-x', 'gap-y'] }
36
+ */
37
+ conflictingClassGroups: NoInfer<Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>>;
38
+ /**
39
+ * Postfix modifiers conflicting with other class groups.
40
+ *
41
+ * A class group ID is the key of a class group in classGroups object.
42
+ *
43
+ * @example { 'font-size': ['leading'] }
44
+ */
45
+ conflictingClassGroupModifiers: NoInfer<Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>>;
46
+ /**
47
+ * Class group IDs which should be resolved again with their postfix modifier attached.
48
+ *
49
+ * This is needed when a slash can make the full class name belong to a different class group than the part before the slash.
50
+ *
51
+ * @example ['container-type'] // `@container-size/sidebar` should resolve differently from `@container-size`
52
+ */
53
+ postfixLookupClassGroups?: readonly NoInferString<ClassGroupIds>[];
54
+ /**
55
+ * Modifiers whose order among multiple modifiers should be preserved because their order changes which element gets targeted.
56
+ *
57
+ * Classes with these modifiers are not overwritten by peers that only differ in order-sensitive modifier position.
58
+ */
59
+ orderSensitiveModifiers: string[];
60
+ }
61
+ type ThemeObject<ThemeGroupIds extends string> = Record<ThemeGroupIds, ClassGroup<ThemeGroupIds>>;
62
+ type ClassGroup<ThemeGroupIds extends string> = readonly ClassDefinition<ThemeGroupIds>[];
63
+ type ClassDefinition<ThemeGroupIds extends string> = string | ClassValidator | ThemeGetter | ClassObject<ThemeGroupIds>;
64
+ type ClassValidator = (classPart: string) => boolean;
65
+ interface ThemeGetter {
66
+ (theme: ThemeObject<AnyThemeGroupIds>): ClassGroup<AnyClassGroupIds>;
67
+ isThemeGetter: true;
68
+ }
69
+ type ClassObject<ThemeGroupIds extends string> = Record<string, readonly ClassDefinition<ThemeGroupIds>[]>;
70
+ /**
71
+ * Hack from https://stackoverflow.com/questions/56687668/a-way-to-disable-type-argument-inference-in-generics/56688073#56688073
72
+ *
73
+ * Could be replaced with NoInfer utility type from TypeScript (https://www.typescriptlang.org/docs/handbook/utility-types.html#noinfertype), but that is only supported in TypeScript 5.4 or higher, so I should wait some time before using it.
74
+ */
75
+ type NoInfer<T> = [T][T extends unknown ? 0 : never];
76
+ /**
77
+ * Special-purpose NoInfer variant for string unions used in array item positions.
78
+ *
79
+ * The NoInfer helper above doesn't prevent inference from array items in all cases, so this keeps
80
+ * config arrays like `postfixLookupClassGroups` from defining or narrowing class group IDs.
81
+ * Prefer TypeScript's built-in `NoInfer` when the minimum supported version is 5.4+.
82
+ */
83
+ type NoInferString<T extends string> = T extends infer S ? S & string : never;
84
+ type AnyClassGroupIds = string;
85
+ type AnyThemeGroupIds = string;
86
+ /** Merger config with unrestricted class-group and theme-group IDs. */
87
+ type AnyConfig = Config<AnyClassGroupIds, AnyThemeGroupIds>;
88
+ /** Merger config: `override` replaces class groups, `extend` appends to them. */
89
+ interface ConfigExtension {
90
+ override?: Partial<AnyConfig>;
91
+ extend?: Partial<AnyConfig>;
92
+ }
93
+
94
+ /** Merger config for the built-in Tailwind conflict resolver. */
95
+ type TWMergeConfig = ConfigExtension & Partial<AnyConfig> & {
96
+ extend?: Partial<AnyConfig>;
97
+ override?: Partial<AnyConfig>;
98
+ };
99
+ type TWMConfig = {
100
+ /**
101
+ * Whether to merge conflicting Tailwind classes.
102
+ * @default true
103
+ */
104
+ twMerge?: boolean;
105
+ /**
106
+ * Custom merger config (`extend` / `override`, or legacy flat fields).
107
+ */
108
+ twMergeConfig?: TWMergeConfig;
109
+ };
110
+ type TVConfig = TWMConfig;
111
+
112
+ export type { ClassNameValue as C, TWMConfig as T, TVConfig as a, TWMergeConfig as b };
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+
@@ -0,0 +1 @@
1
+ export { a as TVConfig, T as TWMConfig, b as TWMergeConfig } from './config-bO3A8WhU.cjs';
package/dist/config.d.ts CHANGED
@@ -1,23 +1 @@
1
- import type {extendTailwindMerge} from "tailwind-merge";
2
-
3
- type MergeConfig = Parameters<typeof extendTailwindMerge>[0];
4
- type LegacyMergeConfig = Extract<MergeConfig, {extend?: unknown}>["extend"];
5
-
6
- export type TWMergeConfig = MergeConfig & LegacyMergeConfig;
7
-
8
- export type TWMConfig = {
9
- /**
10
- * Whether to merge the class names with `tailwind-merge` library.
11
- * It's avoid to have duplicate tailwind classes. (Recommended)
12
- * @see https://github.com/dcastil/tailwind-merge/blob/v2.2.0/README.md
13
- * @default true
14
- */
15
- twMerge?: boolean;
16
- /**
17
- * The config object for `tailwind-merge` library.
18
- * @see https://github.com/dcastil/tailwind-merge/blob/v2.2.0/docs/configuration.md
19
- */
20
- twMergeConfig?: TWMergeConfig;
21
- };
22
-
23
- export type TVConfig = TWMConfig;
1
+ export { a as TVConfig, T as TWMConfig, b as TWMergeConfig } from './config-bO3A8WhU.js';
package/dist/config.js ADDED
@@ -0,0 +1 @@
1
+