Cretex

cnx

The cnx function is a utility to dynamically combine string class names based on various input types, such as strings, numbers, objects, arrays, or functions. This function combines various input types and simplifies complex management by producing clean and valid strings. Useful for dynamically managing string classes in JavaScript or TypeScript applications.

Syntax

function cnx(...inputs: cnxValues[]): string;

How cnx works:

  1. Initialization:
    An empty array (classes) is used to store valid strings.

  2. Input Iteration:
    Each item in the ...inputs parameter (spread operator) is processed with the following logic:

  • String or Number:
    Immediately converted to a string and inserted into the array.
  • Array:
    Processed recursively using cnx(...input) to support nested structures.
  • Object:
    Iterate over the keys and values ​​(key-value pairs). If the value is "truthy" (e.g., true), the key (class name) is added to the array.
  • Function:
    The function is called, and the result is processed recursively using cnx.
  • Null, Undefined, or Boolean:
    Ignored, passed without processing.
  1. Output:
    The collected classes are combined into a space-separated string.

Example Usage

// allows receiving Arrays, Objects and Functions
cnx(['', baz, (foo as string) !== 'foo' && bar], { '': !props }, '', () => ({ '' }), undefined, [{ '' }, () => ({ '' })]);

Basic Merging

cnx("hello", "world");
// Output: "hello world"
 
cnx(() => "there", "dynamic");
// Output: "there dynamic"
 
cnx(["extra", 0, false, "bar"]);
// Output: "extra bar"
 
cnx("hello", true && "foo", false && "bar");
// Output: "hello foo"

Complex Merging

cnx(["foo"], ["", 0, false, "bar"], [["baz", [["hello"], "there"]]]);
// Output: "foo bar baz hello there"
 
cnx("foo", [1 && "bar", { baz: false, bat: null }, ["hello", ["world"]]], "cya");
// Output: "foo bar hello world cya"
 
cnx("foo", { primary: true, disabled: false }, ["extra", null, undefined], () => "dynamic");
// Output: "foo primary extra dynamic"
 
cnx([{ color: "red", fontSize: "16px" }, () => ({ backgroundColor: "blue" }), undefined, [{ margin: "10px" }, () => ({ padding: "5px" })]]);
// Output: "color fontSize backgroundColor margin padding"

Ignored Falsy

cnx(Boolean, Object, undefined, null, "", 0, NaN);
// Output: ""

Advantages

  • Makes it easier to manage dynamic CSS classes.
  • Logic wrangling of class merging in code.
  • Useful in frameworks like React, Vue, or Svelte for changing class conditions.

Merge class tailwind-merge

import { cnx, type cnxValues } from "cretex";
import { twMerge } from "tailwind-merge";
 
export function cn(...merge: cnxValues[]): string {
  return twMerge(cnx(...merge));
}
cn("bg-black dark:bg-white font-normal", { "font-medium": true });

IntelliSense

If you are using the vscode editor, enable autocomplete for the tailwindcss class using the following command:

  1. Install the Tailwind CSS IntelliSense Visual Studio Code extension
  2. Add to your settings.json:
"tailwindCSS.experimental.classRegex": [
  ["cnx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
  ["cn\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
  ["merge\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
],
  1. Add config to your eslint.config.js to eslint-plugin-tailwindcss configuration
export default [
  {
    extends: ["prettier", "plugin:tailwindcss/recommended"],
    plugins: ["tailwindcss"],
    ignorePatterns: [],
    rules: {},
    settings: {
      tailwindcss: {
        callees: ["cnx", "cn"],
        config: "tailwind.config.ts"
      }
    },
    overrides: []
  }
];