From ec25777f1de320ac09a2e78a36702dd32aa7bc0d Mon Sep 17 00:00:00 2001 From: Joe Bell <7349341+joe-bell@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:42:25 +0300 Subject: [PATCH] =?UTF-8?q?`cx`=20=E2=86=92=20`clsx`=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: use clsx instead of bespoke class concatenator --- docs/pages/docs/api-reference.mdx | 6 +- docs/pages/docs/index.mdx | 2 + .../class-variance-authority/package.json | 3 + .../src/index.test.ts | 242 ++++++++++++++---- .../class-variance-authority/src/index.ts | 10 +- .../class-variance-authority/src/types.ts | 5 +- packages/cva/README.md | 2 +- packages/cva/package.json | 3 + packages/cva/src/index.test.ts | 242 ++++++++++++++---- packages/cva/src/index.ts | 10 +- packages/cva/src/types.ts | 4 +- pnpm-lock.yaml | 8 + 12 files changed, 409 insertions(+), 128 deletions(-) diff --git a/docs/pages/docs/api-reference.mdx b/docs/pages/docs/api-reference.mdx index ddb73b9..14efd20 100644 --- a/docs/pages/docs/api-reference.mdx +++ b/docs/pages/docs/api-reference.mdx @@ -10,7 +10,7 @@ const component = cva("base", options); ### Parameters -1. `base`: the base class name (`string`, `string[]` or `null`) +1. `base`: the base class name (`string`, `string[]` or other [`clsx` value](https://github.com/lukeed/clsx#input)) 1. `options` _(optional)_ - `variants`: your variants schema - `compoundVariants`: variants based on a combination of previously defined variants @@ -23,7 +23,7 @@ A `cva` component function ## `cx` -Concatenates class names +Concatenates class names (an alias of [`clsx`](https://github.com/lukeed/clsx)) ```ts const className = cx(classes); @@ -31,7 +31,7 @@ const className = cx(classes); ### Parameters -- `classes`: array of classes to be concatenated +- `classes`: array of classes to be concatenated ([see `clsx` usage](https://github.com/lukeed/clsx#input)) ### Returns diff --git a/docs/pages/docs/index.mdx b/docs/pages/docs/index.mdx index 39e79f9..2163c08 100644 --- a/docs/pages/docs/index.mdx +++ b/docs/pages/docs/index.mdx @@ -22,6 +22,8 @@ Creating variants with the "traditional" CSS approach can become an arduous task - [**clb**](https://github.com/crswll/clb) ([Bill Criswell](https://github.com/crswll)) This project originally started out with the intention of merging into the wonderful [`clb`](https://github.com/crswll/clb) library, but after some discussion with Bill, we felt it was best to go down the route of a separate project. I'm so grateful to Bill for sharing his work publicly and for getting me excited about building a type-safe variants API for classes. If you have a moment, please go and [star the project on GitHub](https://github.com/crswll/clb). Thank you Bill! +- [**clsx**](https://github.com/lukeed/clsx) ([Luke Edwards](https://github.com/lukeed)) + Previously, this project surfaced a custom `cx` utility for flattening classes, but it lacked the ability to handle variadic arguments or objects. [clsx](https://github.com/lukeed/clsx) provided those extra features with quite literally zero increase to the bundle size – a no-brainer to switch! - [**Vanilla Extract**](http://vanilla-extract.style) ([Seek](https://github.com/seek-oss)) ## Downloads diff --git a/packages/class-variance-authority/package.json b/packages/class-variance-authority/package.json index 856a3e6..b8cb1c6 100644 --- a/packages/class-variance-authority/package.json +++ b/packages/class-variance-authority/package.json @@ -46,6 +46,9 @@ "test:jest": "jest --config .config/jest.config.ts --coverage", "test:size": "pnpm build && bundlesize -f 'dist/*.js' -s 850B" }, + "dependencies": { + "clsx": "1.2.1" + }, "devDependencies": { "@jest/types": "28.1.1", "@swc/cli": "0.1.57", diff --git a/packages/class-variance-authority/src/index.test.ts b/packages/class-variance-authority/src/index.test.ts index ff413d1..8b57678 100644 --- a/packages/class-variance-authority/src/index.test.ts +++ b/packages/class-variance-authority/src/index.test.ts @@ -5,6 +5,8 @@ describe("cx", () => { describe.each([ [null, ""], [undefined, ""], + [false && "foo", ""], + [true && "foo", "foo"], [["foo", null, "bar", undefined, "baz"], "foo bar baz"], [ [ @@ -26,6 +28,14 @@ describe("cx", () => { ], "foo bar baz qux quux quuz corge grault garply", ], + [ + [ + "foo", + [1 && "bar", { baz: false, bat: null }, ["hello", ["world"]]], + "cya", + ], + "foo bar hello world cya", + ], ])("cx(%o)", (options, expected) => { test(`returns ${expected}`, () => { expect(cx(options)).toBe(expected); @@ -116,8 +126,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -147,7 +164,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -160,8 +180,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -191,7 +218,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -221,9 +251,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -255,7 +287,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -284,9 +319,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -318,7 +355,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -429,8 +469,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -460,7 +507,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -491,8 +541,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -522,7 +579,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -570,9 +630,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -604,7 +666,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -651,9 +716,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -685,7 +752,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -821,8 +891,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -848,7 +925,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -873,8 +953,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -900,7 +987,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -942,9 +1032,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -972,7 +1064,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1013,9 +1108,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1043,7 +1140,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1167,8 +1267,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -1194,7 +1301,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1224,8 +1334,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -1251,7 +1368,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1298,9 +1418,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1328,7 +1450,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1374,9 +1499,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1404,7 +1531,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], diff --git a/packages/class-variance-authority/src/index.ts b/packages/class-variance-authority/src/index.ts index ac21a9d..e69be49 100644 --- a/packages/class-variance-authority/src/index.ts +++ b/packages/class-variance-authority/src/index.ts @@ -1,3 +1,5 @@ +import clsx from "clsx"; + import type { ClassProp, ClassValue, @@ -16,12 +18,10 @@ const falsyToString = (value: T) => /* cx ============================================ */ -export type CxOptions = ClassValue[]; -export type CxReturn = string; +export type CxOptions = Parameters; +export type CxReturn = ReturnType; -export const cx = (...classes: T): CxReturn => - // @ts-ignore - classes.flat(Infinity).filter(Boolean).join(" "); +export const cx = clsx; /* cva ============================================ */ diff --git a/packages/class-variance-authority/src/types.ts b/packages/class-variance-authority/src/types.ts index 1b228d8..0111f2e 100644 --- a/packages/class-variance-authority/src/types.ts +++ b/packages/class-variance-authority/src/types.ts @@ -1,5 +1,8 @@ +import type * as CLSX from "clsx"; + export type ClassPropKey = "class" | "className"; -export type ClassValue = string | null | undefined | ClassValue[]; + +export type ClassValue = CLSX.ClassValue; export type ClassProp = | { diff --git a/packages/cva/README.md b/packages/cva/README.md index 92ecb3c..5ec16d0 100644 --- a/packages/cva/README.md +++ b/packages/cva/README.md @@ -61,7 +61,7 @@ const component = cva(options); ##### Parameters 1. `options` - - `base`: the base class name (`string`, `string[]` or `null`) + - `base`: the base class name (`string`, `string[]` or other [`clsx` value](https://github.com/lukeed/clsx#input)) - `variants`: your variants schema - `compoundVariants`: variants based on a combination of previously defined variants - `defaultVariants`: set default values for previously defined variants. diff --git a/packages/cva/package.json b/packages/cva/package.json index a9597d2..85cb4fe 100644 --- a/packages/cva/package.json +++ b/packages/cva/package.json @@ -46,6 +46,9 @@ "test:jest": "jest --config .config/jest.config.ts --coverage", "test:size": "pnpm build && bundlesize -f 'dist/*.js' -s 880B" }, + "dependencies": { + "clsx": "1.2.1" + }, "devDependencies": { "@jest/types": "28.1.1", "@swc/cli": "0.1.57", diff --git a/packages/cva/src/index.test.ts b/packages/cva/src/index.test.ts index b23efdb..441a0e9 100644 --- a/packages/cva/src/index.test.ts +++ b/packages/cva/src/index.test.ts @@ -5,6 +5,8 @@ describe("cx", () => { describe.each([ [null, ""], [undefined, ""], + [false && "foo", ""], + [true && "foo", "foo"], [["foo", undefined, "bar", undefined, "baz"], "foo bar baz"], [ [ @@ -25,6 +27,14 @@ describe("cx", () => { ], ], "foo bar baz qux quux quuz corge grault garply", + [ + [ + "foo", + [1 && "bar", { baz: false, bat: null }, ["hello", ["world"]]], + "cya", + ], + "foo bar hello world cya", + ], ], ])("cx(%o)", (options, expected) => { test(`returns ${expected}`, () => { @@ -121,8 +131,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -152,7 +169,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -165,8 +185,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -196,7 +223,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -226,9 +256,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -260,7 +292,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -289,9 +324,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -323,7 +360,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, ], }); @@ -433,8 +473,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -464,7 +511,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -493,8 +543,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -524,7 +581,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -570,9 +630,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -604,7 +666,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -649,9 +714,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -683,7 +750,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -817,8 +887,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -844,7 +921,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -867,8 +947,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -894,7 +981,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -934,9 +1024,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -964,7 +1056,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1003,9 +1098,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1033,7 +1130,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1155,8 +1255,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -1182,7 +1289,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: "button--warning-disabled text-black", + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1210,8 +1320,15 @@ describe("cva", () => { "button--secondary bg-white text-gray-800 border-gray-400 hover:bg-gray-100", warning: "button--warning bg-yellow-500 border-transparent hover:bg-yellow-600", - danger: - "button--danger bg-red-500 text-white border-transparent hover:bg-red-600", + danger: [ + "button--danger", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], + "hover:bg-red-600", + ], }, disabled: { true: "button--disabled opacity-050 cursor-not-allowed", @@ -1237,7 +1354,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: "button--warning-disabled text-black", + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1282,9 +1402,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1312,7 +1434,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - class: ["button--warning-disabled", "text-black"], + class: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], @@ -1356,9 +1481,11 @@ describe("cva", () => { ], danger: [ "button--danger", - "bg-red-500", - "text-white", - "border-transparent", + [ + 1 && "bg-red-500", + { baz: false, bat: null }, + ["text-white", ["border-transparent"]], + ], "hover:bg-red-600", ], }, @@ -1386,7 +1513,10 @@ describe("cva", () => { { intent: "warning", disabled: true, - className: ["button--warning-disabled", "text-black"], + className: [ + "button--warning-disabled", + [1 && "text-black", { baz: false, bat: null }], + ], }, { intent: ["warning", "danger"], diff --git a/packages/cva/src/index.ts b/packages/cva/src/index.ts index 24b783b..03da6f7 100644 --- a/packages/cva/src/index.ts +++ b/packages/cva/src/index.ts @@ -1,3 +1,5 @@ +import clsx from "clsx"; + import type { ClassProp, ClassValue, @@ -16,12 +18,10 @@ const falsyToString = (value: T) => /* cx ============================================ */ -export type CxOptions = ClassValue[]; -export type CxReturn = string; +export type CxOptions = Parameters; +export type CxReturn = ReturnType; -export const cx = (...classes: T): CxReturn => - // @ts-ignore - classes.flat(Infinity).filter(Boolean).join(" "); +export const cx = clsx; /* cva ============================================ */ diff --git a/packages/cva/src/types.ts b/packages/cva/src/types.ts index 17878b6..0111f2e 100644 --- a/packages/cva/src/types.ts +++ b/packages/cva/src/types.ts @@ -1,6 +1,8 @@ +import type * as CLSX from "clsx"; + export type ClassPropKey = "class" | "className"; -export type ClassValue = string | null | undefined | ClassValue[]; +export type ClassValue = CLSX.ClassValue; export type ClassProp = | { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7abca91..d57c49a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -203,6 +203,10 @@ importers: version: 1.0.24(typescript@5.0.3) packages/class-variance-authority: + dependencies: + clsx: + specifier: 1.2.1 + version: 1.2.1 devDependencies: '@jest/types': specifier: 28.1.1 @@ -251,6 +255,10 @@ importers: version: 5.0.3 packages/cva: + dependencies: + clsx: + specifier: 1.2.1 + version: 1.2.1 devDependencies: '@jest/types': specifier: 28.1.1