cx (classNames)
Tiny isomorphic className joiner - strings, numbers, arrays, and { class: boolean } objects, falsy-skipping. No deps.
// Tiny className joiner (isomorphic, no deps).
export type ClassValue =
| string
| number
| null
| false
| undefined
| Record<string, boolean | null | undefined>
| ClassValue[];
export function cx(...parts: ClassValue[]): string {
const out: string[] = [];
for (const p of parts) {
if (!p) continue;
if (typeof p === "string" || typeof p === "number") out.push(String(p));
else if (Array.isArray(p)) {
const s = cx(...p);
if (s) out.push(s);
} else if (typeof p === "object") {
for (const k in p) if (p[k]) out.push(k);
}
}
return out.join(" ");
}