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 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
  ![Screen recording of optimal DX in action: using this package with Prettier as it neatly arranges each class name on a new line](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/Reduce%20typing%20strain.gif)
@@ -101,11 +119,13 @@ function MyComponent() {
101
119
 
102
120
  ## Argument Handling
103
121
 
104
- `mergeClassNames` only accepts **_non-empty string values_**, everything else like empty strings (`""`), `null`, `undefined`, numbers, objects and arrays is _ignored_. This ensures stricter and predictable output.
122
+ `mergeClassNames(...args)` accepts only the following arguments:
105
123
 
106
- ### Breaking Changes From Version 1.X.X
124
+ - **Non-empty strings** (for example: `"app"`, `"min-h-dvh"`)
107
125
 
108
- In pervious versions, arguments that were not strings were implicitly converted to strings by the JavaScript engine.
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.
@@ -1 +1 @@
1
- export declare const mergeClassNames: (...args: string[]) => string;
1
+ export declare const mergeClassNames: (...args: (string | boolean)[]) => string;
@@ -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 [strings, nonStrings] = partition(args, isTypeString);
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 strings ..." */
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 = nonStrings.map(formatGotArray).join(join);
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} non-string values: [${message}].`
89
+ `Expected all arguments to be either strings or value "false", but got ${count} invalid values: [${message}${suffix}.`
80
90
  );
81
91
  }
82
92
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-merge-class-names",
3
- "version": "3.0.4",
3
+ "version": "4.0.1",
4
4
  "description": "A straightforward utility for merging CSS class names in React + Tailwind and JavaScript projects.",
5
5
  "exports": {
6
6
  ".": {