Comparing version 0.1.1 to 0.2.0
import clsx, { type ClassValue } from 'clsx'; | ||
type ConfigWrapperProps = { | ||
cx: (...inputs: Parameters<typeof clsx>) => ReturnType<typeof clsx>; | ||
}; | ||
type StringToBoolean<T> = T extends 'true' | 'false' ? boolean : T; | ||
@@ -29,4 +32,5 @@ type ClassNameProp = { | ||
export type VariantPropsWithRequired<T extends VariantClassNameFn<ConfigSchema>, K extends keyof VariantProps<T>> = VariantProps<T> & Required<Pick<VariantProps<T>, K>>; | ||
export declare const config: ({ cx }: ConfigWrapperProps) => <T>(base?: ClassValue, variantsConfig?: VariantsConfig<T> | undefined) => VariantClassNameFn<T>; | ||
export declare const cx: typeof clsx; | ||
export declare const cvu: <T>(base?: ClassValue, variantsConfig?: VariantsConfig<T> | undefined) => VariantClassNameFn<T>; | ||
export { clsx as cx }; | ||
export default cvu; |
@@ -1,2 +0,2 @@ | ||
"use strict";var d=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var N=Object.prototype.hasOwnProperty;var P=(e,n)=>{for(var r in n)d(e,r,{get:n[r],enumerable:!0})},k=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of h(n))!N.call(e,a)&&a!==r&&d(e,a,{get:()=>n[a],enumerable:!(t=S(n,a))||t.enumerable});return e};var b=e=>k(d({},"__esModule",{value:!0}),e);var B={};P(B,{cvu:()=>m,cx:()=>u,default:()=>A});module.exports=b(B);function C(e){var n,r,t="";if(typeof e=="string"||typeof e=="number")t+=e;else if(typeof e=="object")if(Array.isArray(e))for(n=0;n<e.length;n++)e[n]&&(r=C(e[n]))&&(t&&(t+=" "),t+=r);else for(n in e)e[n]&&(t&&(t+=" "),t+=n);return t}function j(){for(var e,n,r=0,t="";r<arguments.length;)(e=arguments[r++])&&(n=C(e))&&(t&&(t+=" "),t+=n);return t}var u=j;var V=e=>(e==null?void 0:e.toString())||"",m=(e,n)=>{let{variants:r,defaultVariants:t,compoundVariants:a}=n||{};return(i,g)=>{if(!r)return u(e,g);let p=Object.entries(r).map(([s,o])=>{let l=i==null?void 0:i[s],c=t==null?void 0:t[s];if(l===null)return null;let f=V(l)||V(c);return o==null?void 0:o[f]}),y=i&&Object.fromEntries(Object.entries(i).filter(([,s])=>s!==void 0)),x=a==null?void 0:a.reduce((s,{className:o,...l})=>Object.entries(l).every(([c,f])=>{let T={...t,...y}[c];return Array.isArray(f)&&T!=null?f.includes(T):T===f})?[...s,o]:s,[]);return u(e,p,x,g)}};var A=m; | ||
"use strict";var p=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var j=(e,n)=>{for(var r in n)p(e,r,{get:n[r],enumerable:!0})},R=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of k(n))!b.call(e,a)&&a!==r&&p(e,a,{get:()=>n[a],enumerable:!(t=N(n,a))||t.enumerable});return e};var A=e=>R(p({},"__esModule",{value:!0}),e);var W={};j(W,{config:()=>y,cvu:()=>x,cx:()=>m,default:()=>F});module.exports=A(W);function d(e){var n,r,t="";if(typeof e=="string"||typeof e=="number")t+=e;else if(typeof e=="object")if(Array.isArray(e))for(n=0;n<e.length;n++)e[n]&&(r=d(e[n]))&&(t&&(t+=" "),t+=r);else for(n in e)e[n]&&(t&&(t+=" "),t+=n);return t}function B(){for(var e,n,r=0,t="";r<arguments.length;)(e=arguments[r++])&&(n=d(e))&&(t&&(t+=" "),t+=n);return t}var C=B;var V=e=>(e==null?void 0:e.toString())||"",y=({cx:e})=>(n,r)=>{let{variants:t,defaultVariants:a,compoundVariants:u}=r||{};return(o,T)=>{if(!t)return e(n,T);let S=Object.entries(t).map(([s,i])=>{let l=o==null?void 0:o[s],c=a==null?void 0:a[s];if(l===null)return null;let f=V(l)||V(c);return i==null?void 0:i[f]}),h=o&&Object.fromEntries(Object.entries(o).filter(([,s])=>s!==void 0)),P=u==null?void 0:u.reduce((s,{className:i,...l})=>Object.entries(l).every(([c,f])=>{let g={...a,...h}[c];return Array.isArray(f)&&g!=null?f.includes(g):g===f})?[...s,i]:s,[]);return e(n,S,P,T)}},m=C,x=y({cx:m}),F=x; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "cvu", | ||
"description": "A tiny, performant, utility for constructing variant based CSS class strings.", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"license": "MIT", | ||
@@ -60,7 +60,7 @@ "publishConfig": { | ||
"path": "dist/index.js", | ||
"limit": "800 B" | ||
"limit": "1 kB" | ||
}, | ||
{ | ||
"path": "dist/index.mjs", | ||
"limit": "500 B" | ||
"limit": "600 B" | ||
} | ||
@@ -67,0 +67,0 @@ ], |
212
README.md
<h1 align="center">cvu</h1> | ||
> A tiny, performant, utility for constructing variant based CSS class strings. | ||
<p align="center"> | ||
A tiny, performant, utility for constructing variant based CSS class strings. | ||
</p> | ||
--- | ||
<br /> | ||
@@ -10,2 +12,3 @@ ## Installation | ||
NPM: | ||
```sh | ||
@@ -16,2 +19,3 @@ npm i cvu | ||
Yarn: | ||
```sh | ||
@@ -22,2 +26,3 @@ yarn add cvu | ||
PNPM: | ||
```sh | ||
@@ -43,6 +48,3 @@ pnpm i cvu | ||
"tailwindCSS.experimental.classRegex": [ | ||
[ | ||
"cvu\\s*(?:<[\\s\\S]*?>)?\\s*\\(([^)]*)\\)", | ||
"[\"'`]([^\"'`]*).*?[\"'`]" | ||
] | ||
["cvu\\s*(?:<[\\s\\S]*?>)?\\s*\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] | ||
] | ||
@@ -64,20 +66,19 @@ } | ||
```tsx | ||
import { cvu, type VariantProps } from 'cvu'; | ||
import { twMerge } from 'tailwind-merge'; | ||
import { cvu, type VariantProps } from "cvu"; | ||
import { twMerge } from "tailwind-merge"; | ||
const buttonVariants = cvu( | ||
['your', 'base', 'classes'], | ||
{ | ||
variants: { | ||
intent: { | ||
primary: ['your', 'primary', 'classes'], | ||
}, | ||
const buttonVariants = cvu(["your", "base", "classes"], { | ||
variants: { | ||
intent: { | ||
primary: ["your", "primary", "classes"], | ||
}, | ||
defaultVariants: { | ||
intent: 'primary', | ||
}, | ||
}, | ||
); | ||
defaultVariants: { | ||
intent: "primary", | ||
}, | ||
}); | ||
export const buttonClassNames = (props: VariantProps<typeof buttonVariants>) => { | ||
export const buttonClassNames = ( | ||
props: VariantProps<typeof buttonVariants> | ||
) => { | ||
return twMerge(buttonVariants(props)); | ||
@@ -89,2 +90,18 @@ }; | ||
If you find yourself using `twMerge` a lot, you can create a custom `cvu` function that wraps `twMerge` for you. | ||
<details> | ||
<summary>Example with custom cvu</summary> | ||
```tsx | ||
import { config, cx } from "cvu"; | ||
import { twMerge } from "tailwind-merge"; | ||
export const cvu = config({ | ||
cx: (...inputs) => twMerge(cx(inputs)), | ||
}); | ||
``` | ||
</details> | ||
## Getting Started | ||
@@ -97,11 +114,10 @@ | ||
> **Note** | ||
> | ||
> | ||
> The use of Tailwind CSS here is purely for demonstration purposes. `cvu` is not tied to any specific CSS framework. | ||
```ts | ||
import { cvu } from 'cvu'; | ||
import { cvu } from "cvu"; | ||
const buttonClassnames = cvu( | ||
['font-semibold', 'border', 'rounded'], | ||
["font-semibold", "border", "rounded"], | ||
// --or-- | ||
@@ -113,12 +129,12 @@ // 'font-semibold border rounded' | ||
primary: [ | ||
'bg-blue-500', | ||
'text-white', | ||
'border-transparent', | ||
'hover:bg-blue-600', | ||
"bg-blue-500", | ||
"text-white", | ||
"border-transparent", | ||
"hover:bg-blue-600", | ||
], | ||
secondary: 'bg-white text-gray-800 border-gray-400 hover:bg-gray-100', | ||
secondary: "bg-white text-gray-800 border-gray-400 hover:bg-gray-100", | ||
}, | ||
size: { | ||
sm: 'text-sm py-1 px-2', | ||
md: ['text-base', 'py-2', 'px-4'], | ||
sm: "text-sm py-1 px-2", | ||
md: ["text-base", "py-2", "px-4"], | ||
}, | ||
@@ -128,12 +144,12 @@ }, | ||
{ | ||
intent: 'primary', | ||
size: 'md', | ||
className: 'uppercase', | ||
intent: "primary", | ||
size: "md", | ||
className: "uppercase", | ||
}, | ||
], | ||
defaultVariants: { | ||
intent: 'primary', | ||
size: 'md', | ||
intent: "primary", | ||
size: "md", | ||
}, | ||
}, | ||
} | ||
); | ||
@@ -144,3 +160,3 @@ | ||
buttonClassnames({ intent: 'secondary', size: 'sm' }); | ||
buttonClassnames({ intent: "secondary", size: "sm" }); | ||
// => 'font-semibold border rounded bg-white text-gray-800 border-gray-400 hover:bg-gray-100 text-sm py-1 px-2' | ||
@@ -154,13 +170,13 @@ ``` | ||
```ts | ||
import { cvu } from 'cvu'; | ||
import { cvu } from "cvu"; | ||
const buttonClassnames = cva('…', { | ||
const buttonClassnames = cva("…", { | ||
variants: { | ||
intent: { | ||
primary: '…', | ||
secondary: '…', | ||
primary: "…", | ||
secondary: "…", | ||
}, | ||
size: { | ||
sm: '…', | ||
md: '…', | ||
sm: "…", | ||
md: "…", | ||
}, | ||
@@ -172,6 +188,6 @@ }, | ||
{ | ||
intent: 'primary', | ||
size: 'md', | ||
intent: "primary", | ||
size: "md", | ||
// This is the className that will be applied. | ||
className: '…', | ||
className: "…", | ||
}, | ||
@@ -185,13 +201,13 @@ ], | ||
```ts | ||
import { cvu } from 'cvu'; | ||
import { cvu } from "cvu"; | ||
const buttonClassnames = cva('…', { | ||
const buttonClassnames = cva("…", { | ||
variants: { | ||
intent: { | ||
primary: '…', | ||
secondary: '…', | ||
primary: "…", | ||
secondary: "…", | ||
}, | ||
size: { | ||
sm: '…', | ||
md: '…', | ||
sm: "…", | ||
md: "…", | ||
}, | ||
@@ -205,6 +221,6 @@ }, | ||
{ | ||
intent: ['primary', 'secondary'], | ||
size: 'md', | ||
intent: ["primary", "secondary"], | ||
size: "md", | ||
// This is the className that will be applied. | ||
className: '…', | ||
className: "…", | ||
}, | ||
@@ -222,8 +238,8 @@ ], | ||
```ts | ||
import { cvu } from 'cvu'; | ||
import { cvu } from "cvu"; | ||
const buttonClassnames = cvu('rounded', { | ||
const buttonClassnames = cvu("rounded", { | ||
variants: { | ||
intent: { | ||
primary: 'bg-blue-500', | ||
primary: "bg-blue-500", | ||
}, | ||
@@ -233,6 +249,6 @@ }, | ||
buttonClassnames(undefined, 'm-4'); | ||
buttonClassnames(undefined, "m-4"); | ||
// => 'rounded m-4' | ||
buttonClassnames({ intent: 'primary' }, 'm-4'); | ||
buttonClassnames({ intent: "primary" }, "m-4"); | ||
// => 'rounded bg-blue-500 m-4' | ||
@@ -248,3 +264,3 @@ ``` | ||
```ts | ||
import { cvu, type VariantProps } from 'cvu'; | ||
import { cvu, type VariantProps } from "cvu"; | ||
@@ -260,14 +276,17 @@ type ButtonClassnamesProps = VariantProps<typeof buttonClassnames>; | ||
```ts | ||
import { cvu, type VariantPropsWithRequired } from 'cvu'; | ||
import { cvu, type VariantPropsWithRequired } from "cvu"; | ||
type ButtonClassnamesProps = VariantPropsWithRequired<typeof buttonClassnames, 'intent'>; | ||
const buttonClassnames = cvu('…', { | ||
type ButtonClassnamesProps = VariantPropsWithRequired< | ||
typeof buttonClassnames, | ||
"intent" | ||
>; | ||
const buttonClassnames = cvu("…", { | ||
variants: { | ||
intent: { | ||
primary: '…', | ||
secondary: '…', | ||
primary: "…", | ||
secondary: "…", | ||
}, | ||
size: { | ||
sm: '…', | ||
md: '…', | ||
sm: "…", | ||
md: "…", | ||
}, | ||
@@ -286,5 +305,5 @@ }, | ||
wrapper({}); | ||
// ✅ | ||
wrapper({ intent: 'primary' }); | ||
wrapper({ intent: "primary" }); | ||
``` | ||
@@ -296,3 +315,3 @@ | ||
import { cvu, cx, type VariantProps } from "cvu"; | ||
/** | ||
@@ -303,3 +322,3 @@ * Box | ||
export const boxClassnames = cvu(/* … */); | ||
/** | ||
@@ -310,6 +329,16 @@ * Card | ||
const cardBaseClassnames = cvu(/* … */); | ||
export interface CardClassnamesProps extends BoxClassnamesProps, CardBaseClassnamesProps {} | ||
export const cardClassnames = ({ /* destructured props */ }: CardClassnamesProps = {}) => | ||
cx(boxClassnames({ /* … */ }), cardBaseClassnames({ /* … */ })); | ||
export interface CardClassnamesProps | ||
extends BoxClassnamesProps, | ||
CardBaseClassnamesProps {} | ||
export const cardClassnames = | ||
({}: /* destructured props */ CardClassnamesProps = {}) => | ||
cx( | ||
boxClassnames({ | ||
/* … */ | ||
}), | ||
cardBaseClassnames({ | ||
/* … */ | ||
}) | ||
); | ||
``` | ||
@@ -324,7 +353,19 @@ | ||
```ts | ||
import { cvu } from 'cvu'; | ||
import { cvu } from "cvu"; | ||
const classVariants = cvu('base', variantsConfig); | ||
const classVariants = cvu("base", variantsConfig); | ||
``` | ||
### `config` | ||
Allows you to provide your own underlying `cx` implementation or wrapping logic. | ||
```ts | ||
import { config, cx } from "cvu"; | ||
export const customCvu = config({ | ||
cx: (...inputs) => twMerge(cx(inputs)), | ||
}); | ||
``` | ||
#### Parameters | ||
@@ -334,12 +375,13 @@ | ||
2. `variantsConfig` - (optional) | ||
* `variants` - your variants schema | ||
* `componentVariants` - variants based on a combination of previously defined variants | ||
* `defaultVariants` - set default values for previously defined variants. | ||
_Note: these default values can be removed completely by setting the variant as `null`._ | ||
- `variants` - your variants schema | ||
- `componentVariants` - variants based on a combination of previously defined variants | ||
- `defaultVariants` - set default values for previously defined variants. | ||
_Note: these default values can be removed completely by setting the variant as `null`._ | ||
## Acknowledgements | ||
- [Stitches](https://stitches.dev) | ||
For pioneering the `variants` API movement. | ||
@@ -357,2 +399,2 @@ | ||
[MIT](/LICENSE.md) © [Eric Taylor](https://github.com/erictaylor) | ||
[MIT](/LICENSE.md) © [Eric Taylor](https://github.com/erictaylor) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28707
47
376