klsx 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Walter Purcaro
3
+ Copyright (c) 2026 Walter Purcaro
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,88 +1,111 @@
1
1
  # 🎨 𝒌𝒍𝒔𝒙
2
2
 
3
- A simple replacement for [clsx](https://www.npmjs.com/package/clsx) **_you may not actually need_** (see the [benchmark](https://github.com/vuolter/klsx/blob/main/BENCHMARK.md))
3
+ #### The fastest classname constructor out there, drop-in replacement for [clsx](https://www.npmjs.com/package/clsx)
4
4
 
5
- Used to construct `class` conditionally with strings, arrays and key-value objects.
5
+ ---
6
6
 
7
- Developed as a case study, [Bun](https://bun.com) friendly. 🌿
7
+ Conditionally joins class names together from strings, arrays and key-value objects:
8
+
9
+ ```typescript
10
+ klsx('foo', 'bar', 'baz') // => "foo bar baz"
11
+
12
+ klsx(['foo', ['bar', true && 'baz']]) // => "foo bar baz"
13
+
14
+ klsx({ foo: 'string', bar: true, bux: null }, 'baz') // => "foo bar baz"
15
+ ```
8
16
 
9
17
  ### Features
10
18
 
11
- - 🚀 Unnecessarily fast (~20M ops/s)
12
- - 🎯 Same functionality and API of clsx
13
- - 👑 Modern ESM syntax
14
- - 💎 Zero dependencies
15
- - ☀️ No "lite" mode (simply doesn't make any sense)
16
- - 🎈 Only 277B (~190B compressed)
17
- - 🐳 Deeply typed and tested
18
- - 🚨 [Experimental WASM variant](https://github.com/vuolter/klsx/tree/wasm) (for research purposes, do not use it)
19
+ - 🚀 Faster than [clsx](https://www.npmjs.com/package/clsx), [classnames](https://www.npmjs.com/package/classnames) and even [classix](https://www.npmjs.com/package/classix)
20
+ - 🎯 Same of full featured [clsx](https://www.npmjs.com/package/clsx), just change a `c` with `k` and you've done!
21
+ - 👑 ES Module syntax, written in TypeScript and tested on [Bun](https://bun.com)
22
+ - 💎 Zero dependencies, less than 200 bytes (Brotli)
23
+ - 🐳 Provided with [real-world usage benchmark and memory footprint analysis](https://github.com/vuolter/klsx/blob/main/BENCHMARK.md)
24
+
25
+ ## Benchmark
26
+
27
+ Throughput (ops/s, higher is better) from the latest run:
28
+
29
+ ###### Bars are scaled to the fastest package in each test
30
+
31
+ ![Throughput benchmark: 𝒌𝒍𝒔𝒙 vs clsx, classnames and classix](benchmark.svg)
32
+
33
+ Full results: [BENCHMARK.md](BENCHMARK.md).
19
34
 
20
35
  ## Installation
21
36
 
37
+ <details open>
38
+ <summary>bun</summary>
39
+
22
40
  ```bash
23
41
  bun add klsx
24
42
  ```
25
43
 
26
- or with `npm`:
44
+ </details>
45
+
46
+ <details>
47
+ <summary>npm</summary>
27
48
 
28
49
  ```bash
29
50
  npm install klsx
30
51
  ```
31
52
 
32
- ## Quick Start
53
+ </details>
33
54
 
34
- ```typescript
35
- import { klsx } from 'klsx'
55
+ <details>
56
+ <summary>pnpm</summary>
36
57
 
37
- klsx('foo', 'bar', 'baz')
38
- // => "foo bar baz"
58
+ ```bash
59
+ pnpm add klsx
60
+ ```
61
+
62
+ </details>
39
63
 
40
- klsx({ foo: 'string', bar: true, bux: null }, 'baz')
41
- // => "foo bar baz"
64
+ <details>
65
+ <summary>yarn</summary>
42
66
 
43
- klsx(['foo', ['bar', true && 'baz']])
44
- // => "foo bar baz"
67
+ ```bash
68
+ yarn add klsx
45
69
  ```
46
70
 
47
- or importing the short alias `kx`:
71
+ </details>
72
+
73
+ <details>
74
+ <summary>deno</summary>
75
+
76
+ ```bash
77
+ deno add klsx
78
+ ```
79
+
80
+ </details>
81
+
82
+ ## Quick Start
83
+
84
+ ```typescript
85
+ import { klsx, kx } from 'klsx'
86
+
87
+ kx('foo', 'bar', 'baz') // => "foo bar baz"
88
+ klsx('foo', 'bar', 'baz') // => "foo bar baz"
89
+ ```
48
90
 
49
91
  ### React
50
92
 
51
93
  ```jsx
52
- import React, { useState } from 'react'
53
94
  import { kx } from 'klsx'
95
+ import React, { useState } from 'react'
54
96
 
55
97
  const MyComponent = () => {
56
98
  const [isActive, setIsActive] = useState(false)
57
- return (
58
- <div>
59
- <div className={kx('base-class', isActive ? 'active' : 'inactive')}>
60
- {/* ... */}
61
- </div>
62
-
63
- <div className={kx('base-class', { active: isActive, inactive: !isActive })}>
64
- {/* ... */}
65
- </div>
66
-
67
- <div
68
- className={kx('base-class', [isActive && 'active', !isActive && 'inactive'])}
69
- >
70
- {/* ... */}
71
- </div>
72
- </div>
73
- )
99
+
100
+ return <div className={kx('base-class', isActive ? 'active' : 'inactive')}>{/* ... */}</div>
74
101
  }
75
102
  ```
76
103
 
77
- ### Migrate from `clsx`
78
-
79
- Just replace every `c` with a `k`, as in the example below.
104
+ ### Migrate `cn`
80
105
 
81
- From:
106
+ From `clsx`:
82
107
 
83
108
  ```typescript
84
- // clsx
85
-
86
109
  import { clsx, type ClassValue } from 'clsx'
87
110
  import { twMerge } from 'tailwind-merge'
88
111
 
@@ -91,11 +114,9 @@ export function cn(...inputs: ClassValue[]) {
91
114
  }
92
115
  ```
93
116
 
94
- To:
117
+ To `klsx`:
95
118
 
96
119
  ```typescript
97
- // KLSX
98
-
99
120
  import { klsx, type KlassValue } from 'klsx'
100
121
  import { twMerge } from 'tailwind-merge'
101
122
 
@@ -116,7 +137,7 @@ export function cn(...inputs: KlassValue[]) {
116
137
  code --install-extension bradlc.vscode-tailwindcss
117
138
  ```
118
139
 
119
- 2. Update your [`settings.json`](https://code.visualstudio.com/docs/getstarted/settings) configuration with:
140
+ 1. Update your [`settings.json`](https://code.visualstudio.com/docs/getstarted/settings) configuration with:
120
141
 
121
142
  ```json
122
143
  {
@@ -132,7 +153,7 @@ code --install-extension bradlc.vscode-tailwindcss
132
153
  bun add -D prettier prettier-plugin-tailwindcss
133
154
  ```
134
155
 
135
- 2. Update your `prettier.config.js` configuration to handle `klsx`:
156
+ 1. Update your `prettier.config.js` configuration to handle `klsx`:
136
157
 
137
158
  ```javascript
138
159
  /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
@@ -150,11 +171,11 @@ export default {
150
171
  bun add -D eslint eslint-plugin-clsx
151
172
  ```
152
173
 
153
- 2. Update your `eslint.config.js` configuration to handle `klsx`:
174
+ 1. Update your `eslint.config.js` configuration to handle `klsx`:
154
175
 
155
176
  ```javascript
156
- import { defineConfig } from 'eslint/config'
157
177
  import clsx from 'eslint-plugin-clsx'
178
+ import { defineConfig } from 'eslint/config'
158
179
 
159
180
  export default defineConfig({
160
181
  plugins: { clsx },
package/dist/index.d.ts CHANGED
@@ -1,9 +1,5 @@
1
- //#region src/types.d.ts
2
- type KlassObject = Record<string, boolean | unknown>;
1
+ type KlassObject = Record<string, unknown>;
3
2
  type KlassArray = KlassValue[];
4
3
  type KlassValue = bigint | boolean | KlassArray | KlassObject | null | number | string | undefined;
5
- //#endregion
6
- //#region src/kx.d.ts
7
- declare function kx(...args: KlassValue[]): string;
8
- //#endregion
9
- export { type KlassArray, type KlassObject, type KlassValue, kx as default, kx as klsx, kx };
4
+ export default function klsx(...args: KlassValue[]): string;
5
+ export { type KlassArray, type KlassObject, type KlassValue, klsx, klsx as kx };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- function e(t){let n=``;for(let r of t)if(r){if(typeof r==`string`)n=n?n+` `+r:r;else if(typeof r==`object`)if(Array.isArray(r)){let t=e(r);t&&(n=n?n+` `+t:t)}else for(let e in r)r[e]&&(n=n?n+` `+e:e)}return n}function t(...t){return e(t)}export{t as default,t as klsx,t as kx};
1
+ function e(t,n){for(let r=0;r<n.length;r++){let i=n[r];if(i){if(typeof i==`string`)t=t?t+` `+i:i;else if(Array.isArray(i))t=e(t,i);else if(typeof i==`object`)for(let e in i)e&&i[e]&&(t=t?t+` `+e:e)}}return t}function t(){let t=``;for(let n=0;n<arguments.length;n++){let r=arguments[n];if(r){if(typeof r==`string`)t=t?t+` `+r:r;else if(Array.isArray(r))t=e(t,r);else if(typeof r==`object`)for(let e in r)e&&r[e]&&(t=t?t+` `+e:e)}}return t}export{t as default,t as klsx,t as kx};
package/package.json CHANGED
@@ -1,73 +1,62 @@
1
1
  {
2
2
  "name": "klsx",
3
- "description": "Same as clsx but \"maybe\" better",
4
- "version": "0.3.3",
5
- "type": "module",
3
+ "version": "0.4.1",
4
+ "description": "The fastest classname constructor out there, drop-in replacement for clsx",
5
+ "keywords": [
6
+ "bun",
7
+ "class",
8
+ "classix",
9
+ "classname",
10
+ "classnames",
11
+ "clsx",
12
+ "cn",
13
+ "cx",
14
+ "klsx",
15
+ "kx",
16
+ "react",
17
+ "tailwind-merge"
18
+ ],
19
+ "license": "MIT",
6
20
  "author": {
7
21
  "name": "Walter Purcaro",
8
22
  "url": "https://github.com/vuolter"
9
23
  },
10
- "license": "MIT",
11
24
  "repository": {
12
25
  "type": "git",
13
26
  "url": "git+https://github.com/vuolter/klsx.git"
14
27
  },
15
- "url": "https://github.com/vuolter/klsx",
16
- "keywords": [
17
- "cn",
18
- "cx",
19
- "kx",
20
- "klsx",
21
- "clsx",
22
- "class",
23
- "classix",
24
- "classname",
25
- "classnames",
26
- "bun"
27
- ],
28
28
  "files": [
29
29
  "dist"
30
30
  ],
31
+ "type": "module",
32
+ "sideEffects": false,
31
33
  "types": "./dist/index.d.ts",
32
34
  "exports": {
33
35
  ".": "./dist/index.js",
34
36
  "./package.json": "./package.json"
35
37
  },
36
38
  "scripts": {
37
- "build": "bun compile && tsdown",
38
- "format": "prettier . --cache --experimental-cli --write",
39
- "lint": "eslint --cache --cache-location ./node_modules/.cache/eslint --cache-strategy content --concurrency auto --fix .",
40
- "compile": "tsgo --build --noEmit",
41
- "bench": "bun ./tests/bench",
39
+ "build": "bun typecheck && tsdown",
40
+ "typecheck": "tsc --build --noEmit",
41
+ "format": "oxfmt --write .",
42
+ "lint": "oxlint --fix .",
43
+ "bench": "bun run build && bun ./tests/bench",
42
44
  "postinstall": "npm install --force --ignore-scripts --package-lock-only --silent"
43
45
  },
44
46
  "devDependencies": {
45
- "@eslint/js": "^10.0.1",
46
- "@prettier/plugin-oxc": "^0.1.3",
47
- "@socketsecurity/bun-security-scanner": "^1.1.2",
48
- "@types/bun": "^1.3.11",
49
- "@typescript/native-preview": "^7.0.0-dev.20260328.1",
50
- "classix": "^2.2.11",
51
- "classnames": "^2.5.1",
52
- "clsx": "^2.1.1",
53
- "eslint": "^10.1.0",
54
- "eslint-config-prettier": "^10.1.8",
55
- "eslint-import-resolver-typescript": "^4.4.4",
56
- "eslint-plugin-import-x": "^4.16.2",
57
- "eslint-plugin-perfectionist": "^5.7.0",
58
- "eslint-plugin-regexp": "^3.1.0",
59
- "eslint-plugin-security": "^4.0.0",
60
- "eslint-plugin-sonarjs": "^4.0.2",
61
- "eslint-plugin-tsdoc": "^0.5.2",
62
- "eslint-plugin-unicorn": "^64.0.0",
63
- "globals": "^17.4.0",
64
- "prettier": "^3.8.1",
65
- "tinybench": "^6.0.0",
66
- "tsdown": "^0.21.6",
67
- "typescript-eslint": "^8.57.2"
47
+ "@socketsecurity/bun-security-scanner": "1.1.3",
48
+ "@types/bun": "1.4.4",
49
+ "classix": "2.2.27",
50
+ "classnames": "2.5.1",
51
+ "clsx": "2.1.1",
52
+ "oxfmt": "0.76.0",
53
+ "oxlint": "1.91.0",
54
+ "oxlint-tsgolint": "7.0.2005",
55
+ "tinybench": "6.2.3",
56
+ "tsdown": "0.23.4",
57
+ "typescript": "7.0.2"
68
58
  },
69
59
  "engines": {
70
60
  "node": ">=18"
71
- },
72
- "sideEffects": false
61
+ }
73
62
  }