Skip to content

Releases: shadcn-ui/cn

cn@0.2.4

Choose a tag to compare

@github-actions github-actions released this 02 Sep 09:26
989c25e

Patch Changes

  • #12 b6caaa3 Thanks @shadcn! - Fix cn build --content brace globs, dot-directory and symlink scanning, and CLI error reporting.

  • #12 b6caaa3 Thanks @shadcn! - Fix a hang and dropped classes in conflict tracking for large custom configs and merges.

  • #12 b6caaa3 Thanks @shadcn! - Match tailwind-merge on Unicode whitespace and twJoin array-like values.

cn@0.2.3

Choose a tag to compare

@github-actions github-actions released this 02 Sep 01:15
b336e09

Patch Changes

  • #10 bf918c2 Thanks @aidenybai! - perf: non-string arguments and JSC hit path.

    • Object and array arguments resolve in place and ride the argument-identity cache instead of taking a full clsx join on every call; the prediction probe runs again over the resolved strings, so cn(base, { active: isActive }) verifies by identity like an all-string call. 0.83× to 0.88× per call on object and nested-array shapes on node, similar on bun.
    • A single array argument takes the argument path (cn([a, b]) is cn(a, b) under clsx flattening), so stable element identities hit: 0.10× on node, 0.15× on bun.
    • An argument-cache bucket holds 256 tuples instead of 8. The cache keys on the first argument, a component's base string at every usage site, so one key routinely carries dozens of tuples; the old cap evicted them faster than the sequence chain could learn them. 64 sites sharing a base: 301 ns to 6.4 ns per call on node, 153 ns to 5.4 ns on bun.
    • A freshly joined string (the arg-cache miss path) goes through the doorkeeper before the whole-string cache. A first sighting merges straight through with no dictionary lookup on a never-seen key (V8 hashes and internalizes those: ~200 ns at 17 chars, ~1.1 µs at 360) and no cache entry anywhere, so a site with a dynamic arbitrary value (translate-x-[${x}px]) stops churning both caches: 0.16× to 0.43× per call on node, 0.14× to 0.58× on bun. The doorkeeper hash now also folds the first and last eight characters, where arbitrary values keep their digits, which cuts cold arbitrary-value renders to 0.83× on node and 0.78× on bun.
    • On JavaScriptCore the whole-string cache is a Map: JSC looks up a string key in a dictionary-mode object in ~21 ns and a fresh key in ~220 ns, where a Map takes 6 and 75 (V8 is the reverse and keeps the dictionary). 8k-string working sets on bun: 25 ns to 6.6 ns per hit, SSR streams 0.92×; 16-string sets pay ~0.5 ns.
    • On JavaScriptCore the whole-string cache hit is a tiny inlinable front with the miss body outlined: recurring single-string calls 0.62× to 0.71× on bun. V8 keeps the single-closure form, where the outlined body measured 1.17× on long strings.

    All-string call shapes are unchanged on both engines. Size gate: 10,602 gz.

cn@0.2.2

Choose a tag to compare

@github-actions github-actions released this 01 Sep 18:50
788fe9b

Patch Changes

  • #6 9018306 Thanks @shadcn! - Fix conflict detection silently failing after 2^31 cache-missing merges in one process.

  • #4 67e2d93 Thanks @shadcn! - Fix broken published types: cn/config pointed at an internal chunk with mangled export names (no defaultConfig/mergeConfigs) and cn/lite typed clsx with zero parameters — runtime was unaffected, and the build now gates on every entry's declarations.

cn@0.2.1

Choose a tag to compare

@github-actions github-actions released this 01 Sep 16:43
44ce907

Patch Changes

  • #2 fafd8cf Thanks @shadcn! - Faster many-argument calls: predictions are now probed in place, so a warm 4+ argument call allocates nothing (~44ns → ~32ns).

cn@0.2.0

Choose a tag to compare

@shadcn shadcn released this 01 Sep 12:21
cn@0.2.0
4b77299

Minor Changes