klsx 0.3.2 → 0.4.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/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,108 @@
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
+ Conditionally joins class names together from strings, arrays and key-value objects:
6
6
 
7
- Developed as a case study, [Bun](https://bun.com) friendly. 🌿
7
+ ```typescript
8
+ klsx('foo', 'bar', 'baz') // => "foo bar baz"
9
+
10
+ klsx(['foo', ['bar', true && 'baz']]) // => "foo bar baz"
11
+
12
+ klsx({ foo: 'string', bar: true, bux: null }, 'baz') // => "foo bar baz"
13
+ ```
8
14
 
9
15
  ### Features
10
16
 
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)
17
+ - 🚀 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)
18
+ - 🎯 Same of full featured [clsx](https://www.npmjs.com/package/clsx), just change a `c` with `k` and you've done!
19
+ - 👑 ES Module syntax, written in TypeScript and optimized for [Bun](https://bun.com)
20
+ - 💎 Zero dependencies, less than 200 bytes (Brotli)
21
+ - 🐳 Provided with [real-world usage benchmark and memory footprint analysis](https://github.com/vuolter/klsx/blob/main/BENCHMARK.md)
22
+ - 🚨 [Experimental WASM variant](https://github.com/vuolter/klsx/tree/wasm) (research purpose only)
23
+
24
+ ## Benchmark
25
+
26
+ Throughput (ops/s, higher is better) from the latest run. Bars are scaled to the fastest package in each test:
27
+
28
+ ![Throughput benchmark: 𝒌𝒍𝒔𝒙 vs clsx, classnames and classix](benchmark.svg)
29
+
30
+ Full results: [BENCHMARK.md](BENCHMARK.md).
19
31
 
20
32
  ## Installation
21
33
 
34
+ <details open>
35
+ <summary>bun</summary>
36
+
22
37
  ```bash
23
38
  bun add klsx
24
39
  ```
25
40
 
26
- or with `npm`:
41
+ </details>
42
+
43
+ <details>
44
+ <summary>npm</summary>
27
45
 
28
46
  ```bash
29
47
  npm install klsx
30
48
  ```
31
49
 
32
- ## Quick Start
50
+ </details>
33
51
 
34
- ```typescript
35
- import { klsx } from 'klsx'
52
+ <details>
53
+ <summary>pnpm</summary>
36
54
 
37
- klsx('foo', 'bar', 'baz')
38
- // => "foo bar baz"
55
+ ```bash
56
+ pnpm add klsx
57
+ ```
39
58
 
40
- klsx({ foo: 'string', bar: true, bux: null }, 'baz')
41
- // => "foo bar baz"
59
+ </details>
42
60
 
43
- klsx(['foo', ['bar', true && 'baz']])
44
- // => "foo bar baz"
61
+ <details>
62
+ <summary>yarn</summary>
63
+
64
+ ```bash
65
+ yarn add klsx
45
66
  ```
46
67
 
47
- or importing the short alias `kx`:
68
+ </details>
69
+
70
+ <details>
71
+ <summary>deno</summary>
72
+
73
+ ```bash
74
+ deno add klsx
75
+ ```
76
+
77
+ </details>
78
+
79
+ ## Quick Start
80
+
81
+ ```typescript
82
+ import { klsx, kx } from 'klsx'
83
+
84
+ kx('foo', 'bar', 'baz') // => "foo bar baz"
85
+ klsx('foo', 'bar', 'baz') // => "foo bar baz"
86
+ ```
48
87
 
49
88
  ### React
50
89
 
51
90
  ```jsx
52
- import React, { useState } from 'react'
53
91
  import { kx } from 'klsx'
92
+ import React, { useState } from 'react'
54
93
 
55
94
  const MyComponent = () => {
56
95
  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
- )
96
+
97
+ return <div className={kx('base-class', isActive ? 'active' : 'inactive')}>{/* ... */}</div>
74
98
  }
75
99
  ```
76
100
 
77
- ### Migrate from `clsx`
78
-
79
- Just replace every `c` with a `k`, as in the example below.
101
+ ### Migrate `cn`
80
102
 
81
- From:
103
+ From `clsx`:
82
104
 
83
105
  ```typescript
84
- // clsx
85
-
86
106
  import { clsx, type ClassValue } from 'clsx'
87
107
  import { twMerge } from 'tailwind-merge'
88
108
 
@@ -91,11 +111,9 @@ export function cn(...inputs: ClassValue[]) {
91
111
  }
92
112
  ```
93
113
 
94
- To:
114
+ To `klsx`:
95
115
 
96
116
  ```typescript
97
- // KLSX
98
-
99
117
  import { klsx, type KlassValue } from 'klsx'
100
118
  import { twMerge } from 'tailwind-merge'
101
119
 
@@ -116,7 +134,7 @@ export function cn(...inputs: KlassValue[]) {
116
134
  code --install-extension bradlc.vscode-tailwindcss
117
135
  ```
118
136
 
119
- 2. Update your [`settings.json`](https://code.visualstudio.com/docs/getstarted/settings) configuration with:
137
+ 1. Update your [`settings.json`](https://code.visualstudio.com/docs/getstarted/settings) configuration with:
120
138
 
121
139
  ```json
122
140
  {
@@ -132,7 +150,7 @@ code --install-extension bradlc.vscode-tailwindcss
132
150
  bun add -D prettier prettier-plugin-tailwindcss
133
151
  ```
134
152
 
135
- 2. Update your `prettier.config.js` configuration to handle `klsx`:
153
+ 1. Update your `prettier.config.js` configuration to handle `klsx`:
136
154
 
137
155
  ```javascript
138
156
  /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
@@ -150,11 +168,11 @@ export default {
150
168
  bun add -D eslint eslint-plugin-clsx
151
169
  ```
152
170
 
153
- 2. Update your `eslint.config.js` configuration to handle `klsx`:
171
+ 1. Update your `eslint.config.js` configuration to handle `klsx`:
154
172
 
155
173
  ```javascript
156
- import { defineConfig } from 'eslint/config'
157
174
  import clsx from 'eslint-plugin-clsx'
175
+ import { defineConfig } from 'eslint/config'
158
176
 
159
177
  export default defineConfig({
160
178
  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
+ const e=Array.isArray;function t(e,t){for(let n in e)n&&e[n]&&(t=t?t+` `+n:n);return t}function n(r,i){for(let a=0;a<r.length;a++){let o=r[a];o&&(typeof o==`string`?i=i?i+` `+o:o:typeof o==`object`&&(i=e(o)?n(o,i):t(o,i)))}return i}function r(...r){let i=``;for(let a=0;a<r.length;a++){let o=r[a];o&&(typeof o==`string`?i=i?i+` `+o:o:typeof o==`object`&&(i=e(o)?n(o,i):t(o,i)))}return i}export{r as default,r as klsx,r as kx};
package/package.json CHANGED
@@ -1,73 +1,60 @@
1
1
  {
2
2
  "name": "klsx",
3
- "version": "0.3.2",
4
- "type": "module",
3
+ "version": "0.4.0",
5
4
  "description": "Same as clsx but \"maybe\" better",
5
+ "keywords": [
6
+ "bun",
7
+ "class",
8
+ "classix",
9
+ "classname",
10
+ "classnames",
11
+ "clsx",
12
+ "cn",
13
+ "cx",
14
+ "klsx",
15
+ "kx"
16
+ ],
17
+ "license": "MIT",
6
18
  "author": {
7
19
  "name": "Walter Purcaro",
8
20
  "url": "https://github.com/vuolter"
9
21
  },
10
- "license": "MIT",
11
22
  "repository": {
12
23
  "type": "git",
13
24
  "url": "git+https://github.com/vuolter/klsx.git"
14
25
  },
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
26
  "files": [
29
27
  "dist"
30
28
  ],
29
+ "type": "module",
30
+ "sideEffects": false,
31
31
  "types": "./dist/index.d.ts",
32
32
  "exports": {
33
33
  ".": "./dist/index.js",
34
34
  "./package.json": "./package.json"
35
35
  },
36
36
  "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",
41
- "bench": "bun ./tests/bench",
37
+ "build": "bun typecheck && tsdown",
38
+ "typecheck": "tsc --build --noEmit",
39
+ "format": "oxfmt --write .",
40
+ "lint": "oxlint --fix .",
41
+ "bench": "bun run build && bun ./tests/bench",
42
42
  "postinstall": "npm install --force --ignore-scripts --package-lock-only --silent"
43
43
  },
44
44
  "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.8",
49
- "@typescript/native-preview": "^7.0.0-dev.20260207.1",
50
- "classix": "^2.2.6",
51
- "classnames": "^2.5.1",
52
- "clsx": "^2.1.1",
53
- "eslint": "^10.0.0",
54
- "eslint-config-prettier": "^10.1.8",
55
- "eslint-import-resolver-typescript": "^4.4.4",
56
- "eslint-plugin-import-x": "^4.16.1",
57
- "eslint-plugin-perfectionist": "^5.5.0",
58
- "eslint-plugin-regexp": "^3.0.0",
59
- "eslint-plugin-security": "^3.0.1",
60
- "eslint-plugin-sonarjs": "^3.0.6",
61
- "eslint-plugin-tsdoc": "^0.5.0",
62
- "eslint-plugin-unicorn": "^62.0.0",
63
- "globals": "^17.3.0",
64
- "prettier": "^3.8.1",
65
- "tinybench": "^6.0.0",
66
- "tsdown": "^0.20.3",
67
- "typescript-eslint": "^8.54.0"
45
+ "@socketsecurity/bun-security-scanner": "1.1.3",
46
+ "@types/bun": "1.4.4",
47
+ "classix": "2.2.21",
48
+ "classnames": "2.5.1",
49
+ "clsx": "2.1.1",
50
+ "oxfmt": "0.76.0",
51
+ "oxlint": "1.91.0",
52
+ "oxlint-tsgolint": "7.0.2005",
53
+ "tinybench": "6.2.3",
54
+ "tsdown": "0.23.4",
55
+ "typescript": "7.0.2"
68
56
  },
69
57
  "engines": {
70
58
  "node": ">=18"
71
- },
72
- "sideEffects": false
59
+ }
73
60
  }