simple-merge-class-names 9.0.0 → 9.2.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 +41 -354
- package/dist/index.d.mts +8 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,84 +1,38 @@
|
|
|
1
|
-
#
|
|
1
|
+
- [Why this package exists](#why-this-package-exists)
|
|
2
|
+
- [Why not `clsx`](#why-not-clsx)
|
|
3
|
+
- [Exported functions](#exported-functions)
|
|
4
|
+
- [Quick start](#quick-start)
|
|
5
|
+
- [Valid arguments](#valid-arguments)
|
|
6
|
+
- [Invalid arguments](#invalid-arguments)
|
|
7
|
+
- [Github](#github)
|
|
8
|
+
- [License](#license)
|
|
2
9
|
|
|
3
|
-
|
|
10
|
+
# Why this package exists
|
|
4
11
|
|
|
5
|
-
|
|
12
|
+
I got tired of squinting at the single line TailwindCSS `className = "..." ` string cramming a dozen utility classes with no delimiter between them, so I organically created a function that would split each string on a new line, and merge them back.
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
# Why not `clsx`
|
|
8
15
|
|
|
9
|
-
|
|
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)
|
|
16
|
+
I didn't like the unreadable [code](https://github.com/lukeed/clsx/blob/master/src/index.js) and the fact it accepts all types of arguments. I thought my engineering approach is better both in terms of code readability and strictness.
|
|
40
17
|
|
|
41
|
-
|
|
18
|
+
I used TypeScript and a functional programming approach to develop it.
|
|
42
19
|
|
|
43
|
-
|
|
20
|
+
# Exported functions
|
|
44
21
|
|
|
45
|
-
|
|
22
|
+
| | Warns | Invokes debugger |
|
|
23
|
+
| ----------------------------- | ------ | ---------------- |
|
|
24
|
+
| `mergeClassNames` | ✅ | ❌ |
|
|
25
|
+
| `mergeClassNamesDebugger` | ✅ | ✅ |
|
|
26
|
+
| `createCustomMergeClassNames` | Custom | Custom |
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- [Legal Action](https://www.hindrajabfoundation.org/perpetrators)
|
|
50
|
-
|
|
51
|
-
## Install
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
pnpm add simple-merge-class-names
|
|
55
|
-
|
|
56
|
-
# or
|
|
57
|
-
yarn add simple-merge-class-names
|
|
58
|
-
|
|
59
|
-
# or
|
|
60
|
-
npm install simple-merge-class-names
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Install `Prettier` too
|
|
64
|
-
|
|
65
|
-
[https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
|
66
|
-
|
|
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).
|
|
68
|
-
|
|
69
|
-
## Exported Functions
|
|
70
|
-
|
|
71
|
-
| | `console.warn`s | Invokes JS `debugger;` statement on invalid arguments, which pauses execution when Debugger is attached |
|
|
72
|
-
| ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------- |
|
|
73
|
-
| `mergeClassNames` | ✅ | ❌ |
|
|
74
|
-
| `mergeClassNamesDebugger` | ✅ | ✅ |
|
|
75
|
-
|
|
76
|
-
## Non-scale Usage
|
|
77
|
-
|
|
78
|
-
### Example
|
|
28
|
+
# Quick start
|
|
79
29
|
|
|
80
30
|
```jsx
|
|
81
|
-
|
|
31
|
+
/*
|
|
32
|
+
{
|
|
33
|
+
"fileName": "App.jsx"
|
|
34
|
+
}
|
|
35
|
+
*/
|
|
82
36
|
import { mergeClassNames } from "simple-merge-class-names";
|
|
83
37
|
|
|
84
38
|
const Component = ({ condition }) => {
|
|
@@ -98,301 +52,34 @@ const Component = ({ condition }) => {
|
|
|
98
52
|
};
|
|
99
53
|
```
|
|
100
54
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-

|
|
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";
|
|
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
|
|
156
|
-
|
|
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
|
|
55
|
+
# Valid arguments
|
|
190
56
|
|
|
191
|
-
|
|
57
|
+
Valid arguments are:
|
|
192
58
|
|
|
193
|
-
1.
|
|
194
|
-
2.
|
|
59
|
+
1. `string`s, that are not fully whitespace, these will be the class names you pass.
|
|
60
|
+
2. Empty string `""`
|
|
61
|
+
3. `null`
|
|
62
|
+
4. `undefined`
|
|
63
|
+
5. `false`
|
|
195
64
|
|
|
196
|
-
|
|
65
|
+
The latter four are valid but will be ignored as they're commonly used in conditional expressions.
|
|
197
66
|
|
|
198
|
-
|
|
199
|
-
mergeClassNames(
|
|
200
|
-
condition ? "daisy-btn-active" : false
|
|
201
|
-
"mx-auto",
|
|
202
|
-
"min-dvh ",
|
|
203
|
-
" flex",
|
|
204
|
-
" grid ",
|
|
205
|
-
"italic font-bold ",
|
|
206
|
-
`
|
|
207
|
-
gap-y-4
|
|
208
|
-
`,
|
|
209
|
-
);
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Invalid Arguments
|
|
67
|
+
# Invalid arguments
|
|
213
68
|
|
|
214
|
-
|
|
215
|
-
|
|
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`
|
|
69
|
+
- Fully whitespace strings
|
|
226
70
|
- Objects
|
|
227
|
-
-
|
|
228
|
-
-
|
|
71
|
+
- Arrays
|
|
72
|
+
- `true`
|
|
229
73
|
- Symbols
|
|
230
74
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
### Example
|
|
75
|
+
These will cause a console warning to be printed to alert you something might be off.
|
|
234
76
|
|
|
235
|
-
|
|
236
|
-
const someVariable = "";
|
|
237
|
-
|
|
238
|
-
mergeClassNames(
|
|
239
|
-
someVariable,
|
|
240
|
-
" ",
|
|
241
|
-
"\n ",
|
|
242
|
-
" \t \n ",
|
|
243
|
-
`
|
|
244
|
-
\n
|
|
245
|
-
`,
|
|
246
|
-
true,
|
|
247
|
-
undefined,
|
|
248
|
-
null,
|
|
249
|
-
{
|
|
250
|
-
name: "name",
|
|
251
|
-
email: "name@example.com",
|
|
252
|
-
},
|
|
253
|
-
123,
|
|
254
|
-
123.45,
|
|
255
|
-
);
|
|
256
|
-
```
|
|
77
|
+
# Github
|
|
257
78
|
|
|
258
|
-
|
|
79
|
+
[https://github.com/new-AF/simple-merge-class-names](https://github.com/new-AF/simple-merge-class-names)
|
|
259
80
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
## Conditional Class Inclusion
|
|
263
|
-
|
|
264
|
-
```jsx
|
|
265
|
-
mergeClassNames(condition ? "min-h-dvh" : false);
|
|
266
|
-
|
|
267
|
-
// or if you want preciseness.
|
|
268
|
-
mergeClassNames(condition === true ? "min-h-dvh" : false);
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Avoid Short-circuit Syntax
|
|
272
|
-
|
|
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.
|
|
274
|
-
|
|
275
|
-
## Return Result
|
|
276
|
-
|
|
277
|
-
String of all merged valid classes. Invalid arguments are ignored and warned about.
|
|
278
|
-
|
|
279
|
-
### Example
|
|
280
|
-
|
|
281
|
-
```jsx
|
|
282
|
-
import { mergeClassNames } from "simple-merge-class-names";
|
|
283
|
-
|
|
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
|
-
);
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
## Side Effect
|
|
302
|
-
|
|
303
|
-
`console.warn`s if arguments contain invalid arguments.
|
|
304
|
-
|
|
305
|
-
### Example
|
|
306
|
-
|
|
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**
|
|
320
|
-
|
|
321
|
-
## Chaining
|
|
322
|
-
|
|
323
|
-
Because of safe return types you can chain calls safely without worrying about warnings or arguments being ignored.
|
|
324
|
-
|
|
325
|
-
_So this is OK:_
|
|
326
|
-
|
|
327
|
-
```js
|
|
328
|
-
mergeClassNames(condition ? "disabled" : mergeClassNames(...) )
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
## Usage of Browser Debugger
|
|
332
|
-
|
|
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";
|
|
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
|
|
356
|
-
- _For chromium-based browsers it's On by default and you don't need to do anything AFAIK._
|
|
357
|
-
- _For Firefox:_ Open **_Developer Tools_:**
|
|
358
|
-
- _Make Sure_ **_Debugger_** _(tab)_ -> **`Pause on debugger statement`** is ticked.
|
|
359
|
-
- Keep Dev Tools open.
|
|
360
|
-
|
|
361
|
-

|
|
362
|
-
|
|
363
|
-
3. Refresh the page, the debugger should connect:
|
|
364
|
-
- Navigate to the **_Call stack_**
|
|
365
|
-
- Click the function/component right before _`mergeClassNamesDebugger`_
|
|
366
|
-
|
|
367
|
-

|
|
368
|
-
|
|
369
|
-
4. Hover over the arguments, one or several should be invalid:
|
|
370
|
-
|
|
371
|
-

|
|
372
|
-
|
|
373
|
-
## Testing Source Code
|
|
374
|
-
|
|
375
|
-
This project uses `Vitest` as the test runner for fast and modern testing.
|
|
376
|
-
|
|
377
|
-
### Run Once
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
git clone https://github.com/new-AF/simple-merge-class-names
|
|
381
|
-
cd simple-merge-class-names
|
|
382
|
-
pnpm install
|
|
383
|
-
pnpm test
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
### Run Watch Mode
|
|
387
|
-
|
|
388
|
-
```bash
|
|
389
|
-
pnpm test:watch
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
## License
|
|
81
|
+
# License
|
|
393
82
|
|
|
394
83
|
This project is licensed under the AGPL-3.0 License. See `LICENSE.txt` for full details.
|
|
395
84
|
|
|
396
|
-
---
|
|
397
|
-
|
|
398
85
|
Enjoy 😉
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
type CustomOptions = {
|
|
2
|
+
warnings?: boolean;
|
|
3
|
+
"activate-debugger"?: boolean;
|
|
4
|
+
name?: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* mergeClassNames - A class names merger for TypeScript, JavaScript, TSX / JSX (React).
|
|
3
9
|
*
|
|
@@ -33,7 +39,8 @@ Invalid arguments: anything else e.g.
|
|
|
33
39
|
- etc.
|
|
34
40
|
*/
|
|
35
41
|
|
|
42
|
+
declare const createCustomMergeClassNames: (options: CustomOptions) => (...input: (string | false)[]) => string;
|
|
36
43
|
declare const mergeClassNames: (...input: (string | false)[]) => string;
|
|
37
44
|
declare const mergeClassNamesDebugger: (...input: (string | false)[]) => string;
|
|
38
45
|
|
|
39
|
-
export { mergeClassNames, mergeClassNamesDebugger };
|
|
46
|
+
export { createCustomMergeClassNames, mergeClassNames, mergeClassNamesDebugger };
|
package/dist/index.mjs
CHANGED
|
@@ -140,6 +140,6 @@ Invalid arguments: anything else e.g.
|
|
|
140
140
|
- etc.
|
|
141
141
|
*/
|
|
142
142
|
|
|
143
|
-
export { mergeClassNames, mergeClassNamesDebugger };
|
|
143
|
+
export { createCustomMergeClassNames, mergeClassNames, mergeClassNamesDebugger };
|
|
144
144
|
//# sourceMappingURL=index.mjs.map
|
|
145
145
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/mergeClassNames.ts"],"names":[],"mappings":";AAQO,IAAM,QAAA,GAAW,CACpB,KACa,KAAA;AAMb,EAAA,IACI,UAAU,KACV,IAAA,KAAA,KAAU,UACV,KAAU,KAAA,IAAA,IACV,UAAU,EACZ,EAAA;AACE,IAAO,OAAA;AAAA,MACH,MAAQ,EAAA,QAAA;AAAA,MACR;AAAA,KACJ;AAAA;AAIJ,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC3B,IAAO,OAAA;AAAA,MACH,MAAQ,EAAA,SAAA;AAAA,MACR,KAAA;AAAA,MACA,MAAA,EAAA,CAAA;AAAA,KACJ;AAAA;AAKJ,EAAM,MAAA,OAAA,GAAU,MAAM,IAAK,EAAA;AAG3B,EAAA,IAAI,YAAY,EAAI,EAAA;AAChB,IAAO,OAAA;AAAA,MACH,MAAQ,EAAA,SAAA;AAAA,MACR,KAAA;AAAA,MACA,MAAA,EAAA,CAAA;AAAA,KACJ;AAAA;AAIJ,EAAO,OAAA;AAAA,IACH,MAAQ,EAAA,YAAA;AAAA,IACR,KAAO,EAAA;AAAA,GACX;AACJ,CAAA;AAGO,IAAM,aAAA,GAAgB,CAAC,MAAgD,KAAA;AAC1E,EAAA,OAAO,OAAO,MAAO,CAAA,CAAC,GAAQ,KAAA,GAAA,CAAI,WAAW,YAAY,CAAA;AAC7D,CAAA;AAGO,IAAM,UAAA,GAAa,CAAC,MAAkD,KAAA;AACzE,EAAA,OAAO,OAAO,MAAO,CAAA,CAAC,GAAQ,KAAA,GAAA,CAAI,WAAW,SAAS,CAAA;AAC1D,CAAA;AAEO,IAAM,iBAAiB,CAC1B,EAAE,KAAO,EAAA,MAAA,IACT,YACS,KAAA;AACT,EAAA,MAAM,SAAS,CAAC,OAAA,KAAoB,CAAI,CAAA,EAAA,YAAY,KAAK,OAAO,CAAA,CAAA;AAEhE,EAAA,IAAI,MAA+C,KAAA,CAAA,mBAAA;AAE/C,IAAI,IAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,KAAU,MAAW,EAAA;AACvC,MAAO,OAAA,MAAA,CAAO,CAAgC,6BAAA,EAAA,KAAK,CAAE,CAAA,CAAA;AAAA;AAIzD,IAAA,IAAI,UAAU,IAAM,EAAA;AAChB,MAAO,OAAA,MAAA,CAAO,CAAgC,6BAAA,EAAA,KAAK,CAAY,UAAA,CAAA,CAAA;AAAA;AAInE,IAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,KAAK,CAAG,EAAA;AACtB,MAAA,MAAM,GAAM,GAAA,KAAA,CAAM,KAAM,CAAA,CAAA,EAAG,CAAC,CAAA;AAC5B,MAAA,MAAM,SAAS,IAAK,CAAA,SAAA,CAAU,GAAG,CAAE,CAAA,KAAA,CAAM,GAAG,EAAE,CAAA;AAC9C,MAAA,MAAM,YAAe,GAAA,KAAA,CAAM,MAAS,GAAA,GAAA,CAAI,SAAS,OAAU,GAAA,EAAA;AAE3D,MAAO,OAAA,MAAA;AAAA,QACH,CAAA,qCAAA,EAAwC,MAAM,CAAA,EAAG,YAAY,CAAA,EAAA;AAAA,OACjE;AAAA;AACJ;AAIJ,EAAA,IAAI,MAAgD,KAAA,CAAA,oBAAA;AAChD,IAAA,OAAO,OAAO,CAAgC,8BAAA,CAAA,CAAA;AAAA;AAIlD,EAAA,IAAI,MAA+C,KAAA,CAAA,mBAAA;AAC/C,IAAO,OAAA,MAAA,CAAO,CAAwC,qCAAA,EAAA,KAAK,CAAG,CAAA,CAAA,CAAA;AAAA;AAIlE,EAAA,OAAO,OAAO,CAAgC,6BAAA,EAAA,KAAK,CAAK,EAAA,EAAA,OAAO,KAAK,CAAG,CAAA,CAAA,CAAA;AAC3E,CAAA;AAGO,IAAM,IAAA,GAAO,CAAC,OAAA,EAAgC,YAAyB,KAAA;AAC1E,EAAM,MAAA,OAAA,GAAU,cAAe,CAAA,OAAA,EAAS,YAAY,CAAA;AAEpD,EAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AACxB,CAAA;AAGO,IAAM,gBAAA,GAAmB,CAAC,QAAoC,KAAA;AACjE,EAAA;AACJ,CAAA;;;ACtEA,IAAM,mBAAA,GAAsB,CACxB,MAAA,EACA,mBACC,KAAA;AAED,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,GAAA,CAAI,QAAQ,CAAA;AAGtC,EAAA,IAAI,mBAAqB,EAAA;AACrB,IAAW,UAAA,CAAA,UAAU,CAAE,CAAA,OAAA,CAAQ,mBAAmB,CAAA;AAAA;AAItD,EAAM,MAAA,UAAA,GAAuB,aAAc,CAAA,UAAU,CAAE,CAAA,GAAA;AAAA,IACnD,CAAC,EAAE,KAAA,EAAY,KAAA;AAAA,GACnB;AAEA,EAAM,MAAA,cAAA,GAAiB,UAAW,CAAA,IAAA,CAAK,GAAG,CAAA;AAC1C,EAAO,OAAA,cAAA;AACX,CAAA;AAGO,IAAM,2BAAA,GAA8B,CAAC,OAA2B,KAAA;AACnE,EAAA,MAAM,kBAA+C,EAAC;AAGtD,EAAM,MAAA,YAAA,GAAe,QAAQ,IAAQ,IAAA,wBAAA;AAGrC,EAAI,IAAA,OAAA,CAAQ,UAAU,CAAG,EAAA;AACrB,IAAA,eAAA,CAAgB,KAAK,CAAC,GAAA,KAAQ,IAAK,CAAA,GAAA,EAAK,YAAY,CAAC,CAAA;AAAA;AAIzD,EAAI,IAAA,OAAA,CAAQ,mBAAmB,CAAG,EAAA;AAC9B,IAAA,eAAA,CAAgB,KAAK,gBAAgB,CAAA;AAAA;AAGzC,EAAM,MAAA,sBAAA,GAAyB,CAAC,KAAiC,KAAA;AAC7D,IAAA,eAAA,CAAgB,OAAQ,CAAA,CAAC,IAAS,KAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,GACjD;AAGA,EAAA,OAAO,IAAI,KACP,KAAA,mBAAA;AAAA,IACI,KAAA;AAAA,IACA,eAAA,CAAgB,MAAS,GAAA,CAAA,GAAI,sBAAyB,GAAA;AAAA,GAC1D;AACR,CAAA;AAEO,IAAM,kBAAkB,2BAA4B,CAAA;AAAA,EACvD,QAAU,EAAA,IAAA;AAAA,EACV,mBAAqB,EAAA,KAAA;AAAA,EACrB,IAAM,EAAA;AACV,CAAC;AAEM,IAAM,0BAA0B,2BAA4B,CAAA;AAAA,EAC/D,QAAU,EAAA,IAAA;AAAA,EACV,mBAAqB,EAAA,IAAA;AAAA,EACrB,IAAM,EAAA;AACV,CAAC","file":"index.mjs","sourcesContent":["import {\r\n Classified,\r\n ClassifiedInvalidWarn,\r\n ClassifiedInvalidReason,\r\n ClassifiedClassName,\r\n} from \"./types\";\r\n\r\n// classifies input arguments\r\nexport const classify = (\r\n value: string | undefined | null | false,\r\n): 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 (\r\n value === false ||\r\n value === undefined ||\r\n value === null ||\r\n value === \"\"\r\n ) {\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 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[]): ClassifiedInvalidWarn[] => {\r\n return values.filter((obj) => obj.status === \"invalid\");\r\n};\r\n\r\nexport const warningMessage = (\r\n { value, reason }: ClassifiedInvalidWarn,\r\n functionName: string,\r\n): string => {\r\n const format = (message: string) => `[${functionName}] ${message}`;\r\n\r\n if (reason === ClassifiedInvalidReason.NotAString) {\r\n // null, undefined\r\n if (value === null || value === undefined) {\r\n return format(`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 format(`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 format(\r\n `Ignored non-string argument: array ([${string}${ellipsisPart}])`,\r\n );\r\n }\r\n }\r\n\r\n // empty string\r\n if (reason === ClassifiedInvalidReason.EmptyString) {\r\n return format(`Ignored empty string argument.`);\r\n }\r\n\r\n // whitespace\r\n if (reason === ClassifiedInvalidReason.Whitespace) {\r\n return format(`Ignored whitespace string argument: \"${value}\"`);\r\n }\r\n\r\n // object, symbol, etc.\r\n return format(`Ignored non-string argument: ${value} (${typeof value})`);\r\n};\r\n\r\n// console.warn\r\nexport const warn = (invalid: ClassifiedInvalidWarn, functionName: string) => {\r\n const warning = warningMessage(invalid, functionName);\r\n\r\n console.warn(warning);\r\n};\r\n\r\n// activates debugger\r\nexport const activateDebugger = (_invalid: ClassifiedInvalidWarn) => {\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 ClassifiedInvalidWarn,\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 // default: Custom mergeClassNames. will be logged in console\r\n const functionName = options.name ?? \"Custom mergeClassNames\";\r\n\r\n // default: falsey\r\n if (options[\"warnings\"]) {\r\n invalidHandlers.push((arg) => warn(arg, functionName));\r\n }\r\n\r\n // default: falsy\r\n if (options[\"activate-debugger\"]) {\r\n invalidHandlers.push(activateDebugger);\r\n }\r\n\r\n const combinedInvalidHandler = (value: ClassifiedInvalidWarn) => {\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 warnings: true,\r\n \"activate-debugger\": false,\r\n name: \"mergeClassNames\",\r\n});\r\n\r\nexport const mergeClassNamesDebugger = createCustomMergeClassNames({\r\n warnings: true,\r\n \"activate-debugger\": true,\r\n name: \"mergeClassNamesDebugger\",\r\n});\r\n"]}
|
|
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 ClassifiedInvalidWarn,\r\n ClassifiedInvalidReason,\r\n ClassifiedClassName,\r\n} from \"./types\";\r\n\r\n// classifies input arguments\r\nexport const classify = (\r\n value: string | undefined | null | false,\r\n): 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 (\r\n value === false ||\r\n value === undefined ||\r\n value === null ||\r\n value === \"\"\r\n ) {\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 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[]): ClassifiedInvalidWarn[] => {\r\n return values.filter((obj) => obj.status === \"invalid\");\r\n};\r\n\r\nexport const warningMessage = (\r\n { value, reason }: ClassifiedInvalidWarn,\r\n functionName: string,\r\n): string => {\r\n const format = (message: string) => `[${functionName}] ${message}`;\r\n\r\n if (reason === ClassifiedInvalidReason.NotAString) {\r\n // null, undefined\r\n if (value === null || value === undefined) {\r\n return format(`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 format(`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 format(\r\n `Ignored non-string argument: array ([${string}${ellipsisPart}])`,\r\n );\r\n }\r\n }\r\n\r\n // empty string\r\n if (reason === ClassifiedInvalidReason.EmptyString) {\r\n return format(`Ignored empty string argument.`);\r\n }\r\n\r\n // whitespace\r\n if (reason === ClassifiedInvalidReason.Whitespace) {\r\n return format(`Ignored whitespace string argument: \"${value}\"`);\r\n }\r\n\r\n // object, symbol, etc.\r\n return format(`Ignored non-string argument: ${value} (${typeof value})`);\r\n};\r\n\r\n// console.warn\r\nexport const warn = (invalid: ClassifiedInvalidWarn, functionName: string) => {\r\n const warning = warningMessage(invalid, functionName);\r\n\r\n console.warn(warning);\r\n};\r\n\r\n// activates debugger\r\nexport const activateDebugger = (_invalid: ClassifiedInvalidWarn) => {\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 ClassifiedInvalidWarn,\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 // default: Custom mergeClassNames. will be logged in console\r\n const functionName = options.name ?? \"Custom mergeClassNames\";\r\n\r\n // default: falsey\r\n if (options[\"warnings\"]) {\r\n invalidHandlers.push((arg) => warn(arg, functionName));\r\n }\r\n\r\n // default: falsy\r\n if (options[\"activate-debugger\"]) {\r\n invalidHandlers.push(activateDebugger);\r\n }\r\n\r\n const combinedInvalidHandler = (value: ClassifiedInvalidWarn) => {\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 warnings: true,\r\n \"activate-debugger\": false,\r\n name: \"mergeClassNames\",\r\n});\r\n\r\nexport const mergeClassNamesDebugger = createCustomMergeClassNames({\r\n warnings: true,\r\n \"activate-debugger\": true,\r\n name: \"mergeClassNamesDebugger\",\r\n});\r\n"]}
|