When dealing with an important React project at work, I was manipulating multiple CSS Modules class names with a function I wrote 2 and a half years ago, accepting an object for conditionals.
The early hours of the morning of this last day of the year brought me an idea for a shorter, simpler syntax that works better for imported CSS Modules names:
/**
* Generates the `className` attribute with the given class names.
*
* @example
* cn( 'abc' );
* cn( 'abc', 'def' );
* cn( 'abc', ['def', true] );
*/
export function cn(...items: (string | null | undefined | [string, boolean])[]): string {
let fin = '';
for (let i = 0; i < items.length; ++i) {
const item = items[i];
if (item === null || item === undefined) {
continue;
} else if (typeof item === 'string') {
fin += item + ' ';
} else if (Array.isArray(item) && item.length === 2) {
if (typeof item[0] === 'string') {
if (item[1]) fin += item[0] + ' ';
} else {
throw new Error(`cn() item #${i} is an invalid tuple: ${JSON.stringify(item)}`);
}
} else {
throw new Error(`cn() item #${i} is invalid: ${JSON.stringify(item)}`);
}
}
return fin.length ? fin.substring(0, fin.length - 1) : '';
}
And this new function covers all my current needs.
No comments:
Post a Comment