Skip to content

Instantly share code, notes, and snippets.

@andyjessop
Last active March 16, 2023 08:57
Show Gist options
  • Save andyjessop/66c6f6d4481012c5dc6ac5c145a75b47 to your computer and use it in GitHub Desktop.
Save andyjessop/66c6f6d4481012c5dc6ac5c145a75b47 to your computer and use it in GitHub Desktop.
import { cx } from './cx';
describe('classes', () => {
describe('cx', () => {
test('cx should combine class names', () => {
const result = cx('class1', { class2: true }, null, undefined, 'class3');
expect(result).toBe('class1 class2 class3');
});
test('cx should return empty string if no arguments given', () => {
const result = cx();
expect(result).toBe('');
});
test('cx should return empty string if null is provided', () => {
const result = cx(null);
expect(result).toBe('');
});
test('cx should return empty string if undefined is provided', () => {
const result = cx(undefined);
expect(result).toBe('');
});
test('cx should ignore falsy values in object', () => {
const result = cx({ class1: true, class2: false });
expect(result).toBe('class1');
});
test('cx should handle incorrect argument types', () => {
// @ts-expect-error booleans are not a valid argument type
const result = cx('class1', false, 'class2');
expect(result).toBe('class1 class2');
});
test('cx should handle multiple objects', () => {
const result = cx({ class1: true }, { class2: false }, { class3: true });
expect(result).toBe('class1 class3');
});
test('cx should handle multiple falsy values', () => {
// @ts-expect-error booleans are not a valid argument type
const result = cx(false, null, undefined, 0, '');
expect(result).toBe('');
});
});
});
export { cx };
type Arg = string | Record<string, boolean> | null | undefined;
/**
* Conditionally join classNames into a single string
*/
function cx(...args: Arg[]): string {
let str = '';
let i = 0;
let arg: unknown;
let val;
while (i < args.length) {
if ((arg = args[i++])) {
if (typeof arg === 'string') {
val = arg;
} else if (typeof arg === 'object') {
val = cxMap(arg as Record<string, boolean>);
}
if (val) {
if (str) {
str += ' ';
}
str += val;
}
}
}
return str;
}
function cxMap(map: Record<string, boolean>): string {
let str = '';
for (const [key, value] of Object.entries(map)) {
if (value) {
if (str.length) {
str += ' ';
}
str += key;
}
}
return str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment