Releases: shadcn-ui/cn
Release list
cn@0.2.4
Patch Changes
-
#12
b6caaa3Thanks @shadcn! - Fixcn build --contentbrace globs, dot-directory and symlink scanning, and CLI error reporting. -
#12
b6caaa3Thanks @shadcn! - Fix a hang and dropped classes in conflict tracking for large custom configs and merges. -
#12
b6caaa3Thanks @shadcn! - Match tailwind-merge on Unicode whitespace andtwJoinarray-like values.
cn@0.2.3
Patch Changes
-
#10
bf918c2Thanks @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])iscn(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.
- 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@0.2.2
Patch Changes
-
#6
9018306Thanks @shadcn! - Fix conflict detection silently failing after 2^31 cache-missing merges in one process. -
#4
67e2d93Thanks @shadcn! - Fix broken published types:cn/configpointed at an internal chunk with mangled export names (nodefaultConfig/mergeConfigs) andcn/litetypedclsxwith zero parameters — runtime was unaffected, and the build now gates on every entry's declarations.