simple-merge-class-names 7.0.3 → 8.1.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,75 +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
56
64
 
57
- - _[https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)_
65
+ [https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
58
66
 
59
- _It will nicely format your code especially when you have lots of classes, and will significantly improve your visual experience._
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).
60
68
 
61
- _If you have a different IDE use an equivalent auto code formatter tool/extension_
69
+ ## Exported Functions
62
70
 
63
- ## Usage
71
+ | | `console.warn`s | Invokes JS `debugger;` statement on invalid arguments, which pauses execution when Debugger is attached |
72
+ | ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
73
+ | `mergeClassNames` | ✅ | ❌ |
74
+ | `mergeClassNamesDebugger` | ✅ | ✅ |
64
75
 
65
- | Function | Prints console warnings | Activates debugger |
66
- | ------------------------- | ----------------------- | ------------------ |
67
- | `mergeClassNames` | ✅ | ❌ |
68
- | `mergeClassNamesDebugger` | ✅ | ✅ |
76
+ ## Non-scale Usage
69
77
 
70
- _Example_:
78
+ ### Example
71
79
 
72
80
  ```jsx
81
+ // src/App.jsx
73
82
  import { mergeClassNames } from "simple-merge-class-names";
74
83
 
75
84
  const Component = ({ condition }) => {
@@ -80,7 +89,7 @@ const Component = ({ condition }) => {
80
89
  condition ? "min-h-dvh" : false,
81
90
  "grid",
82
91
  "grid-rows-[auto_1fr_auto]",
83
- "outline"
92
+ "outline",
84
93
  )}
85
94
  >
86
95
  Hello, world!
@@ -89,32 +98,106 @@ const Component = ({ condition }) => {
89
98
  };
90
99
  ```
91
100
 
92
- ### TypeScript Definitions
101
+ ## Scale Usage
102
+
103
+ ![diagram explanation of best way to use package](./.github/images/root-file.png)
93
104
 
94
- ```ts
95
- export declare const mergeClassNames: (
96
- ...args: (string | false)[]
97
- ) => string | false;
105
+ ### Create intermediary `@/mergeClassNames.js`
98
106
 
99
- export declare const mergeClassNamesDebugger: (
100
- ...args: (string | false)[]
101
- ) => string | false;
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
102
119
  ```
103
120
 
104
- ### Valid Arguments
121
+ #### Enable `@`-style Imports in Vite
105
122
 
106
- Only 2:
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";
132
+
133
+ // https://vitejs.dev/config/
134
+ export default defineConfig({
135
+ plugins: [react(), tailwindcss()],
136
+
137
+ resolve: {
138
+ alias: {
139
+ "@": path.resolve(__dirname, "src"), // @ now points to "my-react-app/src"
140
+ },
141
+ },
142
+ });
143
+ ```
144
+
145
+ ```js
146
+ // src/mergeClassNames.js
147
+
148
+ export { mergeClassNames } from "simple-merge-class-names";
149
+
150
+ // export { mergeClassNames as mergeClassNamesDebugger } from "simple-merge-class-names";
151
+ ```
152
+
153
+ And toggle-comment between the first and second lines as needed.
154
+
155
+ ### Example
107
156
 
108
- 1. **Valid strings, not whitespace, of length >= 1**
157
+ #### During Dev, Debug Entire Project
109
158
 
110
- _(As long as you have content in the string you're OK)_
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
+ ```
111
166
 
112
- 2. **`false`**
167
+ ```jsx
168
+ // @/App.jsx
113
169
 
114
- _Example, This is OK:_
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
115
197
 
116
198
  ```js
117
199
  mergeClassNames(
200
+ condition ? "daisy-btn-active" : false
118
201
  "mx-auto",
119
202
  "min-dvh ",
120
203
  " flex",
@@ -123,101 +206,119 @@ mergeClassNames(
123
206
  `
124
207
  gap-y-4
125
208
  `,
126
- false,
127
- condition ? "daisy-btn-active" : false
128
209
  );
129
210
  ```
130
211
 
131
- ### Invalid Arguments
212
+ ## Invalid Arguments
132
213
 
133
- 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:
134
215
 
135
- - **Empty strings**: _(e.g. `""`)_
136
- - **Whitespace** any consecutive combination of the following:
137
- - new lines,
138
- - spaces,
139
- - tabs
140
- - _(e.g._ `" "`, `"\n "`, `" \t \n "`, _etc.)_
141
- - **`true`**
142
- - **`undefined`**
143
- - **`null`**
144
- - **Objects**
145
- - **Numbers**
146
- - **Big Int**
147
- - **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
148
230
 
149
- ```js
150
- // 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_
151
232
 
233
+ ### Example
234
+
235
+ ```js
152
236
  const someVariable = "";
153
237
 
154
238
  mergeClassNames(
155
- someVariable, // empty string
156
- " ", // whitespace
157
- "\n ", // whitespace
158
- " \t \n ", // whitespace
159
- ` // whitespace
239
+ someVariable,
240
+ " ",
241
+ "\n ",
242
+ " \t \n ",
243
+ `
160
244
  \n
161
245
  `,
162
- true, // true
163
- undefined, // undefined
164
- null, // null
246
+ true,
247
+ undefined,
248
+ null,
165
249
  {
166
- // object
167
- name: "value",
168
- email: "email@example.com",
250
+ name: "name",
251
+ email: "name@example.com",
169
252
  },
170
- 123, // number
171
- 123.45 // number
253
+ 123,
254
+ 123.45,
172
255
  );
173
256
  ```
174
257
 
258
+ #### Developer Console Warnings
259
+
175
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)
176
261
 
177
- ### Reason for warnings
262
+ ## Conditional Class Inclusion
263
+
264
+ ```jsx
265
+ mergeClassNames(condition ? "min-h-dvh" : false);
178
266
 
179
- - 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
+ ```
180
270
 
181
- ### Conditional class inclusion
271
+ ### Avoid Short-circuit Syntax
182
272
 
183
- 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.
184
274
 
185
- - `condition ? "class-name" : false` with `false` serving as the valid fallback.
186
- - _or_ `condition === true ? "class-name" : false` if you want to be specific.
275
+ ## Return Result
187
276
 
188
- _Note:_ Avoid using the _short-circuit implicit syntax_ like this:
277
+ String of all merged valid classes. Invalid arguments are ignored and warned about.
189
278
 
190
- - `condition && "class-name"`, beside less readable code, it can produce _falsy_ values which will be **_ignored_** _(e.g. `0`, `""`, `undefined`, and `null`)_.
279
+ ### Example
191
280
 
192
281
  ```jsx
193
282
  import { mergeClassNames } from "simple-merge-class-names";
194
283
 
195
- const Component = () => {
196
- return (
197
- <div
198
- className={mergeClassNames(
199
- "app",
200
- condition ? "min-h-dvh" : false,
201
- "grid",
202
- "grid-rows-[auto_1fr_auto]",
203
- "outline"
204
- )}
205
- >
206
- Hello, world!
207
- </div>
208
- );
209
- };
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
+ );
210
299
  ```
211
300
 
212
- ### Return Result
301
+ ## Side Effect
213
302
 
214
- Either:
303
+ `console.warn`s if arguments contain invalid arguments.
215
304
 
216
- 1. **Valid `string`, never whitespace, always length >= 1**
305
+ ### Example
217
306
 
218
- 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
+ ```
219
316
 
220
- ### Chaining
317
+ > _It can be empy_
318
+
319
+ 1. **Valid `string`, never whitespace, always length >= 1**
320
+
321
+ ## Chaining
221
322
 
222
323
  Because of safe return types you can chain calls safely without worrying about warnings or arguments being ignored.
223
324
 
@@ -229,85 +330,45 @@ mergeClassNames(condition ? "disabled" : mergeClassNames(...) )
229
330
 
230
331
  ## Usage of Browser Debugger
231
332
 
232
- **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.
334
+
335
+ ```jsx
336
+ import { mergeClassNamesDebugger as mergeClassNames } from "simple-merge-class-names";
233
337
 
234
- 1. Enable Debugger
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
235
356
  - _For chromium-based browsers it's On by default and you don't need to do anything AFAIK._
236
357
  - _For Firefox:_ Open **_Developer Tools_:**
237
358
  - _Make Sure_ **_Debugger_** _(tab)_ -> **`Pause on debugger statement`** is ticked.
238
359
  - Keep Dev Tools open.
239
- ![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)
240
-
241
- - Use **`import {mergeClassNamesDebugger as mergeClassNames}`** to debug the entire file, and keep the rest intact.
242
-
243
- ```jsx
244
- import { mergeClassNamesDebugger as mergeClassNames } from "simple-merge-class-names";
245
-
246
- const Component = ({ condition }) => {
247
- return (
248
- <div
249
- className={mergeClassNames(
250
- "app",
251
- condition ? "min-h-dvh" : false,
252
- "grid",
253
- "grid-rows-[auto_1fr_auto]",
254
- "outline"
255
- )}
256
- >
257
- Hello, world!
258
- </div>
259
- );
260
- };
261
- ```
262
-
263
- - or call `mergeClassNamesDebugger` directly.
264
-
265
- ```jsx
266
- import { mergeClassNamesDebugger } from "simple-merge-class-names";
267
-
268
- const Component = ({ condition }) => {
269
- return (
270
- <div
271
- className={mergeClassNamesDebugger(
272
- "app",
273
- condition ? "min-h-dvh" : false,
274
- "grid",
275
- "grid-rows-[auto_1fr_auto]",
276
- "outline"
277
- )}
278
- >
279
- Hello, world!
280
- </div>
281
- );
282
- };
283
- ```
284
-
285
- - Refresh the page, the debugger should connect:
286
-
287
- - Navigate to the **_Call stack_**
288
- - Click the function/component right before _`mergeClassNamesDebugger`_
289
-
290
- ![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)
291
-
292
- - Hover over the arguments, one or several should be invalid:
293
- ![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)
294
-
295
- ## VSCode Workflow To Minimize Typing Strain
296
-
297
- Use single quotes around class names, and activate `Prettier` which will neatly format and arrange the classes.
298
360
 
299
- - Install `Prettier`
300
- - Enable `Editor: Word Wrap`:
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)
301
362
 
302
- - Open `Settings (UI)` `Editor: Word Wrap` → `on`
303
- - _or_ `User Settings (JSON)` and add this entry `"editor.wordWrap": "on"`
363
+ 3. Refresh the page, the debugger should connect:
364
+ - Navigate to the **_Call stack_**
365
+ - Click the function/component right before _`mergeClassNamesDebugger`_
304
366
 
305
- - Use single quotes (<kbd>'</kbd>) around class names
306
- - Save the file
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)
307
368
 
308
- _Before and after:_
369
+ 4. Hover over the arguments, one or several should be invalid:
309
370
 
310
- ![Screenshot of code before Prettier neatly formats code](https://raw.githubusercontent.com/new-AF/simple-merge-class-names/main/.github/images/Reduce-typing-strain.gif)
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)
311
372
 
312
373
  ## Testing Source Code
313
374
 
@@ -318,6 +379,7 @@ This project uses `Vitest` as the test runner for fast and modern testing.
318
379
  ```bash
319
380
  git clone https://github.com/new-AF/simple-merge-class-names
320
381
  cd simple-merge-class-names
382
+ pnpm install
321
383
  pnpm test
322
384
  ```
323
385
 
@@ -0,0 +1,39 @@
1
+ /**
2
+ * mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).
3
+ *
4
+ * @license AGPL-3.0
5
+ * Copyright (C) 2026 Abdullah Fatota
6
+ *
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU Affero General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU Affero General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Affero General Public License
19
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+
22
+ Only Valid Arguments:
23
+ 1) valid strings: non-empty, non-whitespace
24
+ 2) value `false`
25
+
26
+ Invalid arguments: anything else e.g.
27
+ - empty strings
28
+ - whitespace strings
29
+ - arrays
30
+ - numbers
31
+ - objects
32
+ - value true
33
+ - etc.
34
+ */
35
+
36
+ declare const mergeClassNames: (...input: (string | false)[]) => string;
37
+ declare const mergeClassNamesDebugger: (...input: (string | false)[]) => string;
38
+
39
+ export { mergeClassNames, mergeClassNamesDebugger };
package/dist/index.mjs ADDED
@@ -0,0 +1,152 @@
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, functionName) => {
69
+ const warning = warningMessage(invalid);
70
+ console.warn(`[${functionName}]`, 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
+ const functionName = options.name ?? "Custom mergeClassNames";
91
+ if (options["console-warn-invalid-and-whitespace-arguments"]) {
92
+ invalidHandlers.push((arg) => warn(arg, functionName));
93
+ }
94
+ if (options["activate-debugger-on-invalid-arguments"]) {
95
+ invalidHandlers.push(activateDebugger);
96
+ }
97
+ const combinedInvalidHandler = (value) => {
98
+ invalidHandlers.forEach((func) => func(value));
99
+ };
100
+ return (...input) => mergeClassNamesCore(
101
+ input,
102
+ invalidHandlers.length > 0 ? combinedInvalidHandler : void 0
103
+ );
104
+ };
105
+ var mergeClassNames = createCustomMergeClassNames({
106
+ "console-warn-invalid-and-whitespace-arguments": true,
107
+ "activate-debugger-on-invalid-arguments": false,
108
+ name: "mergeClassNames"
109
+ });
110
+ var mergeClassNamesDebugger = createCustomMergeClassNames({
111
+ "console-warn-invalid-and-whitespace-arguments": true,
112
+ "activate-debugger-on-invalid-arguments": true,
113
+ name: "mergeClassNamesDebugger"
114
+ });
115
+ /**
116
+ * mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).
117
+ *
118
+ * @license AGPL-3.0
119
+ * Copyright (C) 2026 Abdullah Fatota
120
+ *
121
+ *
122
+ * This program is free software: you can redistribute it and/or modify
123
+ * it under the terms of the GNU Affero General Public License as published by
124
+ * the Free Software Foundation, either version 3 of the License, or
125
+ * (at your option) any later version.
126
+ *
127
+ * This program is distributed in the hope that it will be useful,
128
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
129
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
130
+ * GNU Affero General Public License for more details.
131
+ *
132
+ * You should have received a copy of the GNU Affero General Public License
133
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
134
+
135
+
136
+ Only Valid Arguments:
137
+ 1) valid strings: non-empty, non-whitespace
138
+ 2) value `false`
139
+
140
+ Invalid arguments: anything else e.g.
141
+ - empty strings
142
+ - whitespace strings
143
+ - arrays
144
+ - numbers
145
+ - objects
146
+ - value true
147
+ - etc.
148
+ */
149
+
150
+ export { mergeClassNames, mergeClassNamesDebugger };
151
+ //# sourceMappingURL=index.mjs.map
152
+ //# 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 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: string | false): 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, functionName: string) => {\r\n const warning = warningMessage(invalid);\r\n\r\n console.warn(`[${functionName}]`, 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\nOnly Valid Arguments:\r\n 1) valid strings: non-empty, non-whitespace\r\n 2) value `false`\r\n\r\nInvalid arguments: anything else e.g.\r\n - empty strings\r\n - whitespace strings\r\n - arrays\r\n - numbers\r\n - objects\r\n - value true\r\n - etc.\r\n*/\r\n\r\nimport {\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: (string | false)[],\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 // will be logged in console\r\n const functionName = options.name ?? \"Custom mergeClassNames\";\r\n\r\n if (options[\"console-warn-invalid-and-whitespace-arguments\"]) {\r\n invalidHandlers.push((arg) => warn(arg, functionName));\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: (string | false)[]) =>\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 name: \"mergeClassNames\",\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 name: \"mergeClassNamesDebugger\",\r\n});\r\n"]}
package/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "name": "simple-merge-class-names",
3
- "version": "7.0.3",
4
- "description": "A straightforward utility for merging CSS class names in React + Tailwind and JavaScript projects.",
3
+ "version": "8.1.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
- "class-merger",
20
20
  "class-names-merger",
21
+ "classes-merger",
21
22
  "jsx",
22
23
  "merge",
23
24
  "mergeClassNames",
@@ -25,6 +26,7 @@
25
26
  "merger",
26
27
  "react",
27
28
  "tailwindcss",
29
+ "tsx",
28
30
  "utility"
29
31
  ],
30
32
  "author": "Abdullah Fatota",
@@ -33,14 +35,14 @@
33
35
  "type": "git",
34
36
  "url": "git+https://github.com/new-AF/simple-merge-class-names.git"
35
37
  },
36
- "bugs": {
37
- "url": "https://github.com/new-AF/simple-merge-class-names/issues"
38
- },
39
38
  "homepage": "https://github.com/new-AF/simple-merge-class-names",
40
39
  "devDependencies": {
40
+ "tsup": "^8.5.1",
41
+ "typescript": "^6.0.3",
41
42
  "vitest": "^3.2.3"
42
43
  },
43
44
  "scripts": {
45
+ "build": "tsup",
44
46
  "test": "vitest",
45
47
  "test:watch": "vitest --watch",
46
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
- };