Skip to content

Commit

Permalink
Improve performance and add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Pingid committed Jun 28, 2023
1 parent 46ef461 commit 0bfb725
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mcn",
"version": "0.0.2",
"version": "0.0.3",
"description": "A tiny utility for conditionally joining classNames together.",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
6 changes: 6 additions & 0 deletions src/cn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { expect, it } from 'vitest'
import { cn } from './index'

it('should conditionally join strings', () => {
expect(cn('one', null, undefined, 'two')).toBe('one two')
expect(cn('one', [true, 'two'], [false, 'three'])).toBe('one two')
expect(cn('one', [false, 'two', 'three'])).toBe('one three')
expect(cn([true, 'two', 'three'])).toBe('two')
expect(cn([false, 'two', 'three'])).toBe('three')
expect(cn({ two: true, three: false })).toBe('two')
expect(cn({ two: true, three: true })).toBe('two three')
expect(cn(null, undefined, 0, 1, 2, {}, NaN)).toBe('')
expect(cn('one', null, undefined, { two: true, three: false })).toBe('one two')
})
25 changes: 17 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@ type Join<T> = T extends [infer I, ...infer R] ? `${I & string} ${Join<R>}` : ''
// -----------------------------------------------------------------
// Join className variants
// -----------------------------------------------------------------
export const cn = <T extends ClassNames[]>(...args: T): Join<{ [K in keyof T]: TypeofClassName<T[K]> }> =>
args.reduce<any>((a, b) => {
if (typeof b === 'string') return (a + ' ' + b).trim()
if (Array.isArray(b)) return cn(a, b[0] ? b[1] : b[2])
if (!b) return a
if (typeof b === 'object') return cn(a, ...(Object.entries(b).map((x) => x.reverse()) as any[]))
return a
}, '')
export const cn: <T extends ClassNames[]>(...args: T) => Join<{ [K in keyof T]: TypeofClassName<T[K]> }> =
function cn() {
let a = ''
for (let i = 0; i < arguments.length; i++) {
const b = arguments[i]
if (typeof b === 'string') a = a + ' ' + b
if (typeof b === 'object' && b !== null) {
if (Array.isArray(b)) a = a + ' ' + ((b[0] ? b[1] : b[2]) || '')
else {
for (let key in b) {
a = a + (b[key] ? ' ' + key : '')
}
}
}
}
return a.trim()
} as any

export default cn

0 comments on commit 0bfb725

Please sign in to comment.