simple-merge-class-names 7.0.2 → 8.0.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.
package/README.md CHANGED
@@ -1,73 +1,84 @@
1
1
  # simple-merge-class-names
2
2
 
3
- A straightforward utility for merging CSS class names in _React (JSX)_ and other _JavaScript_ projects.
3
+ A class names merger for TypeScript, JavaScript, TSX / JSX (React).
4
4
 
5
- For Production look into [https://www.npmjs.com/package/clsx](https://www.npmjs.com/package/clsx)
5
+ > For production purposes there is also [https://www.npmjs.com/package/clsx](https://www.npmjs.com/package/clsx)
6
6
 
7
7
  ## Table of Contents
8
8
 
9
- - [simple-merge-class-names](#simple-merge-class-names)
10
- - [Table of Contents](#table-of-contents)
11
- - [The Genocidal Occupation Is Starving Gaza](#the-genocidal-occupation-is-starving-gaza)
12
- - [Installation](#installation)
13
- - [_Recommended If Using VSCode: Install `Prettier` Extension_](#recommended-if-using-vscode-install-prettier-extension)
14
- - [Usage](#usage)
15
- - [TypeScript Definitions](#typescript-definitions)
16
- - [Valid Arguments](#valid-arguments)
17
- - [Invalid Arguments](#invalid-arguments)
18
- - [Reason for warnings](#reason-for-warnings)
19
- - [Conditional class inclusion](#conditional-class-inclusion)
20
- - [Return Result](#return-result)
21
- - [Chaining](#chaining)
22
- - [Usage of Browser Debugger](#usage-of-browser-debugger)
23
- - [VSCode Workflow To Minimize Typing Strain](#vscode-workflow-to-minimize-typing-strain)
24
- - [Testing Source Code](#testing-source-code)
25
- - [Run Once](#run-once)
26
- - [Run Watch Mode](#run-watch-mode)
27
- - [License](#license)
28
-
29
- ## The Genocidal Occupation Is Starving Gaza
30
-
31
- - [Donate](https://gazafunds.com/)
32
-
33
- - [(US) Demand Immediate Opening of ALL Gaza Border Crossings](https://act.uscpr.org/a/letaidin)
34
-
35
- - [Boycott Brands Supporting Gaza Holocaust](https://www.uplift.ie/bds/)
36
-
37
- - [Legal Action](https://www.hindrajabfoundation.org/perpetrators)
38
-
39
- _Palestine is about fundamental non-negotiable human rights. End all financial and diplomatic ties with i\*rael_.
40
-
41
- ## Installation
9
+ - [simple-merge-class-names](#simple-merge-class-names)
10
+ - [Table of Contents](#table-of-contents)
11
+ - [Stop Starving Gaza](#stop-starving-gaza)
12
+ - [Install](#install)
13
+ - [Install `Prettier` too](#install-prettier-too)
14
+ - [Exported Functions](#exported-functions)
15
+ - [Non-scale Usage](#non-scale-usage)
16
+ - [Example](#example)
17
+ - [Scale Usage](#scale-usage)
18
+ - [Create intermediary `@/mergeClassNames.js`](#create-intermediary-mergeclassnamesjs)
19
+ - [Project Structure](#project-structure)
20
+ - [Enable `@`-style Imports in Vite](#enable--style-imports-in-vite)
21
+ - [Example](#example-1)
22
+ - [During Dev, Debug Entire Project](#during-dev-debug-entire-project)
23
+ - [Valid Arguments](#valid-arguments)
24
+ - [Example](#example-2)
25
+ - [Invalid Arguments](#invalid-arguments)
26
+ - [Example](#example-3)
27
+ - [Developer Console Warnings](#developer-console-warnings)
28
+ - [Conditional Class Inclusion](#conditional-class-inclusion)
29
+ - [Avoid Short-circuit Syntax](#avoid-short-circuit-syntax)
30
+ - [Return Result](#return-result)
31
+ - [Example](#example-4)
32
+ - [Side Effect](#side-effect)
33
+ - [Example](#example-5)
34
+ - [Chaining](#chaining)
35
+ - [Usage of Browser Debugger](#usage-of-browser-debugger)
36
+ - [Testing Source Code](#testing-source-code)
37
+ - [Run Once](#run-once)
38
+ - [Run Watch Mode](#run-watch-mode)
39
+ - [License](#license)
40
+
41
+ ## Stop Starving Gaza
42
+
43
+ - [Donate Direct Aid to Gazan Families](https://gazafunds.com/)
44
+
45
+ - [Call US Congress and Demand Immediate Opening of ALL Gaza Border Crossings](https://act.uscpr.org/a/letaidin)
46
+
47
+ - [Boycott Brands Supporting Gaza Holocaust](https://www.uplift.ie/bds/)
48
+
49
+ - [Legal Action](https://www.hindrajabfoundation.org/perpetrators)
50
+
51
+ ## Install
42
52
 
43
53
  ```bash
44
54
  pnpm add simple-merge-class-names
45
- ```
46
55
 
47
- ```bash
56
+ # or
48
57
  yarn add simple-merge-class-names
49
- ```
50
58
 
51
- ```bash
59
+ # or
52
60
  npm install simple-merge-class-names
53
61
  ```
54
62
 
55
- ### _Recommended If Using VSCode: Install `Prettier` Extension_
63
+ ### Install `Prettier` too
64
+
65
+ [https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
56
66
 
57
- - _[https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)_
67
+ It will nicely format and split your classes across new lines, and alleviate wrist strain because you will use single quotes (single key) instead of double (2 keys).
58
68
 
59
- _It will nicely format your code especially when you have lots of classes, and will significantly improve your visual experience._
69
+ ## Exported Functions
60
70
 
61
- _If you have a different IDE use an equivalent auto code formatter tool/extension_
71
+ | | `console.warn`s | Invokes JS `debugger;` statement on invalid arguments, which pauses execution when Debugger is attached |
72
+ | ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
73
+ | `mergeClassNames` | ✅ | ❌ |
74
+ | `mergeClassNamesDebugger` | ✅ | ✅ |
62
75
 
63
- ## Usage
76
+ ## Non-scale Usage
64
77
 
65
- | Function | Prints console warnings | Activates debugger |
66
- | ------------------------- | ----------------------- | ------------------ |
67
- | `mergeClassNames` | ✅ | ❌ |
68
- | `mergeClassNamesDebugger` | ✅ | ✅ |
78
+ ### Example
69
79
 
70
80
  ```jsx
81
+ // src/App.jsx
71
82
  import { mergeClassNames } from "simple-merge-class-names";
72
83
 
73
84
  const Component = ({ condition }) => {
@@ -78,7 +89,7 @@ const Component = ({ condition }) => {
78
89
  condition ? "min-h-dvh" : false,
79
90
  "grid",
80
91
  "grid-rows-[auto_1fr_auto]",
81
- "outline"
92
+ "outline",
82
93
  )}
83
94
  >
84
95
  Hello, world!
@@ -87,32 +98,106 @@ const Component = ({ condition }) => {
87
98
  };
88
99
  ```
89
100
 
90
- ### TypeScript Definitions
101
+ ## Scale Usage
102
+
103
+ ![diagram explanation of best way to use package](./.github/images/root-file.png)
104
+
105
+ ### Create intermediary `@/mergeClassNames.js`
106
+
107
+ #### Project Structure
108
+
109
+ ```
110
+ my-react-app/
111
+ ├─ src/
112
+ │ ├─ components/
113
+ │ ├─ mergeClassNames.js // <- create it here
114
+ │ ├─ App.jsx
115
+ │ └─ index.js
116
+ ├─ package.json
117
+ ├─ vite.config.js
118
+ └─ README.md
119
+ ```
120
+
121
+ #### Enable `@`-style Imports in Vite
122
+
123
+ `@` points to `my-react-app/src`
124
+
125
+ ```js
126
+ // vite.config.js
127
+
128
+ import { defineConfig } from "vite";
129
+ import react from "@vitejs/plugin-react";
130
+ import tailwindcss from "@tailwindcss/vite";
131
+ import path from "path";
91
132
 
92
- ```ts
93
- export declare const mergeClassNames: (
94
- ...args: (string | false)[]
95
- ) => string | false;
133
+ // https://vitejs.dev/config/
134
+ export default defineConfig({
135
+ plugins: [react(), tailwindcss()],
96
136
 
97
- export declare const mergeClassNamesDebugger: (
98
- ...args: (string | false)[]
99
- ) => string | false;
137
+ resolve: {
138
+ alias: {
139
+ "@": path.resolve(__dirname, "src"), // @ now points to "my-react-app/src"
140
+ },
141
+ },
142
+ });
100
143
  ```
101
144
 
102
- ### Valid Arguments
145
+ ```js
146
+ // src/mergeClassNames.js
103
147
 
104
- Only 2:
148
+ export { mergeClassNames } from "simple-merge-class-names";
105
149
 
106
- 1. **Valid strings, not whitespace, of length >= 1**
150
+ // export { mergeClassNames as mergeClassNamesDebugger } from "simple-merge-class-names";
151
+ ```
107
152
 
108
- _(As long as you have content in the string you're OK)_
153
+ And toggle-comment between the first and second lines as needed.
109
154
 
110
- 2. **`false`**
155
+ ### Example
111
156
 
112
- _Example, This is OK:_
157
+ #### During Dev, Debug Entire Project
158
+
159
+ ```js
160
+ // @/mergeClassNames.js
161
+
162
+ // export { mergeClassNames } from "simple-merge-class-names";
163
+
164
+ export { mergeClassNames as mergeClassNamesDebugger } from "simple-merge-class-names";
165
+ ```
166
+
167
+ ```jsx
168
+ // @/App.jsx
169
+
170
+ import { mergeClassNames } from "@/mergeClassNames.js";
171
+
172
+ const Component = ({ condition }) => {
173
+ return (
174
+ <div
175
+ className={mergeClassNames(
176
+ "app",
177
+ condition ? "min-h-dvh" : false,
178
+ "grid",
179
+ "grid-rows-[auto_1fr_auto]",
180
+ "outline",
181
+ )}
182
+ >
183
+ Hello, world!
184
+ </div>
185
+ );
186
+ };
187
+ ```
188
+
189
+ ## Valid Arguments
190
+
191
+ Only 2:
192
+
193
+ 1. A valid string (not empty, not fully whitespace)
194
+ 2. Value `false`
195
+
196
+ ### Example
113
197
 
114
198
  ```js
115
199
  mergeClassNames(
200
+ condition ? "daisy-btn-active" : false
116
201
  "mx-auto",
117
202
  "min-dvh ",
118
203
  " flex",
@@ -121,101 +206,119 @@ mergeClassNames(
121
206
  `
122
207
  gap-y-4
123
208
  `,
124
- false,
125
- condition ? "daisy-btn-active" : false
126
209
  );
127
210
  ```
128
211
 
129
- ### Invalid Arguments
212
+ ## Invalid Arguments
130
213
 
131
- Each below argument will be **ignored**, and cause a Dev Console **warning to be printed** to alert you:
214
+ Anything that is not a valid argument, this includes:
132
215
 
133
- - **Empty strings**: _(e.g. `""`)_
134
- - **Whitespace** any consecutive combination of the following:
135
- - new lines,
136
- - spaces,
137
- - tabs
138
- - _(e.g._ `" "`, `"\n "`, `" \t \n "`, _etc.)_
139
- - **`true`**
140
- - **`undefined`**
141
- - **`null`**
142
- - **Objects**
143
- - **Numbers**
144
- - **Big Int**
145
- - **Symbols**
216
+ - Invalid strings:
217
+ - Empty strings: _(`""`)_
218
+ - Fully whitespace strings: any consecutive combination of the following:
219
+ - new lines,
220
+ - spaces,
221
+ - tabs
222
+ - _(e.g. `" "`, `"\n "`, `" \t \n "`, etc.)_
223
+ - `true`
224
+ - `undefined`
225
+ - `null`
226
+ - Objects
227
+ - Numbers
228
+ - Big Int
229
+ - Symbols
146
230
 
147
- ```js
148
- // Example: These arguments will be **ignored**, and a console.warn will be printed
231
+ _All of above will be **ignored**, and cause a `console.warn` to be printed_
149
232
 
233
+ ### Example
234
+
235
+ ```js
150
236
  const someVariable = "";
151
237
 
152
238
  mergeClassNames(
153
- someVariable, // empty string
154
- " ", // whitespace
155
- "\n ", // whitespace
156
- " \t \n ", // whitespace
157
- ` // whitespace
239
+ someVariable,
240
+ " ",
241
+ "\n ",
242
+ " \t \n ",
243
+ `
158
244
  \n
159
245
  `,
160
- true, // true
161
- undefined, // undefined
162
- null, // null
246
+ true,
247
+ undefined,
248
+ null,
163
249
  {
164
- // object
165
- name: "value",
166
- email: "email@example.com",
250
+ name: "name",
251
+ email: "name@example.com",
167
252
  },
168
- 123, // number
169
- 123.45 // number
253
+ 123,
254
+ 123.45,
170
255
  );
171
256
  ```
172
257
 
258
+ #### Developer Console Warnings
259
+
173
260
  ![screenshot of console.warn warnings because invalid arguments were provided and ignored, so no silent failing](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/console-warnings.png)
174
261
 
175
- ### Reason for warnings
262
+ ## Conditional Class Inclusion
263
+
264
+ ```jsx
265
+ mergeClassNames(condition ? "min-h-dvh" : false);
176
266
 
177
- - To avoid silent failures, because you will be pulling your hair asking why a Tailwind class isn't working only to figure out you passed an _object_, _array_ or an _empty string_ instead of a valid string. _(It could also be because of an unsupported class name or typo but this is beyond the scope of this package)_
267
+ // or if you want preciseness.
268
+ mergeClassNames(condition === true ? "min-h-dvh" : false);
269
+ ```
178
270
 
179
- ### Conditional class inclusion
271
+ ### Avoid Short-circuit Syntax
180
272
 
181
- Use this pattern:
273
+ Avoid the syntax (`condition && "class-name"`) because it can produce falsy values (e.g. `0`, `""`, `undefined`, `null`) which will be ignored and warned about.
182
274
 
183
- - `condition ? "class-name" : false` with `false` serving as the valid fallback.
184
- - _or_ `condition === true ? "class-name" : false` if you want to be specific.
275
+ ## Return Result
185
276
 
186
- _Note:_ Avoid using the _short-circuit implicit syntax_ like this:
277
+ String of all merged valid classes. Invalid arguments are ignored and warned about.
187
278
 
188
- - `condition && "class-name"`, beside less readable code, it can produce _falsy_ values which will be **_ignored_** _(e.g. `0`, `""`, `undefined`, and `null`)_.
279
+ ### Example
189
280
 
190
281
  ```jsx
191
282
  import { mergeClassNames } from "simple-merge-class-names";
192
283
 
193
- const Component = () => {
194
- return (
195
- <div
196
- className={mergeClassNames(
197
- "app",
198
- condition ? "min-h-dvh" : false,
199
- "grid",
200
- "grid-rows-[auto_1fr_auto]",
201
- "outline"
202
- )}
203
- >
204
- Hello, world!
205
- </div>
206
- );
207
- };
284
+ // "app min-h-dvh grid grid-rows-[auto_1fr_auto] outline"
285
+ mergeClassNames(
286
+ " app ",
287
+ undefined,
288
+ [" test "],
289
+ { key: "value" },
290
+ "",
291
+ "min-h-dvh",
292
+ "grid ",
293
+ true,
294
+ null,
295
+ "grid-rows-[auto_1fr_auto]",
296
+ "outline",
297
+ " ",
298
+ );
208
299
  ```
209
300
 
210
- ### Return Result
301
+ ## Side Effect
211
302
 
212
- Either:
303
+ `console.warn`s if arguments contain invalid arguments.
213
304
 
214
- 1. **Valid `string`, never whitespace, always length >= 1**
305
+ ### Example
215
306
 
216
- 2. _or_ **`false`** _(if all input arguments were invalid)_
307
+ ```
308
+ Ignored invalid argument: >undefined< (undefined)
309
+ Ignored invalid argument: > test < (object)
310
+ Ignored invalid argument: >[object Object]< (object)
311
+ Ignored empty string: ""
312
+ Ignored invalid argument: >true< (boolean)
313
+ Ignored invalid argument: >null< (object)
314
+ Ignored whitespace string:
315
+ ```
316
+
317
+ > _It can be empy_
318
+
319
+ 1. **Valid `string`, never whitespace, always length >= 1**
217
320
 
218
- ### Chaining
321
+ ## Chaining
219
322
 
220
323
  Because of safe return types you can chain calls safely without worrying about warnings or arguments being ignored.
221
324
 
@@ -227,90 +330,45 @@ mergeClassNames(condition ? "disabled" : mergeClassNames(...) )
227
330
 
228
331
  ## Usage of Browser Debugger
229
332
 
230
- **Once you see warnings in the console, the next step is to use `mergeClassNamesDebugger`**
333
+ 1. Use **`import {mergeClassNamesDebugger as mergeClassNames}`** to debug the entire file.
231
334
 
232
- 1. Enable Debugger
335
+ ```jsx
336
+ import { mergeClassNamesDebugger as mergeClassNames } from "simple-merge-class-names";
337
+
338
+ const Component = ({ condition }) => {
339
+ return (
340
+ <div
341
+ className={mergeClassNames(
342
+ "app",
343
+ condition ? "min-h-dvh" : false,
344
+ "grid",
345
+ "grid-rows-[auto_1fr_auto]",
346
+ "outline",
347
+ )}
348
+ >
349
+ Hello, world!
350
+ </div>
351
+ );
352
+ };
353
+ ```
354
+
355
+ 2. Enable Debugger
233
356
  - _For chromium-based browsers it's On by default and you don't need to do anything AFAIK._
234
357
  - _For Firefox:_ Open **_Developer Tools_:**
235
358
  - _Make Sure_ **_Debugger_** _(tab)_ -> **`Pause on debugger statement`** is ticked.
236
359
  - Keep Dev Tools open.
237
- ![screenshot of Firefox Debugger section with Pause on debugger statement ticked on](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-check.png)
238
-
239
- - Use **`import {mergeClassNamesDebugger as mergeClassNames}`** to debug the entire file, and keep the rest intact.
240
-
241
- ```jsx
242
- import { mergeClassNamesDebugger as mergeClassNames } from "simple-merge-class-names";
243
-
244
- const Component = ({ condition }) => {
245
- return (
246
- <div
247
- className={mergeClassNames(
248
- "app",
249
- condition ? "min-h-dvh" : false,
250
- "grid",
251
- "grid-rows-[auto_1fr_auto]",
252
- "outline"
253
- )}
254
- >
255
- Hello, world!
256
- </div>
257
- );
258
- };
259
- ```
260
-
261
- - or call `mergeClassNamesDebugger` directly.
262
-
263
- ```jsx
264
- import { mergeClassNamesDebugger } from "simple-merge-class-names";
265
-
266
- const Component = ({ condition }) => {
267
- return (
268
- <div
269
- className={mergeClassNamesDebugger(
270
- "app",
271
- condition ? "min-h-dvh" : false,
272
- "grid",
273
- "grid-rows-[auto_1fr_auto]",
274
- "outline"
275
- )}
276
- >
277
- Hello, world!
278
- </div>
279
- );
280
- };
281
- ```
282
-
283
- - Refresh the page, the debugger should connect:
284
-
285
- - Navigate to the **_Call stack_**
286
- - Click the function/component right before _`mergeClassNamesDebugger`_
287
-
288
- ![screenshot of Firefox debugger active because of `undefined` invalid class name argument](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-active.png)
289
-
290
- - Hover over the arguments, one or several should be invalid:
291
- ![screenshot of Firefox debugger active because of `undefined` invalid class name argument](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-3.png)
292
-
293
- ## VSCode Workflow To Minimize Typing Strain
294
-
295
- Use single quotes around class names, and activate `Prettier` which will neatly format and arrange the classes.
296
-
297
- - Install `Prettier`
298
- - Enable `Editor: Word Wrap`:
299
-
300
- - Open `Settings (UI)` → `Editor: Word Wrap` → `on`
301
- - _or_ `User Settings (JSON)` and add this entry `"editor.wordWrap": "on"`
302
360
 
303
- - Use single quotes (<kbd>'</kbd>) around class names
304
- - Save the file
361
+ ![screenshot of Firefox Debugger section with Pause on debugger statement ticked on](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-check.png)
305
362
 
306
- Example:
363
+ 3. Refresh the page, the debugger should connect:
364
+ - Navigate to the **_Call stack_**
365
+ - Click the function/component right before _`mergeClassNamesDebugger`_
307
366
 
308
- - Before
309
- ![Screenshot of code before Prettier neatly formats code](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/before.png)
367
+ ![screenshot of Firefox debugger active because of `undefined` invalid class name argument](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-active.png)
310
368
 
311
- - After
369
+ 4. Hover over the arguments, one or several should be invalid:
312
370
 
313
- ![Screenshot of code after Prettier neatly formats code](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/after.png)
371
+ ![screenshot of Firefox debugger active because of `undefined` invalid class name argument](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/debugger-3.png)
314
372
 
315
373
  ## Testing Source Code
316
374
 
@@ -0,0 +1,39 @@
1
+ type ValidArgument = string | false;
2
+
3
+ /**
4
+ * mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).
5
+ *
6
+ * @license AGPL-3.0
7
+ * Copyright (C) 2026 Abdullah Fatota
8
+ *
9
+ *
10
+ * This program is free software: you can redistribute it and/or modify
11
+ * it under the terms of the GNU Affero General Public License as published by
12
+ * the Free Software Foundation, either version 3 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU Affero General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU Affero General Public License
21
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
+
23
+
24
+ Valid arguments:
25
+ 1) valid strings, which are non-empty strings, and non-whitespace strings
26
+ 2) value `false`
27
+
28
+ Invalid arguments: anything else e.g.
29
+ - empty strings
30
+ - whitespace strings
31
+ - numbers
32
+ - value true
33
+ -
34
+ */
35
+
36
+ declare const mergeClassNames: (...input: ValidArgument[]) => string;
37
+ declare const mergeClassNamesDebugger: (...input: ValidArgument[]) => string;
38
+
39
+ export { mergeClassNames, mergeClassNamesDebugger };
package/dist/index.mjs ADDED
@@ -0,0 +1,147 @@
1
+ // src/utils.ts
2
+ var classify = (value) => {
3
+ if (value === false) {
4
+ return {
5
+ status: "ignore",
6
+ value
7
+ };
8
+ }
9
+ if (typeof value !== "string") {
10
+ return {
11
+ status: "invalid",
12
+ value,
13
+ reason: 0 /* NotAString */
14
+ };
15
+ }
16
+ if (value === "") {
17
+ return {
18
+ status: "invalid",
19
+ value,
20
+ reason: 1 /* EmptyString */
21
+ };
22
+ }
23
+ const trimmed = value.trim();
24
+ if (trimmed === "") {
25
+ return {
26
+ status: "invalid",
27
+ value,
28
+ reason: 2 /* Whitespace */
29
+ };
30
+ }
31
+ return {
32
+ status: "class-name",
33
+ value: trimmed
34
+ };
35
+ };
36
+ var getClassNames = (values) => {
37
+ return values.filter((obj) => obj.status === "class-name");
38
+ };
39
+ var getInvalid = (values) => {
40
+ return values.filter((obj) => obj.status === "invalid");
41
+ };
42
+ var warningMessage = ({
43
+ value,
44
+ reason
45
+ }) => {
46
+ if (reason === 0 /* NotAString */) {
47
+ if (value === null || value === void 0) {
48
+ return `Ignored non-string argument: ${value}`;
49
+ }
50
+ if (value === true) {
51
+ return `Ignored non-string argument: ${value} (boolean)`;
52
+ }
53
+ if (Array.isArray(value)) {
54
+ const sub = value.slice(0, 3);
55
+ const string = JSON.stringify(sub).slice(1, -1);
56
+ const ellipsisPart = value.length > sub.length ? ", ..." : "";
57
+ return `Ignored non-string argument: array ([${string}${ellipsisPart}])`;
58
+ }
59
+ }
60
+ if (reason === 1 /* EmptyString */) {
61
+ return `Ignored empty string argument.`;
62
+ }
63
+ if (reason === 2 /* Whitespace */) {
64
+ return `Ignored whitespace string argument: "${value}"`;
65
+ }
66
+ return `Ignored non-string argument: ${value} (${typeof value})`;
67
+ };
68
+ var warn = (invalid) => {
69
+ const warning = warningMessage(invalid);
70
+ console.warn(warning);
71
+ };
72
+ var activateDebugger = (_invalid) => {
73
+ debugger;
74
+ };
75
+
76
+ // src/mergeClassNames.ts
77
+ var mergeClassNamesCore = (values, onClassifiedInvalid) => {
78
+ const classified = values.map(classify);
79
+ if (onClassifiedInvalid) {
80
+ getInvalid(classified).forEach(onClassifiedInvalid);
81
+ }
82
+ const classNames = getClassNames(classified).map(
83
+ ({ value }) => value
84
+ );
85
+ const finalClassName = classNames.join(" ");
86
+ return finalClassName;
87
+ };
88
+ var createCustomMergeClassNames = (options) => {
89
+ const invalidHandlers = [];
90
+ if (options["console-warn-invalid-and-whitespace-arguments"]) {
91
+ invalidHandlers.push(warn);
92
+ }
93
+ if (options["activate-debugger-on-invalid-arguments"]) {
94
+ invalidHandlers.push(activateDebugger);
95
+ }
96
+ const combinedInvalidHandler = (value) => {
97
+ invalidHandlers.forEach((func) => func(value));
98
+ };
99
+ return (...input) => mergeClassNamesCore(
100
+ input,
101
+ invalidHandlers.length > 0 ? combinedInvalidHandler : void 0
102
+ );
103
+ };
104
+ var mergeClassNames = createCustomMergeClassNames({
105
+ "console-warn-invalid-and-whitespace-arguments": true,
106
+ "activate-debugger-on-invalid-arguments": false
107
+ });
108
+ var mergeClassNamesDebugger = createCustomMergeClassNames({
109
+ "console-warn-invalid-and-whitespace-arguments": true,
110
+ "activate-debugger-on-invalid-arguments": true
111
+ });
112
+ /**
113
+ * mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).
114
+ *
115
+ * @license AGPL-3.0
116
+ * Copyright (C) 2026 Abdullah Fatota
117
+ *
118
+ *
119
+ * This program is free software: you can redistribute it and/or modify
120
+ * it under the terms of the GNU Affero General Public License as published by
121
+ * the Free Software Foundation, either version 3 of the License, or
122
+ * (at your option) any later version.
123
+ *
124
+ * This program is distributed in the hope that it will be useful,
125
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
126
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127
+ * GNU Affero General Public License for more details.
128
+ *
129
+ * You should have received a copy of the GNU Affero General Public License
130
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
131
+
132
+
133
+ Valid arguments:
134
+ 1) valid strings, which are non-empty strings, and non-whitespace strings
135
+ 2) value `false`
136
+
137
+ Invalid arguments: anything else e.g.
138
+ - empty strings
139
+ - whitespace strings
140
+ - numbers
141
+ - value true
142
+ -
143
+ */
144
+
145
+ export { mergeClassNames, mergeClassNamesDebugger };
146
+ //# sourceMappingURL=index.mjs.map
147
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts","../src/mergeClassNames.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import {\r\n ValidArgument,\r\n Classified,\r\n ClassifiedInvalid,\r\n ClassifiedInvalidReason,\r\n ClassifiedClassName,\r\n} from \"./types\";\r\n\r\n// classifies input arguments\r\nexport const classify = (value: ValidArgument): Classified => {\r\n // FP pattern of mapping values with extra information.\r\n // The core computes data.\r\n // because TS types disappear in JS runtime\r\n\r\n // valid but ignored\r\n if (value === false) {\r\n return {\r\n status: \"ignore\",\r\n value,\r\n };\r\n }\r\n\r\n // invalid\r\n if (typeof value !== \"string\") {\r\n return {\r\n status: \"invalid\",\r\n value,\r\n reason: ClassifiedInvalidReason.NotAString,\r\n };\r\n }\r\n\r\n // it's a string\r\n\r\n // invalid.\r\n if (value === \"\") {\r\n return {\r\n status: \"invalid\",\r\n value,\r\n reason: ClassifiedInvalidReason.EmptyString,\r\n };\r\n }\r\n\r\n const trimmed = value.trim();\r\n\r\n // invalid\r\n if (trimmed === \"\") {\r\n return {\r\n status: \"invalid\",\r\n value,\r\n reason: ClassifiedInvalidReason.Whitespace,\r\n };\r\n }\r\n\r\n // valid\r\n return {\r\n status: \"class-name\",\r\n value: trimmed,\r\n };\r\n};\r\n\r\n// get only valid objects\r\nexport const getClassNames = (values: Classified[]): ClassifiedClassName[] => {\r\n return values.filter((obj) => obj.status === \"class-name\");\r\n};\r\n\r\n// get only valid objects\r\nexport const getInvalid = (values: Classified[]): ClassifiedInvalid[] => {\r\n return values.filter((obj) => obj.status === \"invalid\");\r\n};\r\n\r\nexport const warningMessage = ({\r\n value,\r\n reason,\r\n}: ClassifiedInvalid): string => {\r\n if (reason === ClassifiedInvalidReason.NotAString) {\r\n // null, undefined\r\n if (value === null || value === undefined) {\r\n return `Ignored non-string argument: ${value}`;\r\n }\r\n\r\n // true (because false was filtered out)\r\n if (value === true) {\r\n return `Ignored non-string argument: ${value} (boolean)`;\r\n }\r\n\r\n // array\r\n if (Array.isArray(value)) {\r\n const sub = value.slice(0, 3);\r\n const string = JSON.stringify(sub).slice(1, -1);\r\n const ellipsisPart = value.length > sub.length ? \", ...\" : \"\";\r\n\r\n return `Ignored non-string argument: array ([${string}${ellipsisPart}])`;\r\n }\r\n }\r\n\r\n // empty string\r\n if (reason === ClassifiedInvalidReason.EmptyString) {\r\n return `Ignored empty string argument.`;\r\n }\r\n\r\n // whitespace\r\n if (reason === ClassifiedInvalidReason.Whitespace) {\r\n return `Ignored whitespace string argument: \"${value}\"`;\r\n }\r\n\r\n // object, symbol, etc.\r\n return `Ignored non-string argument: ${value} (${typeof value})`;\r\n};\r\n\r\n// console.warn\r\nexport const warn = (invalid: ClassifiedInvalid) => {\r\n const warning = warningMessage(invalid);\r\n\r\n console.warn(warning);\r\n};\r\n\r\n// activates debugger\r\nexport const activateDebugger = (_invalid: ClassifiedInvalid) => {\r\n debugger;\r\n};\r\n","/**\r\n * mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).\r\n *\r\n * @license AGPL-3.0\r\n * Copyright (C) 2026 Abdullah Fatota\r\n *\r\n *\r\n * This program is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU Affero General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n * GNU Affero General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU Affero General Public License\r\n * along with this program. If not, see <https://www.gnu.org/licenses/>.\r\n \r\n\r\nValid arguments:\r\n 1) valid strings, which are non-empty strings, and non-whitespace strings\r\n 2) value `false`\r\n\r\nInvalid arguments: anything else e.g.\r\n - empty strings\r\n - whitespace strings\r\n - numbers\r\n - value true\r\n - \r\n*/\r\n\r\nimport {\r\n ValidArgument,\r\n ClassifiedInvalidFunction,\r\n ClassifiedInvalid,\r\n CustomOptions,\r\n} from \"./types\";\r\n\r\nimport {\r\n classify,\r\n getInvalid,\r\n warn,\r\n activateDebugger,\r\n getClassNames,\r\n} from \"./utils\";\r\n\r\n// joins valid strings into final className\r\nconst mergeClassNamesCore = (\r\n values: ValidArgument[],\r\n onClassifiedInvalid?: ClassifiedInvalidFunction,\r\n) => {\r\n // classify arguments\r\n const classified = values.map(classify);\r\n\r\n // optional call invalid arguments handlers: warn and/or activate debugger\r\n if (onClassifiedInvalid) {\r\n getInvalid(classified).forEach(onClassifiedInvalid);\r\n }\r\n\r\n // valid strings only\r\n const classNames: string[] = getClassNames(classified).map(\r\n ({ value }) => value,\r\n );\r\n\r\n const finalClassName = classNames.join(\" \");\r\n return finalClassName;\r\n};\r\n\r\n// creates custom mergeClassNames e.g. warn = false, activate debugger = true\r\nexport const createCustomMergeClassNames = (options: CustomOptions) => {\r\n const invalidHandlers: ClassifiedInvalidFunction[] = [];\r\n\r\n if (options[\"console-warn-invalid-and-whitespace-arguments\"]) {\r\n invalidHandlers.push(warn);\r\n }\r\n\r\n if (options[\"activate-debugger-on-invalid-arguments\"]) {\r\n invalidHandlers.push(activateDebugger);\r\n }\r\n\r\n const combinedInvalidHandler = (value: ClassifiedInvalid) => {\r\n invalidHandlers.forEach((func) => func(value));\r\n };\r\n\r\n // construct the mergeClassNames function\r\n return (...input: ValidArgument[]) =>\r\n mergeClassNamesCore(\r\n input,\r\n invalidHandlers.length > 0 ? combinedInvalidHandler : undefined,\r\n );\r\n};\r\n\r\nexport const mergeClassNames = createCustomMergeClassNames({\r\n \"console-warn-invalid-and-whitespace-arguments\": true,\r\n \"activate-debugger-on-invalid-arguments\": false,\r\n});\r\n\r\nexport const mergeClassNamesDebugger = createCustomMergeClassNames({\r\n \"console-warn-invalid-and-whitespace-arguments\": true,\r\n \"activate-debugger-on-invalid-arguments\": true,\r\n});\r\n"]}
package/package.json CHANGED
@@ -1,27 +1,33 @@
1
1
  {
2
2
  "name": "simple-merge-class-names",
3
- "version": "7.0.2",
4
- "description": "A straightforward utility for merging CSS class names in React + Tailwind and JavaScript projects.",
3
+ "version": "8.0.0",
4
+ "description": " A class names merger for TypeScript, JavaScript, TSX, and JSX (React)",
5
5
  "exports": {
6
6
  ".": {
7
- "import": "./mergeClassNames.js",
8
- "types": "./mergeClassNames.d.ts"
7
+ "import": "./dist/index.mjs",
8
+ "types": "./dist/index.d.mts"
9
9
  }
10
10
  },
11
+ "main": "./dist/index.mjs",
12
+ "types": "./dist/index.d.mts",
11
13
  "files": [
12
- "mergeClassNames.js",
13
- "mergeClassNames.d.ts",
14
+ "dist",
14
15
  "LICENSE.txt",
15
16
  "README.md"
16
17
  ],
17
18
  "sideEffects": false,
18
19
  "keywords": [
19
- "mergeClassNames",
20
- "merge",
21
20
  "class-names-merger",
22
- "utility",
21
+ "classes-merger",
22
+ "jsx",
23
+ "merge",
24
+ "mergeClassNames",
25
+ "mergeClassNamesDebugger",
26
+ "merger",
23
27
  "react",
24
- "tailwindcss"
28
+ "tailwindcss",
29
+ "tsx",
30
+ "utility"
25
31
  ],
26
32
  "author": "Abdullah Fatota",
27
33
  "license": "AGPL-3.0",
@@ -29,14 +35,14 @@
29
35
  "type": "git",
30
36
  "url": "git+https://github.com/new-AF/simple-merge-class-names.git"
31
37
  },
32
- "bugs": {
33
- "url": "https://github.com/new-AF/simple-merge-class-names/issues"
34
- },
35
38
  "homepage": "https://github.com/new-AF/simple-merge-class-names",
36
39
  "devDependencies": {
40
+ "tsup": "^8.5.1",
41
+ "typescript": "^6.0.3",
37
42
  "vitest": "^3.2.3"
38
43
  },
39
44
  "scripts": {
45
+ "build": "tsup",
40
46
  "test": "vitest",
41
47
  "test:watch": "vitest --watch",
42
48
  "test:ui": "vitest --ui"
@@ -1,7 +0,0 @@
1
- export declare const mergeClassNames: (
2
- ...args: (string | false)[]
3
- ) => string | false;
4
-
5
- export declare const mergeClassNamesDebugger: (
6
- ...args: (string | false)[]
7
- ) => string | false;
@@ -1,175 +0,0 @@
1
- /**
2
- * mergeClassNames - A straightforward utility for merging CSS class names in React + Tailwind, and other JavaScript projects.
3
- *
4
- * @license AGPL-3.0
5
- * Copyright (C) 2025 Abdullah Fatota
6
- *
7
- * Example usage:
8
- * import { mergeClassNames } from "simple-merge-class-names";
9
- *
10
- * function MyComponent() {
11
- * return (
12
- * <div
13
- * className={mergeClassNames(
14
- * "app",
15
- * "min-h-dvh",
16
- * "grid",
17
- * "grid-rows-[auto_1fr_auto]",
18
- * "outline"
19
- * )}
20
- * >
21
- * Hello, world!
22
- * </div>
23
- * );
24
- * }
25
- *
26
- * This program is free software: you can redistribute it and/or modify
27
- * it under the terms of the GNU Affero General Public License as published by
28
- * the Free Software Foundation, either version 3 of the License, or
29
- * (at your option) any later version.
30
- *
31
- * This program is distributed in the hope that it will be useful,
32
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
33
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
- * GNU Affero General Public License for more details.
35
- *
36
- * You should have received a copy of the GNU Affero General Public License
37
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
38
- */
39
-
40
- const partition = (array, keepPredicate) => {
41
- const keep = [];
42
- const ignore = [];
43
- for (const element of array) {
44
- const arrayRef = keepPredicate(element) ? keep : ignore;
45
- arrayRef.push(element);
46
- }
47
- return [keep, ignore];
48
- };
49
-
50
- const filterArguments = (argumentsArray) => {
51
- /*
52
- returns {
53
- valid: bool,
54
- value: any
55
- (optional) isString: bool,
56
- (optional) valueType: any
57
- (optional) isValueFalse
58
- (optional) isValidString: bool
59
- }
60
- */
61
- const isValidArgument = (value) => {
62
- const valueType = typeof value;
63
-
64
- if (value === false) {
65
- return { valid: true, value };
66
- }
67
-
68
- if (valueType === "string") {
69
- const trimmed = value.trim();
70
-
71
- // invalid string
72
- if (trimmed === "") {
73
- return {
74
- valid: false,
75
- value,
76
- isString: true,
77
- isValidString: false,
78
- };
79
- }
80
- // valid string
81
- return {
82
- valid: true,
83
- value: trimmed,
84
- isString: true,
85
- isValidString: true,
86
- };
87
- }
88
-
89
- // everything else
90
- return { valid: false, value, isString: false, valueType };
91
- };
92
-
93
- // array of objects
94
- const newArguments = argumentsArray.map((element) =>
95
- isValidArgument(element)
96
- );
97
-
98
- // includes `false`
99
- const [validArgumentsWithFalse, invalidArguments] = partition(
100
- newArguments,
101
- ({ valid }) => valid === true
102
- );
103
-
104
- // ignore `false`
105
- const [validArguments, _] = partition(
106
- validArgumentsWithFalse,
107
- ({ value }) => value !== false
108
- );
109
-
110
- // console.log({ validArgumentsWithFalse, validArguments, invalidArguments });
111
-
112
- return { validArguments, invalidArguments };
113
- };
114
-
115
- const warnMessage = (
116
- { value, isString, valueType, isValidString },
117
- callerFunctionName
118
- ) => {
119
- if (isString === false) {
120
- return `[${callerFunctionName}] Ignored non-string >${value}< (${valueType})`;
121
- } else if (isValidString === false) {
122
- return `[${callerFunctionName}] Ignored empty string "${value}"`;
123
- }
124
- };
125
-
126
- const warnOnly = (
127
- invalidArgumentsArray,
128
- callerFunctionName,
129
- debuggerVariantName
130
- ) =>
131
- invalidArgumentsArray.forEach((obj) => {
132
- const message = warnMessage(obj, callerFunctionName);
133
- console.warn(`${message}`);
134
- });
135
-
136
- const warnDebug = (invalidArgumentsArray, callerFunctionName) =>
137
- invalidArgumentsArray.forEach((obj) => {
138
- console.warn(warnMessage(obj, callerFunctionName));
139
- debugger;
140
- });
141
-
142
- const join = (argumentsArray) => {
143
- const space = "\x20"; // ASCII for single space (" "), decimal 32
144
- const classNames = argumentsArray.map(({ value }) => value).join(space);
145
- return classNames;
146
- };
147
-
148
- const finalResult = (joinedClassNames) =>
149
- joinedClassNames === "" ? false : joinedClassNames;
150
-
151
- // exported
152
- // export const mergeClassNamesNoWarning = (...argumentsArray) => {
153
- // const { validArguments, _ } = filterArguments(argumentsArray);
154
- // const classNames = join(validArguments);
155
- // const result = finalResult(classNames);
156
- // return result;
157
- // };
158
-
159
- export const mergeClassNames = (...argumentsArray) => {
160
- const { validArguments, invalidArguments } =
161
- filterArguments(argumentsArray);
162
- warnOnly(invalidArguments, "mergeClassNames", "mergeClassNamesDebugger");
163
- const classNames = join(validArguments);
164
- const result = finalResult(classNames);
165
- return result;
166
- };
167
-
168
- export const mergeClassNamesDebugger = (...argumentsArray) => {
169
- const { validArguments, invalidArguments } =
170
- filterArguments(argumentsArray);
171
- warnDebug(invalidArguments, "mergeClassNamesDebugger");
172
- const classNames = join(validArguments);
173
- const result = finalResult(classNames);
174
- return result;
175
- };