simple-merge-class-names 3.0.4 → 4.0.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 +30 -6
- package/mergeClassNames.d.ts +1 -1
- package/mergeClassNames.js +14 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,14 +8,16 @@ A straightforward utility for merging CSS class names in `React + Tailwind` and
|
|
|
8
8
|
- [Install Prettier With VSCode (Most Recommended)](#install-prettier-with-vscode-most-recommended)
|
|
9
9
|
- [Usage](#usage)
|
|
10
10
|
|
|
11
|
+
- [Conditionally Include Class Names](#conditionally-include-class-names)
|
|
12
|
+
|
|
11
13
|
- [Workflow To Minimize Typing Strain](#workflow-to-minimize-typing-strain)
|
|
12
14
|
|
|
13
15
|
- [Argument Handling](#argument-handling)
|
|
14
16
|
|
|
15
|
-
- [Breaking Changes From Version 1.X.X](#breaking-changes-from-version-1xx)
|
|
16
|
-
|
|
17
17
|
- [Console Warning for Invalid Arguments](#console-warning-for-invalid-arguments)
|
|
18
18
|
|
|
19
|
+
- [Breaking Changes From Version 1.X.X](#breaking-changes-from-version-1xx)
|
|
20
|
+
|
|
19
21
|
- [Testing](#testing)
|
|
20
22
|
- [Source Code (Partial)](#source-code-partial)
|
|
21
23
|
- [Misc.](#misc)
|
|
@@ -58,7 +60,7 @@ function MyComponent() {
|
|
|
58
60
|
<div
|
|
59
61
|
className={mergeClassNames(
|
|
60
62
|
"app",
|
|
61
|
-
"min-h-dvh",
|
|
63
|
+
condition ? "min-h-dvh" : false,
|
|
62
64
|
"grid",
|
|
63
65
|
"grid-rows-[auto_1fr_auto]",
|
|
64
66
|
"outline"
|
|
@@ -82,6 +84,22 @@ function MyComponent() {
|
|
|
82
84
|
}
|
|
83
85
|
```
|
|
84
86
|
|
|
87
|
+
### Conditionally Include Class Names
|
|
88
|
+
|
|
89
|
+
To conditionally include a class, use the ternary operator like this: `condition ? 'class-name' : false` to maintain clear and warning-free code.
|
|
90
|
+
|
|
91
|
+
```jsx
|
|
92
|
+
mergeClassNames(
|
|
93
|
+
"app",
|
|
94
|
+
condition ? "min-h-dvh" : false,
|
|
95
|
+
"grid",
|
|
96
|
+
"grid-rows-[auto_1fr_auto]",
|
|
97
|
+
"outline"
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Important**: Avoid using the short-circuit implicit syntax `condition && "class-name"` because it can produce falsy values like `0`, `""`, `undefined`, `null`, which will cause warnings to be logged.
|
|
102
|
+
|
|
85
103
|
### Workflow To Minimize Typing Strain
|
|
86
104
|
|
|
87
105
|

|
|
@@ -101,11 +119,13 @@ function MyComponent() {
|
|
|
101
119
|
|
|
102
120
|
## Argument Handling
|
|
103
121
|
|
|
104
|
-
`mergeClassNames
|
|
122
|
+
`mergeClassNames(...args)` accepts only the following arguments:
|
|
105
123
|
|
|
106
|
-
|
|
124
|
+
- **Non-empty strings** (for example: `"app"`, `"min-h-dvh"`)
|
|
107
125
|
|
|
108
|
-
|
|
126
|
+
- The boolean value **`false`**
|
|
127
|
+
|
|
128
|
+
Everything else like empty strings (`""`), `null`, `undefined`, numbers, objects and arrays is _ignored_ and logged via `console.warn` to alert the user of a potentially deeper issue.
|
|
109
129
|
|
|
110
130
|
### Console Warning for Invalid Arguments
|
|
111
131
|
|
|
@@ -119,6 +139,10 @@ Example output:
|
|
|
119
139
|
- Expected 0 empty strings, but got 2.
|
|
120
140
|
```
|
|
121
141
|
|
|
142
|
+
### Breaking Changes From Version 1.X.X
|
|
143
|
+
|
|
144
|
+
In pervious versions, arguments that were not strings were implicitly converted to strings by the JavaScript engine.
|
|
145
|
+
|
|
122
146
|
## Testing
|
|
123
147
|
|
|
124
148
|
This project uses `Vitest` as the test runner for fast, modern testing.
|
package/mergeClassNames.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const mergeClassNames: (...args: string[]) => string;
|
|
1
|
+
export declare const mergeClassNames: (...args: (string | boolean)[]) => string;
|
package/mergeClassNames.js
CHANGED
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
+
const isValueFalse = (val) => val === false;
|
|
41
|
+
|
|
40
42
|
const isTypeString = (val) => typeof val === "string";
|
|
41
43
|
|
|
42
44
|
const isNonEmptyString = (val) => val !== "";
|
|
@@ -53,7 +55,9 @@ const partition = (array, keepPredicate) => {
|
|
|
53
55
|
export const mergeClassNames = (...args) => {
|
|
54
56
|
const space = "\x20"; // ASCII code for a single space character (" "), decimal 32
|
|
55
57
|
|
|
56
|
-
const [
|
|
58
|
+
const [_, nonFalseValues] = partition(args, isValueFalse); // ignore all false values used for conditional class inclusion
|
|
59
|
+
|
|
60
|
+
const [strings, nonStrings] = partition(nonFalseValues, isTypeString);
|
|
57
61
|
|
|
58
62
|
const trimmed = strings.map((val) => val.trim());
|
|
59
63
|
|
|
@@ -67,16 +71,22 @@ export const mergeClassNames = (...args) => {
|
|
|
67
71
|
/* Don't silently ignore invalid input, explicitly disclose them as it may indicate a bigger problem */
|
|
68
72
|
const warn = [];
|
|
69
73
|
|
|
70
|
-
/* "Expected all arguments to be
|
|
74
|
+
/* "Expected all arguments to be either ..." */
|
|
71
75
|
if (nonStrings.length > 0) {
|
|
72
76
|
const join = ", ";
|
|
73
77
|
const count = nonStrings.length;
|
|
78
|
+
const maxPrint = 10;
|
|
74
79
|
const formatGotArray = (element, index) =>
|
|
75
80
|
`(${index + 1}/${count}): (${element}) of type "${typeof element}"`;
|
|
76
|
-
const message =
|
|
81
|
+
const message = (
|
|
82
|
+
count > maxPrint ? nonStrings.slice(0, maxPrint) : nonStrings
|
|
83
|
+
)
|
|
84
|
+
.map(formatGotArray)
|
|
85
|
+
.join(join);
|
|
86
|
+
const suffix = count > maxPrint ? ", ... ]" : "]";
|
|
77
87
|
|
|
78
88
|
warn.push(
|
|
79
|
-
`Expected all arguments to be strings, but got ${count}
|
|
89
|
+
`Expected all arguments to be either strings or value "false", but got ${count} invalid values: [${message}${suffix}.`
|
|
80
90
|
);
|
|
81
91
|
}
|
|
82
92
|
|